🛡️Gatekeeper/ SDKs

This walks through one complete flow in both SDKs: sign up a user, apply the returned access token to the client, create a tenant, mint an API key, record a unit of metered usage, and handle a failure with GatekeeperError.

The full flow#

  1. Construct a core over your instance base URL.
  2. Sign up a user. The response carries an accessToken (and a refreshToken plus the user).
  3. Set the token on the core so subsequent calls are authenticated.
  4. Create a tenant to scope keys and usage under.
  5. Create an API key for that tenant. The plaintext key is returned exactly once.
  6. Record usage against the tenant.
  7. Handle errors with GatekeeperError.
import {
  GatekeeperCore,
  AuthService,
  TenantsService,
  KeysService,
  UsageService,
  GatekeeperError,
} from '@orkait/sdk';
 
const core = new GatekeeperCore({ baseUrl: 'http://localhost:8787' });
 
try {
  // 1 + 2. Sign up - returns access + refresh tokens and the user.
  const auth = new AuthService(core);
  const { accessToken } = await auth.signup({
    email: 'founder@example.com',
    password: 'hunter2pass',
    name: 'Founder',
  });
 
  // 3. Apply the token so the next calls are authenticated.
  core.setToken(accessToken);
 
  // 4. Create a tenant (positional name).
  const tenants = new TenantsService(core);
  const tenant = await tenants.create('Acme Inc');
 
  // 5. Create an API key for the tenant. plainTextKey is shown once.
  const keys = new KeysService(core);
  const { apiKey, plainTextKey } = await keys.create({
    tenantId: tenant.id,
    name: 'server-key',
    scopes: ['read', 'write'],
  });
  console.log('store this now, it is not retrievable later:', plainTextKey);
 
  // 6. Record a unit of metered usage against the tenant.
  const usage = new UsageService(core);
  const event = await usage.record({
    tenantId: tenant.id,
    apiKeyId: apiKey.id,
    service: 'inference',
    action: 'completion',
    quantity: 1,
  });
  console.log('recorded usage event', event.id);
} catch (err) {
  // 7. Every non-ok response throws GatekeeperError.
  if (err instanceof GatekeeperError) {
    console.error(`Gatekeeper error ${err.status} (${err.code ?? 'no-code'}): ${err.message}`);
    if (err.status === 429 && err.retryAfter !== undefined) {
      console.error(`rate limited, retry after ${err.retryAfter}s`);
    }
  } else {
    throw err;
  }
}

What you get back#

StepTypeScript methodPython methodReturns
Sign upauth.signup({ email, password })auth.signup(email, password)access + refresh tokens, user
Set tokencore.setToken(token)core.set_token(token)nothing
Create tenanttenants.create(name)tenants.create(name)the tenant
Create keykeys.create({ tenantId, scopes })keys.create(tenant_id=..., scopes=[...])the key plus plainTextKey
Record usageusage.record({ tenantId, service, action })usage.record(tenant_id, service, action)the usage event

Error handling#

Every non-ok response surfaces as a single error type with a numeric .status, an optional .code, and .retryAfter / .retry_after populated from the Retry-After header on 429 responses.

import { GatekeeperError } from '@orkait/sdk';
 
try {
  await auth.login({ email: 'nobody@example.com', password: 'wrong' });
} catch (err) {
  if (err instanceof GatekeeperError) {
    console.error(err.status, err.code, err.message);
  }
}

Continue to Authentication for the full token, API key, MFA, and OAuth model.