SDK Reference

Integration reference (canonical SDK doc)

This page is rendered directly from packages/age-verify/docs/INTEGRATION.md so website guidance stays aligned with the SDK source docs.

packages/age-verify/docs/INTEGRATION.md

# Age Verify Integration Guide

This guide covers the current integration flow for `age-verify`.

## Prerequisites

- Active operator account.
- API key generated in portal.
- Billing setup complete (payment method + active billing state).

## Recommended architecture

- Backend owns `AGEVERIFY_API_KEY`.
- Browser does not hold secret API key.
- Browser biometric runtime uses short-lived model access tokens from backend-assisted API calls.

## End-to-end flow

1. Evaluate policy
- `POST /api/v1/policy/evaluate`
- Input context: `operatorId`, `action`, optional route/category/geography.
- Output determines whether verification is required and which method/classification applies.

2. Create verification session
- `POST /api/v1/verification-sessions`
- Required: `operatorId`, `idempotencyKey`.
- Optional: `userId`, `paymentIntentId`, `expiresAt`.

3. Request model access
- `POST /api/v1/verification-sessions/{sessionId}/model-access`
- Returns `modelAccessToken` + `modelBasePath`.

4. Run biometric check (browser SDK)
- `runDefaultBiometricCheck({ modelBasePath, modelAccessToken, ... })`

5. Submit result
- `POST /api/v1/verification-sessions/{sessionId}/biometric-result`
- For checkbox companion UX: `POST /api/v1/verification-sessions/{sessionId}/checkbox-result`
- Canonical response outcome: `passed` | `failed` | `inconclusive`
- Successful fresh outcomes may include a signed decision token for reusable verification.

6. Optional fallback handoff
- `POST /api/v1/fallback/initiate`
- Body: `{ verificationSessionId }`
- Fallback is external-vendor handoff only; no internal fallback verification engine is used.

## Minimal SDK example

```ts
import { createAgeVerifyClient, runDefaultBiometricCheck } from 'age-verify';

const client = createAgeVerifyClient({
  apiBaseUrl: '/api/ageverify-proxy',
});

const session = await client.createVerificationSession({
  operatorId: '11111111-1111-1111-1111-111111111111',
  idempotencyKey: 'idem_1234567890',
  userId: 'user_abc',
});

const access = await client.getModelAccess(session.sessionId);
const biometric = await runDefaultBiometricCheck({
  modelBasePath: access.modelBasePath,
  modelAccessToken: access.modelAccessToken,
});

const result = await client.submitBiometricResult(session.sessionId, {
  outcome: biometric.passed ? 'passed' : 'failed',
  reason: biometric.reason,
  subjectId: biometric.subjectId,
});

// Canonical outcome field: 'passed' | 'failed' | 'inconclusive'
// Use result.outcome for all new integrations.
// The legacy result.passed boolean is retained for backward compatibility but is deprecated.
if (result.outcome === 'passed') {
  // allow access
}

if (result.outcome === 'inconclusive') {
  // route to external fallback as required by policy
  await client.initiateFallback(session.sessionId);
}
```

## Terminology

- Completed verification session: lifecycle completion in `verification_sessions`.
- Successful tokenized outcome: successful result persisted in `decision_tokens`.
- Billable verification: event persisted in `billable_events`.
- API usage telemetry: request event in `api_key_usage_events`.

Do not treat these as interchangeable metrics.

## Error handling guidance

- Reuse `idempotencyKey` when retrying session creation.
- Handle `billing_blocked` as an onboarding/billing-state action item.
- Treat webhook processing as idempotent by event id.
- Treat model access token expiry as recoverable: request fresh model access and retry the biometric step.

## Security checklist

- Keep secret API key backend-only.
- Verify webhook signatures.
- Use HTTPS for all requests.
- Rotate API keys through portal workflows.