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#
- Construct a core over your instance base URL.
- Sign up a user. The response carries an
accessToken(and arefreshTokenplus the user). - Set the token on the core so subsequent calls are authenticated.
- Create a tenant to scope keys and usage under.
- Create an API key for that tenant. The plaintext key is returned exactly once.
- Record usage against the tenant.
- 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#
| Step | TypeScript method | Python method | Returns |
|---|---|---|---|
| Sign up | auth.signup({ email, password }) | auth.signup(email, password) | access + refresh tokens, user |
| Set token | core.setToken(token) | core.set_token(token) | nothing |
| Create tenant | tenants.create(name) | tenants.create(name) | the tenant |
| Create key | keys.create({ tenantId, scopes }) | keys.create(tenant_id=..., scopes=[...]) | the key plus plainTextKey |
| Record usage | usage.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.