Backend API
All backend endpoints require Authorization: Bearer <API_KEY>. Keys identify the
calling product; every action is audit-logged against a non-reversible key
fingerprint. Never embed an API key in a mobile app, browser bundle, or repo.
Business clients & API keys
Section titled “Business clients & API keys”Every API key belongs to a client (a business tenant). Keys look like
bk_live_…, are shown exactly once at creation, and only their SHA-256 hash is
stored server-side. All data access is scoped to the owning client: you can only
read, review, erase, or attest verifications your own key created — anything
else returns 404. Each client also gets its own whsec_… webhook signing
secret (see Webhooks).
Clients are managed by the operator through the /v1/admin API, which is gated
by a separate admin credential (BAQSHI_ADMIN_KEY, never a client key):
POST /v1/admin/clients {"name": "Acme Bank"} # → api_key + webhook secret, shown onceGET /v1/admin/clients # list (prefixes only, no secrets)POST /v1/admin/clients/{id}/rotate-key # → new api_key, shown oncePOST /v1/admin/clients/{id}/disable | /enableDon’t have a key yet? Prospective clients can request access with
POST /v1/access-requests {"company_name", "contact_name", "email", "message"?}
(no auth, rate-limited) — the owner reviews requests in the admin panel and, on
approval, hands over the credentials securely.
Lost keys cannot be recovered — rotate instead. Keys configured via the
BAQSHI_API_KEYS environment variable act as the operator’s root client:
they authenticate as before and can see every tenant’s verifications (for ops
and manual review across tenants).
Create a verification
Section titled “Create a verification”POST /v1/verifications{ "external_user_ref": "user-123", "webhook_url": "https://yourapp.com/kyc-hook" }Both fields are optional. webhook_url must be HTTPS. Response contains
verification_id, handoff_token, handoff_url, expires_in_minutes.
Pattern: create verifications lazily, at the moment the user starts the flow — tokens live 30 minutes. If the user abandons and returns later, create a new one; old tokens die on their own.
Read status
Section titled “Read status”GET /v1/verifications/{verification_id}Returns status, decision_reasons, and the minimal extracted fields (names, DOB,
document type/country/expiry). This endpoint is the only place extracted
identity data leaves the system, and it requires the API key — the user’s device
can never read it.
Prefer webhooks over polling; poll as a fallback with backoff (the pipeline usually decides in seconds, manual review in hours).
Issue an attestation
Section titled “Issue an attestation”POST /v1/attestations/{verification_id}{ "claims": ["verified", "over_18"] }Only works for approved verifications (409 otherwise). Returns a signed compact
token plus the claim values. See Attestations for
verification and the claim catalogue.
Erase a user’s data
Section titled “Erase a user’s data”DELETE /v1/verifications/{verification_id}/dataCryptographic erasure for privacy/deletion requests: destroys every artifact’s data key, deletes hot blobs, and nulls the identity fields in the database. Blobs already on offline archive media become permanently unreadable too — no media handling required. The decision status and audit chain remain (you generally must keep that you verified someone; you stop keeping what you saw).
Idempotency and retries
Section titled “Idempotency and retries”- Creating a verification is not idempotent — dedupe on your side per user-session.
- Reads are safe to retry.
- Erasure is idempotent (already-erased artifacts are skipped).
- On
429, respectRetry-After— see Rate limits.