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 / event | Path / area | Purpose |
|---|---|---|
| GET | /verify/config | Read the project KYC configuration with a secret project key. |
| POST | /verify/liveness/reference | Create a liveness session for a custom server-side integration. |
| POST | /verify/liveness/result | Normalize a completed liveness SDK result. |
| POST | /verify | Run 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/count | Count approved identity records using a NIN HMAC, not a raw NIN. |
| GET | /sdk/identity/history | List 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 / event | Path / area | Purpose |
|---|---|---|
| POST | /auth/register | Create a dashboard user. |
| POST | /auth/login | Issue dashboard access and refresh tokens. |
| POST | /auth/refresh | Rotate a refresh token and issue a new access token. |
| POST | /auth/logout | Revoke a refresh token. |
| GET | /orgs | List organisations available to the authenticated user. |
| POST | /orgs | Create an organisation. |
| GET | /orgs/{orgId}/projects | List projects in an organisation. |
| POST | /orgs/{orgId}/projects | Create a project. |
| GET | /orgs/{orgId}/projects/{projectId} | Read project details. |
| GET | /orgs/{orgId}/projects/{projectId}/api-keys | List active project API keys. |
| POST | /orgs/{orgId}/projects/{projectId}/api-keys | Create a sandbox or live project API key. |
| GET | /orgs/{orgId}/projects/{projectId}/verifications | List project verification attempts. |
| GET | /orgs/{orgId}/projects/{projectId}/verifications/{verificationId} | Read one verification attempt. |
| GET | /orgs/{orgId}/projects/{projectId}/sdk-settings | Read the public SDK key, allowed origins, and branding. |
| PATCH | /orgs/{orgId}/projects/{projectId}/sdk-settings | Update allowed origins and browser SDK branding. |
| GET | /orgs/{orgId}/projects/{projectId}/webhook | Read webhook configuration without exposing its secret. |
| PATCH | /orgs/{orgId}/projects/{projectId}/webhook | Set or clear the webhook URL and signing secret. |
| POST | /orgs/{orgId}/projects/{projectId}/webhook/test | Queue a signed webhook test delivery. |
| GET | /orgs/{orgId}/projects/{projectId}/consent-records | List project consent records. |
| GET | /orgs/{orgId}/projects/{projectId}/data-subject | Read data held for an approved data-subject request. |
| GET | /orgs/{orgId}/projects/{projectId}/compliance/report | Read 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.
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 / event | Path / area | Purpose |
|---|---|---|
| kyc.completed | Verification | The overall verdict is approved. |
| kyc.needs_review | Verification | The attempt requires manual review. |
| kyc.failed | Verification | The attempt failed an automated gate. |
| kyc.limit_exceeded | Verification | The subscriber reached the configured SIM limit. |
| liveness.failed | Liveness | The liveness result failed. |
| liveness.timeout | Liveness | The provider was unavailable or timed out. |
| face_match.low_confidence | Face match | Face match returned a review outcome. |
| webhook.test | Operations | A 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.
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.