Skip to main content

Authentication & SDK Token Generation

AttestID supports two authentication modes, used at different points in your integration:

ModeWho uses itWhat it sendsLifetime
API key + client certificateYour backendX-API-Key + X-Access-Key-Id headers, over a mutual-TLS connectionKey: until revoked or rotated. Certificate: 365 days
SDK tokenWeb and mobile SDK clientsAuthorization: Bearer <sdk_token>10 minutes

API keys are used only for server-to-server calls. Client applications use SDK tokens for every KYC endpoint.


1. API key authentication​

Used for account-management endpoints (/v1/account/*), webhook configuration (/v1/webhooks/*), and to generate SDK tokens (POST /v1/kyc/session).

Example headers:

X-API-Key: sk_live_7d0a...b31f
X-Access-Key-Id: ak_live_9f2c...

Both headers are required. The access_key_id must belong to the same key pair as the api_key; a correct secret with someone else's access key ID is rejected.

Requests with invalid, suspended, expired or revoked credentials are rejected with 401.


2. Mutual TLS: a client certificate is required​

Every request that carries an API key must also present a client certificate issued by AttestID to your company. This applies to every company, for both test and live keys, and there is no way to turn it off. A request with an API key and no valid certificate gets:

{ "detail": "A valid client certificate is required for API-key requests. It is missing, invalid, revoked, expired, or not issued to this account. Issue one in the dashboard under Client Certificates." }

The certificate must be issued to the same company as the API key. A valid certificate from company A with company B's key is rejected.

SDK-token traffic from browsers and phones is not affected. Only your backend needs a certificate.

In short: create a private key and CSR on your server, issue the certificate in the dashboard under Client Certificates, and attach both files to your HTTP client.

→ Client Certificates (mTLS) has the full steps, examples for Node.js, Python, PHP, Java, C# and Go, a test command, renewal, and troubleshooting.


3. SDK token flow​

SDK tokens let browser and mobile apps run KYC without ever holding your API credentials. Your backend generates the token for one specific user.

Step 1: Generate an SDK token from your backend

POST /v1/kyc/session
X-API-Key: sk_live_...
X-Access-Key-Id: ak_live_...
Content-Type: application/json
(+ your client certificate on the TLS connection)
{ "user_id": "user-123" }

Response (201 Created):

{
"sdk_token": "eyJhbGciOi...",
"user_id": "user-123",
"expires_in": 600
}

If you use Node.js, the SDK's createSdkSession() helper makes this call for you, including safe retries:

import { createSdkSession } from '@attestid/sdk';

const session = await createSdkSession(
process.env.ATTESTID_API_URL!,
process.env.ATTESTID_API_KEY!,
process.env.ATTESTID_ACCESS_KEY_ID!,
userId,
{ fetch: fetchWithClientCert }, // a fetch that presents client.crt / client.key
);

Step 2: Return the token to your client app

Your backend returns the sdk_token to your frontend or mobile app, for example as the JSON response of your own /api/attestid-session route (see the SDK guide).

:::warning Resolve the user on your backend Take user_id from your own authenticated session, not from the request body. If your endpoint trusts whatever userId the browser sends, anyone can mint a token for any user. :::

Step 3: The SDK uses the token for KYC requests

Authorization: Bearer <sdk_token>

Every /v1/kyc/* endpoint except /kyc/session requires the SDK token, including /kyc/start, /kyc/complete, the liveness endpoints, and result retrieval. These endpoints don't accept an API key.

SDK token rules​

SDK tokens:

  • Are valid for 10 minutes.
  • Are bound to the user_id given when they were generated. A /kyc/start request with a different user_id is rejected (400), and one user's token can't read another user's verification.
  • Can't be used to create more tokens, manage keys, or change webhooks.

The SDK refreshes the token through your token callback (getSdkToken) about 15 seconds before it expires, so you don't manage expiry yourself.


4. Token generation with the client SDK​

Browser or mobile app​

Give the SDK a getSdkToken callback that calls your backend:

const client = new AttestID({
apiUrl: 'https://api.attestid.brimsage.co.ls',
getSdkToken: (userId) =>
fetch('/api/attestid-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId }),
}).then(r => r.json()),
});

Server mode (Node.js only)​

A backend process can hold the API key directly and let the SDK exchange it for tokens. Pass a fetch that presents your client certificate:

const client = new AttestID({
apiUrl: process.env.ATTESTID_API_URL!,
apiKey: process.env.ATTESTID_API_KEY!,
accessKeyId: process.env.ATTESTID_ACCESS_KEY_ID!,
fetch: fetchWithClientCert,
});

The SDK refuses this configuration anywhere other than a real Node.js process (browser, React Native, edge runtimes) and throws INSECURE_CONFIG, because a bundler would ship the key to every visitor.


Other tokens​

TokenLifetimeUsed for
Company dashboard session8 hoursDashboard login. Not used by the SDK
SDK token10 minutesAll /v1/kyc/* calls from the client

Dashboard and SDK tokens are typed: one kind can't be presented where another is expected.


Summary diagram​

┌─────────────┐ X-API-Key + X-Access-Key-Id ┌──────────────┐
│ Your backend│ + client certificate (mTLS) │ POST /kyc/ │
│ (holds │ ─────────────────────────────────▶│ session │
│ api_key, │ └──────┬───────┘
│ client.key)│ ◀──────────── sdk_token (10 min) ─────────┘
└─────┬───────┘
│ hands sdk_token to client (your own API route)
▼
┌─────────────┐ Authorization: Bearer <sdk_token> ┌──────────────┐
│ Browser / │ ─────────────────────────────────▶ │ /kyc/start │
│ mobile app │ │ liveness │
│ (@attestid/ │ ◀────── signed verification result │ /kyc/complete│
│ sdk) │ └──────────────┘
└─────────────┘