> Toden documentation. For the full index fetch /llms.txt. Every page is available as Markdown by appending .md to its URL. Identity verification uses /api/kyc, Risk Intelligence uses /api/v1; they are separate contracts with different error shapes. Never invent an endpoint, field or enum value: read the API reference page for the operation first.

# Quickstart

> Run a complete identity verification from your terminal in a few minutes.

> **Note**
>
> Looking for transaction decisions, customer screening, continuous monitoring
> or Travel Rule? Use the [Risk Intelligence quickstart](/risk-intelligence/quickstart).

This guide takes you through a full verification using `curl`. By the end you will have created an API key, discovered your enabled ID types, uploaded a selfie, submitted a verification, and read the result.

> **Note**
>
> **Building an app or website flow?** You usually don't need the raw API. Build a [workflow](/user-verification/workflows/workflows) in the dashboard and mount it with an [SDK](/integrate/sdks/overview) (`workflowId="wf_…"`), or share its hosted link with zero integration. This page walks the API underneath, for server-side integrations and for understanding what the SDKs do.

We use the **sandbox** environment (`pk_test_…` keys against `https://api.toden.co/api/kyc`) so you can test freely without affecting production. Sandbox and production share the same base URL, and your key prefix decides which environment you hit.

## 1. Create a test API key

In the dashboard, go to **Settings → Organization → Developers → API Keys**, switch the environment selector to **Sandbox**, and create a key. Copy the full key (`pk_test_…`); it is shown only once.

Store it in your shell:

```bash
export TODEN_KEY="pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export TODEN_BASE="https://api.toden.co/api/kyc"
```

## 2. Check your configuration

`GET /config` returns the ID types enabled for your organisation and which features each supports.

```bash
curl "$TODEN_BASE/config" \
  -H "Authorization: Bearer $TODEN_KEY"
```

```json
{
  "environment": "SANDBOX",
  "idTypes": [
    {
      "country": "NG",
      "idType": "bvn",
      "features": { "documentVerification": false, "livenessCheck": true, "govDbCheck": true }
    }
  ]
}
```

## 3. Upload media (optional)

Number-only IDs (such as BVN) don't need media. For document or selfie/liveness flows, upload each file and keep the returned `mediaId`.

```bash
curl "$TODEN_BASE/upload" \
  -H "Authorization: Bearer $TODEN_KEY" \
  -F "type=selfie" \
  -F "file=@./selfie.jpg"
```

```json
{ "mediaId": "media_01j9..." }
```

## 4. Create the verification

Submit the ID details. The `metadata.requestId` is **your** idempotency key: reuse it to safely retry without creating duplicates.

```bash
curl "$TODEN_BASE/verify" \
  -H "Authorization: Bearer $TODEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "NG",
    "idType": "bvn",
    "idNumber": "12345678901",
    "metadata": { "requestId": "order_1001", "userId": "user_42" }
  }'
```

The API responds immediately with `202 Accepted`:

```json
{ "verificationId": "ver_01j9...", "status": "processing" }
```

## 5. Get the result

Verification runs asynchronously. The publishable key polls **minimal status** (no PII):

```bash
curl "$TODEN_BASE/status/ver_01j9..." \
  -H "Authorization: Bearer $TODEN_KEY"
```

```json
{
  "verificationId": "ver_01j9...",
  "status": "approved",
  "checkStatus": "verified",
  "createdAt": "2026-04-27T12:00:00.000Z",
  "completedAt": "2026-04-27T12:00:05.000Z"
}
```

To read the **full result** (biodata, ID number, facial match), call the
[result endpoint](/user-verification/server-api/verification-result) from your backend with a **secret
(`sk_`) key**, never from client code:

```bash
curl "$TODEN_BASE/verifications/ver_01j9..." \
  -H "Authorization: Bearer $TODEN_SECRET_KEY"
```

```json
{
  "verificationId": "ver_01j9...",
  "status": "approved",
  "checkStatus": "verified",
  "country": "NG",
  "idType": "bvn",
  "result": {
    "firstName": "JOHN",
    "lastName": "DOE",
    "dateOfBirth": "1990-01-01",
    "idNumberMasked": "1234•••901",
    "facialMatch": null
  },
  "completedAt": "2026-04-27T12:00:05.000Z"
}
```

Better still, receive the result on your backend via a [webhook](/integrate/webhooks/overview).

## Next steps

* Set up [webhooks](/integrate/webhooks/overview) instead of polling.
* Review the full [verification lifecycle](/user-verification/concepts/verifications) and all status values.
* Go live by reading about [environments](/get-started/environments) and production access.