PasskeyBase

Elixir SDK

The :passkeybase package provides an Elixir client for the PasskeyBase Management API. Manage users, credentials, apps, roles, and enrollment tokens from your Elixir backend.


Installation

Add to your mix.exs dependencies:

mix.exs
# mix.exs
defp deps do
  [
    {:passkeybase, "~> 1.0"}
  ]
end

Then run mix deps.get to install.


Quick Start

Initialize the client with your Management API key and tenant domain, then make your first API call.

lib/my_app.ex
# Configure the client
client = PasskeyBase.client(
  api_key: "YOUR_MANAGEMENT_API_KEY",
  domain: "myapp.auth.ing"
)

# List all users
{:ok, users} = PasskeyBase.Users.list(client)
Enum.each(users.data, fn user ->
  IO.puts("#{user.id}: #{user.display_name}")
end)

User Management

Create User

Create a user
{:ok, user} = PasskeyBase.Users.create(client, %{
  external_id: "user_123",
  display_name: "Jane Doe"
})
IO.puts("Created user: #{user.id}")

List Users

List users with pagination
# List with pagination
{:ok, users} = PasskeyBase.Users.list(client, page: 1, per_page: 20)

Enum.each(users.data, fn user ->
  IO.puts("#{user.id}: #{user.display_name}")
end)

IO.puts("Total: #{users.pagination.total}")

Get User

Get a user by ID
{:ok, user} = PasskeyBase.Users.get(client, "usr_abc123")
IO.puts("Name: #{user.display_name}")
IO.puts("Passkeys: #{user.passkey_count}")
IO.puts("Last login: #{user.last_login_at}")

Update User

Update a user
{:ok, user} = PasskeyBase.Users.update(client, "usr_abc123", %{
  display_name: "Jane Smith"
})
IO.puts("Updated: #{user.display_name}")

Delete User

Deletes a user and all their associated passkeys.

Delete a user
:ok = PasskeyBase.Users.delete(client, "usr_abc123")

Block / Unblock User

Block and unblock
# Block a user (prevents authentication)
:ok = PasskeyBase.Users.block(client, "usr_abc123")

# Unblock a user
:ok = PasskeyBase.Users.unblock(client, "usr_abc123")

Credential Management

List Credentials

List all passkey credentials for a specific user.

List credentials
{:ok, credentials} = PasskeyBase.Credentials.list(client, "usr_abc123")
Enum.each(credentials.data, fn cred ->
  IO.puts("#{cred.id}: #{cred.device_name} (#{cred.authenticator_type})")
end)

Delete Credential

Revoke a specific passkey credential.

Delete a credential
:ok = PasskeyBase.Credentials.delete(client, "usr_abc123", "pk_xyz789")

Client / App Management

Create App

Create an OAuth app
{:ok, app} = PasskeyBase.Apps.create(client, %{
  name: "My Mobile App",
  redirect_uris: ["myapp://callback"]
})
IO.puts("Client ID: #{app.id}")

Rotate Secret

Rotate client secret
{:ok, secret} = PasskeyBase.Apps.rotate_secret(client, "pk_live_abc123")
IO.puts("New secret: #{secret.client_secret}")

Role Management

Create Role

Create a role
{:ok, role} = PasskeyBase.Roles.create(client, %{
  name: "admin",
  description: "Administrator role"
})
IO.puts("Role ID: #{role.id}")

Assign Users

Assign users to a role
:ok = PasskeyBase.Roles.assign_user(client, "role_abc123", "usr_abc123")

# List users in a role
{:ok, users} = PasskeyBase.Roles.list_users(client, "role_abc123")
Enum.each(users.data, fn user ->
  IO.puts("#{user.id}: #{user.display_name}")
end)

Enrollment Tokens

Generate a one-time token for enrolling a passkey for an existing user. See the Enrollment guide for the full flow.

Create enrollment token
{:ok, token} = PasskeyBase.EnrollmentTokens.create(client, %{
  external_id: "user_123",
  display_name: "Jane Doe",
  expires_in: 3600
})
IO.puts("Token: #{token.token}")
IO.puts("Expires: #{token.expires_at}")

# Return this token to your frontend for passkey enrollment

Error Handling

API errors are returned as {:error, %PasskeyBase.Error{}} tuples. Use pattern matching to handle different error types.

Error handling
client = PasskeyBase.client(
  api_key: "YOUR_MANAGEMENT_API_KEY",
  domain: "myapp.auth.ing"
)

case PasskeyBase.Users.get(client, "usr_nonexistent") do
  {:ok, user} ->
    IO.puts("Found: #{user.display_name}")

  {:error, %PasskeyBase.Error{} = e} ->
    IO.puts("Error: #{e.error}")       # "not_found"
    IO.puts("Message: #{e.message}")   # "User not found"
    IO.puts("Status: #{e.status}")     # 404
end

Configuration Options

Configuration
client = PasskeyBase.client(
  api_key: "YOUR_MANAGEMENT_API_KEY",    # Required. Management API key.
  domain: "myapp.auth.ing",             # Required. Your tenant domain.
  timeout: 30_000,                      # Optional. Request timeout in ms. Default: 10_000.
  max_retries: 3,                       # Optional. Max retry attempts. Default: 2.
  base_url: "https://custom.url"        # Optional. Override API base URL.
)
OptionTypeRequiredDescription
api_keyString.t()YesYour Management API key from the dashboard.
domainString.t()YesYour tenant domain (e.g., myapp.auth.ing).
timeoutinteger()NoRequest timeout in milliseconds. Default: 10_000.
max_retriesinteger()NoMaximum retry attempts. Default: 2.
base_urlString.t()NoOverride the API base URL.