Skip to main content

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

TierWithdrawal rangeDocs required
tier_0up to $200 lifetimeNone (pre-KYC ceiling)
tier_1201201 – 2,000Email + phone OTP
tier_22,0012,001 – 20,000Government ID + selfie
tier_320,00120,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_0tier_1 or higher is required for every future withdrawal.

Endpoints

MethodPathDescription
POST/v1/kyc/startInitiate verification for a withdrawal that exceeds the user’s current tier.
GET/v1/kyc/statusPoll for review status (webhook fallback).
GET/v1/kyc/tierRead the user’s verified tier + cumulative withdrawn.
POST/v1/kyc/manual-reviewAdmin-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"
StatusMeaning
not_startedUser hasn’t begun uploading.
in_progressActive in vendor flow.
pending_reviewSubmitted — under review.
approvedTier achieved, withdrawal released.
rejectedVerification failed.
expiredAbandoned 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

EventFires when
kyc.startedUser initiated the vendor flow.
kyc.submittedDocuments uploaded, awaiting review.
kyc.approvedTier achieved — release held withdrawal.
kyc.rejectedVerification failed — keep withdrawal blocked.
kyc.tier_upgradedUser now verified at a higher tier (monotonic; never downgrades).
kyc.expiredAbandoned 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

StatusCode
400invalid_amount
401unauthorized
404user_not_found, kyc_check_not_found
409already_in_progress
422ceiling_exceeded
429rate_limited