Skip to content

Tracking verification status

Three endpoints, one mental model: ask the same applicant id, get different levels of detail.

Endpoint Use it when
GET /v1/applicants/{externalUserId}/status You just want the rolled-up verdict.
GET /v1/applicants/{externalUserId}/steps You want a per-step breakdown ("which step failed?").
GET /v1/applicants/{externalUserId}/review-history You want a chronological timeline of decisions + transitions.

/steps — per-step breakdown

Returns one row per step the applicant's level requires. The vocabulary matches the applicantReviewed webhook payload exactly — no translation layer needed.

curl -X GET 'https://api.compliance.example/v1/applicants/user-12345/steps' \
  -H 'X-Api-Key: pk_live_...' \
  -H 'X-Api-Secret: ...' \
  -H 'X-Environment: production'
{
  "externalUserId": "user-12345",
  "levelId": "a1b2c3d4-...",
  "levelName": "KYC_01",
  "steps": [
    {
      "kind": "identity_doc",
      "optional": false,
      "reviewAnswer": "GREEN",
      "reviewStatus": "completed",
      "reviewRejectType": null,
      "lastUpdatedAtUtc": "2026-06-07T10:31:22Z"
    },
    {
      "kind": "questionnaire",
      "optional": false,
      "reviewAnswer": null,
      "reviewStatus": "in_review",
      "reviewRejectType": null,
      "lastUpdatedAtUtc": "2026-06-07T10:30:15Z"
    }
  ]
}

Step kind

identity_doc · selfie · liveness · poa · questionnaire · company_docs · aml · adverse_media.

Vocabulary

  • reviewAnswerGREEN (approved) · RED (rejected) · null (no verdict yet)
  • reviewStatuspending · submitted · in_review · completed · awaitingOperatorReview · expired
  • reviewRejectTypeFINAL · RETRY · EXPIRED (set when reviewAnswer=RED)
  • rejectLabels — array of labels explaining the rejection (see Webhook Integration)

This is identical to what the applicantReviewed webhook delivers — your handler can switch on the same enum here.

/review-history — chronological audit

Returns up to 200 chronological events for the applicant. Operator- administrative events (admin login, credential rotation, internal level edits) are filtered out — partner-safe surface.

curl -X GET 'https://api.compliance.example/v1/applicants/user-12345/review-history?limit=10' \
  -H 'X-Api-Key: pk_live_...' \
  -H 'X-Api-Secret: ...' \
  -H 'X-Environment: production'
{
  "items": [
    { "atUtc": "2026-06-07T10:31:22Z", "eventType": "applicant.verified", "actorType": "system" },
    { "atUtc": "2026-06-07T10:30:00Z", "eventType": "enrollment.completed", "actorType": "sdk" },
    { "atUtc": "2026-06-07T10:15:11Z", "eventType": "enrollment.created", "actorType": "partner" }
  ],
  "totalItems": 3
}

Query parameters

Param Effect
since ISO 8601 timestamp — events at/after this time only
limit 1..200 (default 50)
eventType Filter to one event name (400 if outside the partner allowlist)

Partner-visible event allowlist

applicant.{created,updated,reset,blocklisted,blocklist_removed,sent_to_review,email_status_sent,monitoring_enabled,monitoring_disabled,verified,approved,rejected,deactivated,activated}, enrollment.{created,submitted,completed,expired}, aml.run, adverse_media.run, managed_compliance.decided. Anything else is silently dropped from the response.