Management SDK
The Management SDK provides tools for managing client keys, webhooks, and invitations in your Fluxbase instance. These features allow you to:
- Client Keys: Create and manage client keys for service-to-service authentication
- Webhooks: Set up event-driven integrations with external services
- Invitations: Invite new users to join your dashboard
Installation
Section titled “Installation”The management module is included with the Fluxbase SDK:
npm install @fluxbase/sdkQuick Start
Section titled “Quick Start”import { createClient } from "@fluxbase/sdk";
const client = createClient( "http://localhost:8080", "your-api-key");
// Authenticate firstawait client.auth.login({ email: "user@example.com", password: "password",});
// Create a client keyconst { client_key, key } = await client.management.clientKeys.create({ name: "Production Service", scopes: ["read:users", "write:users"], rate_limit_per_minute: 100,});
// Create a webhookconst webhook = await client.management.webhooks.create({ url: "https://myapp.com/webhook", events: ["user.created", "user.updated"],});
// Create an invitation (admin only)await client.admin.login({ email: "admin@example.com", password: "admin-password",});
const invitation = await client.management.invitations.create({ email: "newuser@example.com", role: "dashboard_user",});Client Keys Management
Section titled “Client Keys Management”Client keys provide a secure way for external services to authenticate with your Fluxbase instance without using user credentials.
Create Client Key
Section titled “Create Client Key”Create a new client key with specific scopes and rate limits.
const { client_key, key } = await client.management.clientKeys.create({ name: "Production Service", description: "Client key for production microservice", scopes: ["read:users", "write:users", "read:products"], rate_limit_per_minute: 100, expires_at: "2025-12-31T23:59:59Z", // Optional expiration});
// ⚠️ IMPORTANT: Store the full key securely - it won't be shown againconsole.log("Client Key:", key); // fbk_abc123def456...console.log("Key Prefix:", client_key.key_prefix); // fbk_abcParameters:
name(required): Human-readable name for the client keydescription(optional): Detailed descriptionscopes(required): Array of permission scopesrate_limit_per_minute(required): Maximum requests per minuteexpires_at(optional): ISO 8601 expiration date
Returns: Object containing:
client_key: Client key metadatakey: Full client key value (only returned once)
List Client Keys
Section titled “List Client Keys”Retrieve all client keys for the authenticated user.
const { client_keys, total } = await client.management.clientKeys.list();
client_keys.forEach((key) => { console.log(`${key.name}: ${key.key_prefix}...`); console.log(` Scopes: ${key.scopes.join(", ")}`); console.log(` Rate Limit: ${key.rate_limit_per_minute}/min`); console.log(` Last Used: ${key.last_used_at || "Never"}`);
if (key.revoked_at) { console.log(` Status: REVOKED`); } else if (key.expires_at && new Date(key.expires_at) < new Date()) { console.log(` Status: EXPIRED`); } else { console.log(` Status: ACTIVE`); }});Get Client Key
Section titled “Get Client Key”Retrieve details for a specific client key.
const clientKey = await client.management.clientKeys.get("key-uuid");
console.log("Name:", clientKey.name);console.log("Scopes:", clientKey.scopes);console.log("Created:", clientKey.created_at);console.log("Last Used:", clientKey.last_used_at);Update Client Key
Section titled “Update Client Key”Update client key properties (name, description, scopes, rate limit).
const updated = await client.management.clientKeys.update("key-uuid", { name: "Updated Service Name", description: "New description", scopes: ["read:users", "write:users", "read:orders"], rate_limit_per_minute: 200,});
console.log("Updated:", updated.name);Note: Updating scopes immediately affects client key permissions. Update rate limits to handle increased/decreased traffic.
Revoke Client Key
Section titled “Revoke Client Key”Revoke a client key to prevent further use while keeping it for audit logs.
await client.management.clientKeys.revoke("key-uuid");console.log("Client key revoked successfully");Difference between Revoke and Delete:
- Revoke: Disables the key but keeps it in the database for audit trails
- Delete: Permanently removes the key from the system
Delete Client Key
Section titled “Delete Client Key”Permanently delete a client key.
await client.management.clientKeys.delete("key-uuid");console.log("Client key deleted successfully");⚠️ Warning: This action cannot be undone. Consider revoking instead of deleting for audit purposes.
Webhooks Management
Section titled “Webhooks Management”Webhooks allow you to receive real-time notifications when events occur in your Fluxbase instance.
Create Webhook
Section titled “Create Webhook”Set up a new webhook endpoint to receive event notifications.
const webhook = await client.management.webhooks.create({ url: "https://myapp.com/webhook", events: [ "user.created", "user.updated", "user.deleted", "auth.login", "auth.logout", ], description: "User and auth events webhook", secret: "my-webhook-secret-key", // Used to sign webhook payloads});
console.log("Webhook created:", webhook.id);console.log("URL:", webhook.url);console.log("Events:", webhook.events);Parameters:
url(required): HTTPS endpoint to receive webhook POST requestsevents(required): Array of event types to subscribe todescription(optional): Human-readable descriptionsecret(optional): Secret key for HMAC signature verification
Common Event Types:
user.created- New user registereduser.updated- User profile updateduser.deleted- User account deletedauth.login- User logged inauth.logout- User logged outpassword.reset- Password reset initiatedemail.verified- Email address verified
List Webhooks
Section titled “List Webhooks”Retrieve all webhooks for the authenticated user.
const { webhooks, total } = await client.management.webhooks.list();
webhooks.forEach((webhook) => { console.log(`${webhook.url} (${webhook.is_active ? "active" : "inactive"})`); console.log(` Events: ${webhook.events.join(", ")}`); console.log(` Created: ${webhook.created_at}`);});Get Webhook
Section titled “Get Webhook”Retrieve details for a specific webhook.
const webhook = await client.management.webhooks.get("webhook-uuid");
console.log("URL:", webhook.url);console.log("Events:", webhook.events);console.log("Active:", webhook.is_active);console.log("Description:", webhook.description);Update Webhook
Section titled “Update Webhook”Modify webhook configuration.
const updated = await client.management.webhooks.update("webhook-uuid", { url: "https://myapp.com/new-webhook-endpoint", events: ["user.created", "user.deleted"], // Changed event list is_active: false, // Temporarily disable});
console.log("Webhook updated");Common Use Cases:
- Update the webhook URL when your endpoint changes
- Add/remove event subscriptions
- Temporarily disable webhooks during maintenance
Delete Webhook
Section titled “Delete Webhook”Permanently remove a webhook.
await client.management.webhooks.delete("webhook-uuid");console.log("Webhook deleted");Test Webhook
Section titled “Test Webhook”Send a test event to verify your webhook endpoint is working correctly.
const result = await client.management.webhooks.test("webhook-uuid");
if (result.success) { console.log("✅ Webhook test successful"); console.log("Status Code:", result.status_code); console.log("Response:", result.response_body);} else { console.error("❌ Webhook test failed"); console.error("Error:", result.error);}Test Payload Structure:
{ "event": "webhook.test", "timestamp": "2024-01-26T10:00:00Z", "data": { "test": true, "webhook_id": "webhook-uuid" }}List Webhook Deliveries
Section titled “List Webhook Deliveries”View the delivery history for a webhook, including successes and failures.
const { deliveries } = await client.management.webhooks.listDeliveries( "webhook-uuid", 100,);
deliveries.forEach((delivery) => { console.log(`Event: ${delivery.event}`); console.log(`Status: ${delivery.status_code}`); console.log(`Created: ${delivery.created_at}`); console.log(`Delivered: ${delivery.delivered_at || "Pending"}`);
if (delivery.error) { console.error(`Error: ${delivery.error}`); }
console.log("---");});Parameters:
webhookId: Webhook UUIDlimit: Maximum deliveries to return (default: 50, max: 1000)
Webhook Payload Format
Section titled “Webhook Payload Format”When an event occurs, Fluxbase sends a POST request to your webhook URL with the following structure:
interface WebhookPayload { event: string; // Event type (e.g., "user.created") timestamp: string; // ISO 8601 timestamp data: { // Event-specific data user_id?: string; email?: string; // ... more fields }; signature: string; // HMAC-SHA256 signature (if secret provided)}Verifying Webhook Signatures
Section titled “Verifying Webhook Signatures”If you provided a secret when creating the webhook, verify incoming webhook payloads:
import crypto from "crypto";
function verifyWebhookSignature( payload: string, signature: string, secret: string,): boolean { const expectedSignature = crypto .createHmac("sha256", secret) .update(payload) .digest("hex");
return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature), );}
// In your webhook endpoint:app.post("/webhook", (req, res) => { const signature = req.headers["x-fluxbase-signature"]; const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) { return res.status(401).json({ error: "Invalid signature" }); }
// Process the webhook console.log("Event:", req.body.event); console.log("Data:", req.body.data);
res.json({ received: true });});Invitations Management
Section titled “Invitations Management”Invitations allow administrators to invite new users to join the dashboard. The invitation system supports role-based access and automatic email notifications.
Create Invitation
Section titled “Create Invitation”Create a new invitation for a user (admin only).
// Must be authenticated as adminawait client.admin.login({ email: "admin@example.com", password: "admin-password",});
const invitation = await client.management.invitations.create({ email: "newuser@example.com", role: "dashboard_user", // or 'dashboard_admin' expiry_duration: 604800, // 7 days in seconds (default)});
console.log("Invitation created");console.log("Invite Link:", invitation.invite_link);console.log("Email Sent:", invitation.email_sent);
// Share the invite link with the user// They'll use this link to set up their accountParameters:
email(required): Email address to inviterole(required): Either'dashboard_user'or'dashboard_admin'expiry_duration(optional): Duration in seconds (default: 604800 = 7 days)
Roles:
dashboard_user: Can access the dashboard with limited permissionsdashboard_admin: Full admin access to instance management
List Invitations
Section titled “List Invitations”Retrieve all invitations (admin only).
// List only pending invitationsconst { invitations } = await client.management.invitations.list({ include_accepted: false, include_expired: false,});
invitations.forEach((invite) => { console.log(`${invite.email} - ${invite.role}`); console.log(` Expires: ${invite.expires_at}`); console.log(` Status: ${invite.accepted_at ? "Accepted" : "Pending"}`);});
// List all invitations including accepted and expiredconst all = await client.management.invitations.list({ include_accepted: true, include_expired: true,});
console.log(`Total invitations: ${all.invitations.length}`);Filter Options:
include_accepted: Include invitations that have been accepted (default: false)include_expired: Include expired invitations (default: false)
Validate Invitation
Section titled “Validate Invitation”Check if an invitation token is valid (public endpoint - no authentication required).
const result = await client.management.invitations.validate("invitation-token");
if (result.valid) { console.log("✅ Valid invitation"); console.log("Email:", result.invitation?.email); console.log("Role:", result.invitation?.role); console.log("Expires:", result.invitation?.expires_at);} else { console.error("❌ Invalid invitation:", result.error); // Possible errors: // - "Invitation has expired" // - "Invitation has already been accepted" // - "Invitation not found"}Accept Invitation
Section titled “Accept Invitation”Accept an invitation and create a new user account (public endpoint).
const response = await client.management.invitations.accept( "invitation-token", { password: "SecurePassword123!", name: "John Doe", },);
console.log("✅ Account created successfully");console.log("User:", response.user.email);console.log("Name:", response.user.name);console.log("Role:", response.user.role);
// Store authentication tokenslocalStorage.setItem("access_token", response.access_token);localStorage.setItem("refresh_token", response.refresh_token);
// User is now logged in and can access the dashboardParameters:
token: Invitation token from the invite linkpassword: New user’s password (minimum 12 characters)name: User’s display name (minimum 2 characters)
Returns: Authentication response with:
user: Created user detailsaccess_token: JWT access tokenrefresh_token: JWT refresh tokenexpires_in: Token expiration time in seconds
Revoke Invitation
Section titled “Revoke Invitation”Cancel an invitation (admin only).
await client.management.invitations.revoke("invitation-token");console.log("Invitation revoked");Use Cases:
- User no longer needs access
- Invitation was sent to wrong email
- Security concerns with pending invitations
Complete Examples
Section titled “Complete Examples”Client Key Management Dashboard
Section titled “Client Key Management Dashboard”import { createClient } from "@fluxbase/sdk";
const client = createClient( "http://localhost:8080", "your-client-key");
async function setupClientKeyDashboard() { // Authenticate await client.auth.login({ email: "user@example.com", password: "password", });
// List existing keys const { client_keys } = await client.management.clientKeys.list();
console.log("=== Client Keys ==="); client_keys.forEach((key) => { const status = key.revoked_at ? "🔴 REVOKED" : key.expires_at && new Date(key.expires_at) < new Date() ? "🟡 EXPIRED" : "🟢 ACTIVE";
console.log(`${status} ${key.name}`); console.log(` Prefix: ${key.key_prefix}`); console.log(` Rate Limit: ${key.rate_limit_per_minute}/min`); console.log(` Last Used: ${key.last_used_at || "Never"}`); });
// Create a new key const { client_key, key } = await client.management.clientKeys.create({ name: "New Integration", scopes: ["read:users"], rate_limit_per_minute: 60, });
console.log("\n✅ New Client Key Created"); console.log("Key:", key); console.log("Save this key securely - it won't be shown again!");
// Update an existing key const updated = await client.management.clientKeys.update(client_keys[0].id, { rate_limit_per_minute: 120, });
console.log( `\n✅ Updated ${updated.name} rate limit to ${updated.rate_limit_per_minute}/min`, );}
setupClientKeyDashboard().catch(console.error);Webhook Event Handler
Section titled “Webhook Event Handler”import express from "express";import crypto from "crypto";import { createClient } from "@fluxbase/sdk";
const app = express();const client = createClient( "http://localhost:8080", "your-api-key");const WEBHOOK_SECRET = "your-webhook-secret";
// Verify webhook signaturefunction verifySignature(payload: string, signature: string): boolean { const expectedSignature = crypto .createHmac("sha256", WEBHOOK_SECRET) .update(payload) .digest("hex");
return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature), );}
// Webhook endpointapp.post("/webhook", express.json(), (req, res) => { const signature = req.headers["x-fluxbase-signature"] as string; const payload = JSON.stringify(req.body);
// Verify signature if (!verifySignature(payload, signature)) { return res.status(401).json({ error: "Invalid signature" }); }
// Process event const { event, timestamp, data } = req.body;
console.log(`Received event: ${event} at ${timestamp}`);
switch (event) { case "user.created": console.log("New user registered:", data.email); // Send welcome email, create customer profile, etc. break;
case "user.deleted": console.log("User deleted:", data.user_id); // Clean up related data, cancel subscriptions, etc. break;
case "auth.login": console.log("User logged in:", data.email); // Track login analytics, send notification, etc. break;
default: console.log("Unknown event:", event); }
res.json({ received: true });});
// Set up webhookasync function setupWebhook() { await client.auth.login({ email: "user@example.com", password: "password", });
const webhook = await client.management.webhooks.create({ url: "https://myapp.com/webhook", events: ["user.created", "user.deleted", "auth.login"], secret: WEBHOOK_SECRET, });
console.log("Webhook created:", webhook.id);
// Test the webhook const testResult = await client.management.webhooks.test(webhook.id);
if (testResult.success) { console.log("✅ Webhook test successful"); } else { console.error("❌ Webhook test failed:", testResult.error); }}
app.listen(3000, () => { console.log("Server running on port 3000"); setupWebhook().catch(console.error);});Invitation Management System
Section titled “Invitation Management System”import { createClient } from "@fluxbase/sdk";
const client = createClient( "http://localhost:8080", "your-api-key");
async function manageInvitations() { // Admin login await client.admin.login({ email: "admin@example.com", password: "admin-password", });
// Bulk invite multiple users const usersToInvite = [ { email: "user1@example.com", role: "dashboard_user" as const }, { email: "user2@example.com", role: "dashboard_user" as const }, { email: "admin2@example.com", role: "dashboard_admin" as const }, ];
console.log("Creating invitations...");
for (const user of usersToInvite) { const invitation = await client.management.invitations.create({ email: user.email, role: user.role, expiry_duration: 604800, // 7 days });
console.log(`✅ Invited ${user.email}`); console.log(` Link: ${invitation.invite_link}`);
// In production, send this link via email }
// Check pending invitations const { invitations } = await client.management.invitations.list({ include_accepted: false, include_expired: false, });
console.log(`\n${invitations.length} pending invitations:`); invitations.forEach((invite) => { const expiresIn = Math.floor( (new Date(invite.expires_at).getTime() - Date.now()) / (1000 * 60 * 60 * 24), ); console.log(`- ${invite.email} (expires in ${expiresIn} days)`); });
// Revoke old invitations const oldInvitations = invitations.filter((invite) => { const daysOld = Math.floor( (Date.now() - new Date(invite.created_at).getTime()) / (1000 * 60 * 60 * 24), ); return daysOld > 5; });
if (oldInvitations.length > 0) { console.log(`\nRevoking ${oldInvitations.length} old invitations...`); for (const invite of oldInvitations) { await client.management.invitations.revoke(invite.token!); console.log(`✅ Revoked invitation for ${invite.email}`); } }}
manageInvitations().catch(console.error);Error Handling
Section titled “Error Handling”All management methods may throw errors. Always wrap calls in try-catch blocks:
try { const { client_key, key } = await client.management.clientKeys.create({ name: "New Key", scopes: ["read:users"], rate_limit_per_minute: 100, });
console.log("Client key created:", key);} catch (error) { if (error.message.includes("unauthorized")) { console.error("You must be logged in to create client keys"); } else if (error.message.includes("rate_limit")) { console.error("Invalid rate limit value"); } else { console.error("Failed to create client key:", error.message); }}Common Error Scenarios:
-
Authentication Required
// Error: User not authenticated// Solution: Log in before calling management methodsawait client.auth.login({ email, password }); -
Admin Permission Required
// Error: Admin role required// Solution: Use admin credentials for invitation managementawait client.admin.login({ email: adminEmail, password: adminPassword }); -
Invalid Invitation Token
const result = await client.management.invitations.validate("invalid-token");if (!result.valid) {console.error(result.error); // "Invitation not found"} -
Webhook Delivery Failure
const result = await client.management.webhooks.test("webhook-id");if (!result.success) {console.error("Webhook failed:", result.error);// Common issues: invalid URL, timeout, SSL certificate errors}
Best Practices
Section titled “Best Practices”Client Keys
Section titled “Client Keys”- Store keys securely: Never commit client keys to version control
- Rotate regularly: Create new keys and revoke old ones periodically
- Use specific scopes: Grant minimal permissions needed
- Monitor usage: Check
last_used_atto identify unused keys - Set expiration: Use
expires_atfor temporary integrations
Webhooks
Section titled “Webhooks”- Validate signatures: Always verify webhook signatures to prevent spoofing
- Handle retries: Implement idempotent handlers (same event may be delivered multiple times)
- Respond quickly: Return 200 OK within 5 seconds to avoid timeouts
- Process async: Queue events for background processing
- Monitor deliveries: Check delivery history for failures
Invitations
Section titled “Invitations”- Use appropriate roles: Grant minimal necessary permissions
- Set reasonable expiry: Default 7 days is usually sufficient
- Track invitations: Regularly clean up expired/unused invitations
- Secure invite links: Treat invitation tokens as sensitive data
- Revoke when needed: Cancel invitations if user no longer needs access
TypeScript Types
Section titled “TypeScript Types”All management types are fully typed for excellent IDE support:
import type { // Client Keys ClientKey, CreateClientKeyRequest, CreateClientKeyResponse,
// Webhooks Webhook, CreateWebhookRequest, WebhookDelivery, TestWebhookResponse,
// Invitations Invitation, CreateInvitationRequest, ValidateInvitationResponse, AcceptInvitationResponse,} from "@fluxbase/sdk";Next Steps
Section titled “Next Steps”- Admin SDK - Instance administration
- OAuth - OAuth authentication
- Advanced Features - Advanced SDK features