Skip to content

Quickstart

You need: the service base URL and an API key (issued by whoever operates the instance — for the reference deployment, keys live in Railway service variables).

From your backend (never from a browser or mobile app — the API key must not ship to devices):

Terminal window
curl -X POST $BASE/v1/verifications \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_user_ref": "user-123",
"webhook_url": "https://yourapp.com/kyc-hook"
}'
{
"verification_id": "ver_01kyts0zyt4nrgwajvs2nz8w78",
"handoff_token": "JdEcex…",
"handoff_url": "https://kyc-server-production.up.railway.app/v/JdEcex…",
"expires_in_minutes": 30
}
  • external_user_ref is your user ID — opaque to BAQSHI-KYC, echoed back so you can correlate.
  • handoff_token is the only credential the user’s device will ever hold. It is scoped to this one verification, expires in 30 minutes, and can be revoked.

Pick whichever fits the moment:

SituationDo this
User is on desktopRender handoff_url as a QR code — scanning opens the hosted capture page on their phone
User is on mobile webRedirect to handoff_url
User is in your Expo appPass handoff_token to the Expo SDK

The hosted page and the SDK drive the same flow: ID photo → randomized pose challenge (look straight, turn left/right) → decision.

Your webhook_url receives a signed, PII-free notification:

{ "type": "verification.decided", "verification_id": "ver_…", "status": "approved" }

Always verify the signature before trusting it. Then fetch details or an attestation:

Terminal window
# Full status + minimal extracted identity fields (server-to-server only)
curl -H "Authorization: Bearer $API_KEY" $BASE/v1/verifications/ver_…
# Signed attestation with only the claims you need
curl -X POST -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
-d '{"claims": ["verified", "over_18"]}' $BASE/v1/attestations/ver_…
StatusMeaningYour action
approvedAll checks passedGrant access
rejectedA check failed decisively (expired doc, failed liveness, face mismatch)Deny; offer retry or support
manual_reviewSomething was uncertain or suspiciousWait — a reviewer will decide, then the webhook fires again

Details on every rejection and review reason: Decision states.