> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oneshotagent.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity Verification

> Ask a person to verify their identity document in a session they complete themselves

> [!NOTE]
>
> **Status: Building.** Not yet taking sessions: the start answers `service_unavailable` until the account behind it is live.

Start a session for a named person and hand them the link. They see a consent page naming you and your purpose; if they continue, they photograph an identity document and their face on a hosted page. The decision is the job's result. OneShot sends nothing to the person.

Charged at start (see [Pricing](https://docs.oneshotagent.com/pricing.md)); not refunded on decline, abandon or expiry. The owner's [approval rules](https://docs.oneshotagent.com/api-reference/approvals/overview) apply first.

## Request

| Field | Required | Meaning |
| - | - | - |
| `full_name` | yes | The name as on their document (1 to 200 characters) |
| `email` | no | Deleted when the session ends |
| `purpose` | yes | Shown on the consent page (at most 140 characters) |
| `idempotency_key` | yes, or the `Idempotency-Key` header | 1 to 255 letters, digits, `_ . : -`; same key and input, same session |

```typescript theme={null}
const session = await agent.route('POST', '/v1/tools/identity/start', {
  paid: true,
  body: { full_name: 'Jane Doe', purpose: 'Confirm the account holder before a payout' },
  idempotencyKey: 'kyc-2026-10-jane-doe',
  wait: false, // the 202 is the answer: the person decides only after you hand them the link
});
// Hand session.verification_url to the person.
```

`202` with `request_id`, `receipt_id`, `status` (`pending`), `verification_url` and `expires_at`.

The caller proves its wallet: an access token, or `X-Agent-ID` with a signed `x-agent-proof` on every leg (the SDKs do).

## Result

Poll `GET /v1/requests/{request_id}`. When the session ends, `status` is `completed` and `result` holds:

| Field | Meaning |
| - | - |
| `status` | `approved`, `declined`, `resubmission_requested`, `expired` (7 days) or `abandoned` (declined consent) |
| `reason` | Our words: `verified`, `name_does_not_match_document`, `document_expired`, `poor_image_quality`, `declined_consent` and the like |
| `document_type` | `passport`, `id_card`, `residence_permit`, `drivers_license`, `visa` or `other`; `null` without a document |
| `issuing_country` | Two-letter code; `null` without a document |
| `name_matches` | `true` or `false` against `full_name`; `null` without a name |
| `decided_at` | When the decision was made |

Every result, `resubmission_requested` included, ends the session. Only the paying agent reads it.

## What is kept

The fields above, as long as the job; the email goes when the session ends. Never: document number, images, date of birth, address, face match score.

## The consent page

> **\{Organisation or agent name} asks you to verify your identity.**
> Reason given: "\{purpose}".
> You will photograph an identity document and your face. Our verification provider checks them and deletes the images after \{N} days. OneShot keeps only the result: whether you were verified, the document type and country, and the date. It never keeps the images or the document number.
> \[Continue] \[Decline]

## Errors

`service_unavailable` (503; any charge returned), `invalid_input` and `invalid_idempotency_key` (400), `agent_proof_required` (401), `approval_required` (403; retry with `X-Approval-Id`), `action_denied_by_policy` (403), `request_in_flight` (409; retry), `idempotency_key_reuse` (422).

`start_unconfirmed` and `charge_unrecorded` (500): use a new key. Uniquely matched confirmed charges return as credits after 30 minutes, even with unconfirmed sessions. Unmatched or ambiguous charges require review; automatic credits aren't guaranteed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.