Skip to content

API overview

The integrator API is /v1. The full schema is on the Reference page, generated from the OpenAPI spec published with thibit-verify v1.0.9.

Environment Base URL
Production https://api.thibit.id

Every machine /v1 call is scoped by a project API key in the X-API-Key header:

X-API-Key: tk_test_…

Get a project API key from the dashboard: sign in with Google or GitHub, and create/list/revoke project-scoped keys inside an org → project. Keys are project-scoped; keep them server-side. The OAuth/session plane (the /auth/* routes the dashboard uses to sign you in) is internal to the dashboard and not part of the machine-to-machine /v1 contract documented here.

There are two ways to start a verification:

  • Create directly — POST /v1/verifications mints a verification from an inline allowed-documents list. No Template to author; fully back-compatible.
  • Run a Flow — POST /v1/flows/{slug}/intake runs a Flow you activated in the dashboard, pre-filling capture from your payload and stamping your reference record. See Templates, Flows & Cases.
Method Path Purpose
POST /v1/signup Self-serve sandbox tenant + key. Local/dev only — disabled in production (403); use the dashboard to get a project key.
GET /v1/me For api-key callers: your tenant profile (name, webhook URL, sandbox flag).
POST /v1/keys/rotate Rotate your API key (the old key is invalidated).
POST /v1/verifications Create a verification → { id, onboarding_url, short_url }.
GET /v1/verifications List your recent verifications (the log).
GET /v1/verifications/{id} Fetch one verification’s status + assessment.
DELETE /v1/verifications/{id} Erase a verification’s PII (GDPR-style) → a PII-safe receipt; the record’s status becomes erased.
POST /v1/flows/{slug}/intake Run a Flow for a payload → mints a Case + link (project-scoped key).
POST /v1/webhook Set/clear the legacy tenant-level webhook URL (project webhooks below are preferred).

Project management (dashboard session or project scope)

Section titled “Project management (dashboard session or project scope)”

These routes back the dashboard’s Integrate, Team, and Settings surfaces. They are driven by a signed-in dashboard session (Google/GitHub OAuth) and gated per-permission; non-members get a 404.

Method Path Purpose
GET /v1/projects/{id}/keys List a project’s API keys.
POST /v1/projects/{id}/keys Create a project API key (raw value shown once).
DELETE /v1/projects/{id}/keys/{key_id} Revoke a project key (idempotent).
GET /v1/projects/{id}/webhook Read the project webhook config (never returns the secret).
PUT /v1/projects/{id}/webhook Set the project webhook URL; mints the signing secret on first set (returned once).
DELETE /v1/projects/{id}/webhook Clear the webhook URL (the secret is retained for re-enabling).
GET /v1/projects/{id}/branding Read the project’s hosted-page branding.
PUT /v1/projects/{id}/branding Set the project’s hosted-page branding.
GET /v1/team/members The active org’s members (email + name + role).
GET /v1/team/invitations Pending invitations for the active org.
POST /v1/team/invitations Invite a colleague by email + role — they auto-join on their next OAuth sign-in (no email is sent yet).
DELETE /v1/team/invitations/{id} Revoke a pending invitation.

The dashboard’s Build / Flows / Verifications / Case Management surfaces are driven by session-scoped dashboard routes that are not part of the machine contract — use the dashboard for those.

Once you’ve activated a Flow in the dashboard (Build → Flows), run it by POSTing the data you already hold. Use a project-scoped API key.

Terminal window
curl -X POST https://api.thibit.id/v1/flows/{slug}/intake \
-H "X-API-Key: tk_test_…" \
-H "Content-Type: application/json" \
-d '{
"payload": {
"full_name": "Ana Sitoe",
"dob": "1994-03-12",
"id_number": "110100..."
},
"verifiee": { "email": "ana@example.com" }
}'
{
"id": "…",
"flow_id": "…",
"flow_slug": "swift-harbor-x7k2m9",
"flow_version_ref": 3,
"status": "collecting",
"onboarding_url": "https://onboard.thibit.id/?token=…",
"short_url": "https://thibit.id/s/…",
"link": "https://thibit.id/s/…"
}

payload is validated against the Flow’s declared intake shape (a missing required field is a 400 naming the key). Mapped fields pre-fill capture for the verifiee; the whole payload (or an explicit claimed object) is stored on the Case as your reference record for record match. link is the short apex link to send the verifiee. The Case is read back from the dashboard’s Verifications surface.

collecting → pending → processing → completed | failed — plus erased after a DELETE /v1/verifications/{id}. Creation returns immediately; the engine runs asynchronously and the result arrives by webhook or polling GET /v1/verifications/{id}. Terminal results carry an advisory assessment (no_material_concerns | manual_review_recommended | material_inconsistency | assessment_incomplete) — see Verification flow. A verification also ends failed when its document is not supported or its hosted link expires before the applicant submits; an expired link sends no webhook.

A create that timed out can be retried without minting a second verification when it carries an idempotency key:

  • POST /v1/flows/{slug}/intake — send idempotency_key in the request body.
  • POST /v1/verifications with a contract_version — send the Idempotency-Key header, which that contract requires.

Repeating a key with the same request returns the original verification (the same id and link expiry) instead of creating another; reusing it with a different request returns 409. Keys are scoped to your project and hold up to 255 characters. POST /v1/verifications without a contract_version does not deduplicate: it ignores Idempotency-Key, so a retry creates a second verification. Keep your own applicant-to-verification mapping there, or create through intake.

  • Async, not blocking — never hold a request open waiting for a result.
  • Idempotency — retry a create only with an idempotency key, on a path that honours it (see above).
  • Errors — standard HTTP status codes; 401 = missing/invalid X-API-Key.