Zig SDK
The passkeybase package provides a Zig client for the PasskeyBase Management API. Manage users, credentials, apps, roles, and enrollment tokens from your Zig backend.
Installation
Fetch the package and add it to your build configuration:
Terminal
zig fetch --save git+https://github.com/passkeybase/passkeybase-zigbuild.zig.zon
# build.zig.zon
.{
.dependencies = .{
.passkeybase = .{
.url = "git+https://github.com/passkeybase/passkeybase-zig",
},
},
}build.zig
# build.zig
const passkeybase = b.dependency("passkeybase", .{});
exe.root_module.addImport("passkeybase", passkeybase.module("passkeybase"));Quick Start
Initialize the client with your Management API key and tenant domain, then make your first API call.
main.zig
const std = @import("std");
const passkeybase = @import("passkeybase");
pub fn main() !void {
var client = try passkeybase.Client.init(.{
.api_key = "YOUR_MANAGEMENT_API_KEY",
.domain = "myapp.auth.ing",
.allocator = std.heap.page_allocator,
});
defer client.deinit();
// List all users
const users = try client.users().list(.{});
defer users.deinit();
for (users.data) |user| {
std.debug.print("{s}: {s}\n", .{ user.id, user.display_name });
}
}User Management
Create User
Create a user
const user = try client.users().create(.{
.external_id = "user_123",
.display_name = "Jane Doe",
});
defer user.deinit();
std.debug.print("Created user: {s}\n", .{user.id});List Users
List users with pagination
// List with pagination
const users = try client.users().list(.{
.page = 1,
.per_page = 20,
});
defer users.deinit();
for (users.data) |user| {
std.debug.print("{s}: {s}\n", .{ user.id, user.display_name });
}
std.debug.print("Total: {d}\n", .{users.pagination.total});Get User
Get a user by ID
const user = try client.users().get("usr_abc123");
defer user.deinit();
std.debug.print("Name: {s}\n", .{user.display_name});
std.debug.print("Passkeys: {d}\n", .{user.passkey_count});
std.debug.print("Last login: {s}\n", .{user.last_login_at});Update User
Update a user
const user = try client.users().update("usr_abc123", .{
.display_name = "Jane Smith",
});
defer user.deinit();
std.debug.print("Updated: {s}\n", .{user.display_name});Delete User
Deletes a user and all their associated passkeys.
Delete a user
try client.users().delete("usr_abc123");Block / Unblock User
Block and unblock
// Block a user (prevents authentication)
try client.users().block("usr_abc123");
// Unblock a user
try client.users().unblock("usr_abc123");Credential Management
List Credentials
List all passkey credentials for a specific user.
List credentials
const credentials = try client.credentials().list("usr_abc123");
defer credentials.deinit();
for (credentials.data) |cred| {
std.debug.print("{s}: {s} ({s})\n", .{
cred.id, cred.device_name, cred.authenticator_type,
});
}Delete Credential
Revoke a specific passkey credential.
Delete a credential
try client.credentials().delete("usr_abc123", "pk_xyz789");Client / App Management
Create App
Create an OAuth app
const app = try client.apps().create(.{
.name = "My Mobile App",
.redirect_uris = &.{"myapp://callback"},
});
defer app.deinit();
std.debug.print("Client ID: {s}\n", .{app.id});Rotate Secret
Rotate client secret
const secret = try client.apps().rotateSecret("pk_live_abc123");
defer secret.deinit();
std.debug.print("New secret: {s}\n", .{secret.client_secret});Role Management
Create Role
Create a role
const role = try client.roles().create(.{
.name = "admin",
.description = "Administrator role",
});
defer role.deinit();
std.debug.print("Role ID: {s}\n", .{role.id});Assign Users
Assign users to a role
try client.roles().assignUser("role_abc123", "usr_abc123");
// List users in a role
const users = try client.roles().listUsers("role_abc123");
defer users.deinit();
for (users.data) |user| {
std.debug.print("{s}: {s}\n", .{ user.id, user.display_name });
}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
const token = try client.enrollmentTokens().create(.{
.external_id = "user_123",
.display_name = "Jane Doe",
.expires_in = 3600,
});
defer token.deinit();
std.debug.print("Token: {s}\n", .{token.token});
std.debug.print("Expires: {s}\n", .{token.expires_at});
// Return this token to your frontend for passkey enrollmentError Handling
API errors are returned as Zig error union types. Use if/elseor switch to handle specific error cases.
Error handling
const std = @import("std");
const passkeybase = @import("passkeybase");
var client = try passkeybase.Client.init(.{
.api_key = "YOUR_MANAGEMENT_API_KEY",
.domain = "myapp.auth.ing",
.allocator = std.heap.page_allocator,
});
defer client.deinit();
const result = client.users().get("usr_nonexistent");
if (result) |user| {
defer user.deinit();
std.debug.print("Found: {s}\n", .{user.display_name});
} else |err| switch (err) {
passkeybase.Error.NotFound => {
std.debug.print("User not found\n", .{});
},
passkeybase.Error.Unauthorized => {
std.debug.print("Invalid API key\n", .{});
},
passkeybase.Error.NetworkError => {
std.debug.print("Network error\n", .{});
},
else => {
std.debug.print("Unexpected error\n", .{});
},
}Configuration Options
Configuration
var client = try passkeybase.Client.init(.{
.api_key = "YOUR_MANAGEMENT_API_KEY", // Required. Management API key.
.domain = "myapp.auth.ing", // Required. Your tenant domain.
.allocator = std.heap.page_allocator, // Required. Memory allocator.
.timeout_ms = 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.
});
defer client.deinit();| Option | Type | Required | Description |
|---|---|---|---|
api_key | []const u8 | Yes | Your Management API key from the dashboard. |
domain | []const u8 | Yes | Your tenant domain (e.g., myapp.auth.ing). |
allocator | std.mem.Allocator | Yes | Memory allocator for HTTP and JSON parsing. |
timeout_ms | u32 | No | Request timeout in milliseconds. Default: 10_000. |
max_retries | u32 | No | Maximum retry attempts. Default: 2. |
base_url | []const u8 | No | Override the API base URL. |