Skip to documentation content
DocumentationAPI and webhooks

API & operations

Server API, webhooks, and data controls

Use these interfaces from trusted backend code. All paths below are relative tohttps://<YOUR_IKYC_HOST>/api/v1.

Authentication boundaries

Secret project key

Send it as x-api-key from your server only. Never place it in a mobile app, browser bundle, client log, or support ticket.

Native session token

Flutter receives a short-lived bearer token only after your server mints a native session. It is not a replacement for your project secret key.

Server-to-server API

These operations require a trusted server integration. For the Flutter native-session sequence, use the dedicated Flutter guide instead of calling the direct verification endpoints from a mobile client.

Method / eventPath / areaPurpose
GET/verify/configRead the project KYC configuration with a secret project key.
POST/verify/liveness/referenceCreate a liveness session for a custom server-side integration.
POST/verify/liveness/resultNormalize a completed liveness SDK result.
POST/verifyRun KYC directly from a trusted backend service.
GET/kyc/status/{id}Retrieve a stored verification by verification ID.
GET/sdk/consent/{consentId}Read a consent record scoped to the project.
GET/sdk/identity/countCount approved identity records using a NIN HMAC, not a raw NIN.
GET/sdk/identity/historyList approved identity records using a NIN HMAC, not a raw NIN.
DELETE/kyc/erasure/{externalUserId}Run the approved data-erasure workflow.

Dashboard API

Dashboard operations use a dashboard bearer token and the caller’s organisation/project role. They manage projects, keys, verification records, browser settings, webhooks, and approved compliance workflows. They are not native-mobile SDK endpoints.

Method / eventPath / areaPurpose
POST/auth/registerCreate a dashboard user.
POST/auth/loginIssue dashboard access and refresh tokens.
POST/auth/refreshRotate a refresh token and issue a new access token.
POST/auth/logoutRevoke a refresh token.
GET/orgsList organisations available to the authenticated user.
POST/orgsCreate an organisation.
GET/orgs/{orgId}/projectsList projects in an organisation.
POST/orgs/{orgId}/projectsCreate a project.
GET/orgs/{orgId}/projects/{projectId}Read project details.
GET/orgs/{orgId}/projects/{projectId}/api-keysList active project API keys.
POST/orgs/{orgId}/projects/{projectId}/api-keysCreate a sandbox or live project API key.
GET/orgs/{orgId}/projects/{projectId}/verificationsList project verification attempts.
GET/orgs/{orgId}/projects/{projectId}/verifications/{verificationId}Read one verification attempt.
GET/orgs/{orgId}/projects/{projectId}/sdk-settingsRead the public SDK key, allowed origins, and branding.
PATCH/orgs/{orgId}/projects/{projectId}/sdk-settingsUpdate allowed origins and browser SDK branding.
GET/orgs/{orgId}/projects/{projectId}/webhookRead webhook configuration without exposing its secret.
PATCH/orgs/{orgId}/projects/{projectId}/webhookSet or clear the webhook URL and signing secret.
POST/orgs/{orgId}/projects/{projectId}/webhook/testQueue a signed webhook test delivery.
GET/orgs/{orgId}/projects/{projectId}/consent-recordsList project consent records.
GET/orgs/{orgId}/projects/{projectId}/data-subjectRead data held for an approved data-subject request.
GET/orgs/{orgId}/projects/{projectId}/compliance/reportRead aggregate compliance counts for a date range.

Signed webhooks

Configure a webhook URL and signing secret in the project dashboard. Verify the signature over the unmodified raw request body before parsing it. Make your handler idempotent: the same event can be delivered more than once during retry.

Verify a webhook signature
import crypto from "node:crypto";

export function verifyIkycSignature(
  secret: string,
  rawBody: string,
  signature: string,
) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex"),
  );
}
Method / eventPath / areaPurpose
kyc.completedVerificationThe overall verdict is approved.
kyc.needs_reviewVerificationThe attempt requires manual review.
kyc.failedVerificationThe attempt failed an automated gate.
kyc.limit_exceededVerificationThe subscriber reached the configured SIM limit.
liveness.failedLivenessThe liveness result failed.
liveness.timeoutLivenessThe provider was unavailable or timed out.
face_match.low_confidenceFace matchFace match returned a review outcome.
webhook.testOperationsA manual delivery test was requested in the dashboard.

Webhook payloads do not replace a controlled status lookup. Keep raw identity data, images, biometric data, provider responses, NINs, BVNs, and tokens out of your webhook logs.

Identity lookup and retention controls

Identity lookup endpoints accept a 64-character HMAC-SHA256 digest, not a raw NIN. Use a dedicated server-side NIN_HMAC_SECRET; do not reuse application token or encryption keys.

Compute a NIN HMAC on your server
import crypto from "node:crypto";

export function computeNinHmac(nin: string) {
  return crypto
    .createHmac("sha256", process.env.NIN_HMAC_SECRET!)
    .update(nin)
    .digest("hex");
}

// Send only this 64-character digest to identity lookup endpoints.
const ninHmac = computeNinHmac("<NIN>");

Use the project’s data-subject and erasure controls for approved privacy requests. Keep only the operational data your organisation is authorized to retain.