Documentation Index
Fetch the complete documentation index at: https://ventra.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
KYC is the withdrawal gate. Deposits stay frictionless; identity is verified only when money tries to leave. Five tiers keyed to lifetime cumulative withdrawals. Production cutover will use SumSub; sandbox runs against a deterministic stub.
Sandbox currently uses a stub vendor with deterministic triggers — see “Sandbox triggers” below.
Tiers
| Tier | Withdrawal range | Docs required |
|---|
tier_0 | up to $200 lifetime | None (pre-KYC ceiling) |
tier_1 | 201–2,000 | Email + phone OTP |
tier_2 | 2,001–20,000 | Government ID + selfie |
tier_3 | 20,001–100,000 | + proof of address |
tier_4 | $100,000+ | + source-of-funds documents |
Once the $200 lifetime ceiling is crossed, the user cannot return to tier_0 — tier_1 or higher is required for every future withdrawal.
Endpoints
| Method | Path | Description |
|---|
POST | /v1/kyc/start | Initiate verification for a withdrawal that exceeds the user’s current tier. |
GET | /v1/kyc/status | Poll for review status (webhook fallback). |
GET | /v1/kyc/tier | Read the user’s verified tier + cumulative withdrawn. |
POST | /v1/kyc/manual-review | Admin-only. Manual approve / reject. |
POST /v1/kyc/start
curl https://sandbox.api.anunnakielite.com/v1/kyc/start \
-H "Authorization: Bearer cur_sk_test_EXAMPLEKEY123456789012345678901234" \
-H "Content-Type: application/json" \
-d '{
"user_id": "rt_usr_8a2f1c",
"email": "jane.doe@example.com",
"phone": "+44 7700 900123",
"withdrawal_amount_cents": 250000,
"currency": "USD"
}'
Verification required (201 Created):
{
"kyc_check_id": "kyc_3a91f7",
"user_id": "rt_usr_8a2f1c",
"required_tier": "tier_2",
"required_documents": ["government_id", "selfie"],
"sumsub_access_token": "_act-EXAMPLE-TOKEN",
"sumsub_expires_in": 600,
"withdrawal_held": true,
"estimated_clear_time": "same_day"
}
tier_0 fast path (200 OK):
{
"kyc_check_id": null,
"required_tier": "tier_0",
"required_documents": [],
"withdrawal_held": false,
"withdrawal_remaining_cents": 5000,
"message": "Withdrawal under pre-KYC ceiling. Approved instantly."
}
GET /v1/kyc/status
curl "https://sandbox.api.anunnakielite.com/v1/kyc/status?kyc_check_id=kyc_3a91f7" \
-H "Authorization: Bearer cur_sk_test_EXAMPLEKEY123456789012345678901234"
| Status | Meaning |
|---|
not_started | User hasn’t begun uploading. |
in_progress | Active in vendor flow. |
pending_review | Submitted — under review. |
approved | Tier achieved, withdrawal released. |
rejected | Verification failed. |
expired | Abandoned 7+ days. Must restart. |
GET /v1/kyc/tier
{
"user_id": "rt_usr_8a2f1c",
"verified_tier": "tier_2",
"verified_at": "2026-04-12T10:14:00Z",
"max_withdrawal_cents": 2000000,
"cumulative_withdrawn_cents": 187000,
"next_tier_required_at_cents": 2000000
}
Webhooks
| Event | Fires when |
|---|
kyc.started | User initiated the vendor flow. |
kyc.submitted | Documents uploaded, awaiting review. |
kyc.approved | Tier achieved — release held withdrawal. |
kyc.rejected | Verification failed — keep withdrawal blocked. |
kyc.tier_upgraded | User now verified at a higher tier (monotonic; never downgrades). |
kyc.expired | Abandoned check — withdrawal cancelled. |
{
"event": "kyc.approved",
"event_id": "evt_kyc_3a91f7",
"timestamp": "2026-05-24T16:08:22Z",
"data": {
"kyc_check_id": "kyc_3a91f7",
"user_id": "rt_usr_8a2f1c",
"verified_tier": "tier_2",
"release_withdrawal_id": "wd_99f02a"
}
}
Sandbox triggers
The sandbox stub vendor advances checks deterministically based on external_user_id:
- Contains
autoapprove → check moves to approved.
- Contains
autoreject → check moves to rejected.
- Otherwise →
pending_review (use the admin CLI to advance).
Error codes
| Status | Code |
|---|
| 400 | invalid_amount |
| 401 | unauthorized |
| 404 | user_not_found, kyc_check_not_found |
| 409 | already_in_progress |
| 422 | ceiling_exceeded |
| 429 | rate_limited |