Skip to main content

Server-side Implementation

CreditChek Widget (SDK) - Backend Integration Guide​

Integrate the CreditChek Widget (SDK) to perform identity verifications (BVN, NIN, Liveness) with a frictionless user experience.

Production Base URL: https://api.creditchek.africa


To keep your business informed about transaction results outcomes (objects) through our API & SDK, beside providing some On-demand API polling Endpoints, we strongly recommend the use of Webhooks. This feature enables you to initiate additional workflows based on transaction events. Whenever an event you're subscribed to occurs, Creditchek will dispatch a POST request to the Webhook URL you specified, including information about the transaction event.

To activate webhook requests, you must enable this feature on the dashboard settings and configure your correct webhook Callback URL, which should accept POST HTTP requests.

Webhook requests include an "x-auth-signature" on the header, containing your app's LiveSecretKey, for verification purposes. You can leverage this key to authenticate and authorize your unique webhook request.

Overview​

StepWhoWhat happensWhere
0. Configure SDKBusiness (dashboard)Creates an SDK, picks branding and the verification services. Gets a Widget ID.CreditChek Dashboard
1. Create SessionYour BackendCreates a widget session using your secret key and Widget ID. Receives a sessionId.POST /v1/auth/widget-session/token
2. Launch WidgetYour FrontendOpens the CreditChek widget with your public key, Widget ID and the sessionId.CreditChek.open({ publicKey, widgetId, sessionId })
3. User VerifiesEnd UserCompletes BVN / NIN / Liveness inside the widget.CreditChek Widget UI
4. WebhookCreditChek APISends the verified profile to your webhook URL.identity.bvn.verified, identity.nin.verified
5. Confirm SessionYour BackendConfirms the session is completed.GET /v1/auth/widget-session/:sessionId
6. Fetch DataYour Backend(Optional) Pulls the verified profile on demand.GET /v1/auth/widget-session/bvn-data/:sessionId
GET /v1/auth/widget-session/nin-data/:sessionId

Step 0: Configure the SDK on the Dashboard​

This is done once per app on the CreditChek dashboard. No API call is needed from your backend.

  1. Sign in to the dashboard and open the app you want to use.
  2. Go to SDK Setup and create a new SDK.
  3. Fill in the configuration:
OptionWhat it controls
NameInternal name for this SDK configuration
Display nameName shown to end users in the widget
LogoLogo shown in the widget header
Brand colourPrimary colour of the widget
Support emailContact shown to users if something goes wrong
Environmentsandbox for testing, live for production
ModulesWhich product modules are enabled: Identity, Credit, Income, Recova, Liveness
ServicesVerification steps the user must complete: bvn, nin, liveness (and identity, credit, income, recova)
OrderThe order the enabled steps are shown to the user
Multiple approvalWhether changes need more than one approver
  1. Save. Copy the Widget ID — your backend sends it as widgetId when creating sessions, and your frontend passes it to the widget as widgetId.

One SDK setup is allowed per app.

You also need, from the dashboard's API Keys page:

  • Your app's secret key — used by your backend (Step 1). Never expose it in the frontend.
  • Your app's public key — used by your frontend (Step 2).

Use keys from the same environment: live secret key with live public key, sandbox with sandbox.

Finally, register a webhook URL so you receive verification events.


Step 1: Create a Widget Session (Backend)​

Your backend creates a session server-to-server, authenticated with your app's secret key. The public key is resolved from the secret key automatically:

  • Live secret key → session uses your live public key.
  • Sandbox secret key → session uses your sandbox public key.
POST /v1/auth/widget-session/token
token: <your_secret_key>
Content-Type: application/json

Request body​

FieldTypeRequiredDescription
widgetIdstringNoYour widget ID from the dashboard (the same value you pass to the widget). Links the session to that widget's branding and services.

The session uses the services configured on the SDK. If no widgetId is sent, it defaults to bvn only.

Example request​

curl -X POST https://api.creditchek.africa/v1/auth/widget-session/token \
-H "token: $CREDITCHEK_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{ "widgetId": "64b2c1f0a9e3b2c4d5e6f7a8" }'

Backend example (Node.js / Express)​

const axios = require('axios');

async function createVerificationSession(req, res) {
try {
const { data } = await axios.post(
'https://api.creditchek.africa/v1/auth/widget-session/token',
{ widgetId: process.env.CREDITCHEK_WIDGET_ID },
{ headers: { token: process.env.CREDITCHEK_SECRET_KEY } }
);

res.status(200).json({ sessionId: data.data.sessionId });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
}

Response 200​

{
"success": true,
"message": "Widget session created successfully",
"data": {
"_id": "66dee42b918f4a187d90a12f",
"publicKey": "reh+e9i7kTu9neibSbX6NTaLgx/ZfThcmPWOsDr4tL/p6X9Qf9YmU4pUNnelkm47",
"widgetId": "64b2c1f0a9e3b2c4d5e6f7a8",
"sessionId": "412275c7-5be5-433a-873d-3dd32d6b9ff2",
"status": "active",
"services": {
"bvn": { "status": "pending" },
"liveness": { "status": "pending" }
},
"expiresAt": "2026-09-29T14:10:00.000Z",
"createdAt": "2026-09-29T13:50:00.000Z",
"updatedAt": "2026-09-29T13:50:00.000Z"
}
}

Sessions expire 20 minutes after creation. Create the session when the user is about to verify, not ahead of time.

Errors​

StatusMessageCause
401Access token is required / Invalid App tokenMissing or wrong token header
400No public key configured for this appThe app has no public key for that environment
404SDK setup not foundwidgetId does not exist
403SDK setup does not belong to this appwidgetId belongs to a different app than the secret key

Step 2: Launch the Widget (Frontend)​

Load the widget script and call CreditChek.open with your public key, your widget ID (widgetId) and the sessionId from your backend. The widget loads the SDK's branding (logo, colour, display name) and shows the configured steps in order.

<button id="verify">Verify my identity</button>

<script src="https://securedwidget.creditchek.africa/v1/inline.js"></script>
<script>
document.getElementById("verify").addEventListener("click", () => {
CreditChek.open({
publicKey: "<your public key>",
widgetId: "<your widget configuration ID>",
sessionId: "<session created on your server>",

onResult: ({ module, status }) => console.log(`${module}: ${status}`),
onError: ({ error, reason }) => console.error("CreditChek:", error, reason),

onClose: async ({ reason, sessionId }) => {
console.log("Widget closed:", reason); // "finished" | "dismissed" | "error"
if (!sessionId) return; // the session was never created
await fetch("/api/verification/confirm", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sessionId }),
});
},
});
});
</script>

Options​

OptionTypeRequiredDescription
publicKeystringYesYour app's public key. Must be from the same environment as the secret key used in Step 1.
widgetIdstringYesYour widget ID from the dashboard (Step 0)
sessionIdstringYesThe session created by your backend in Step 1
onResultfunctionNoCalled each time a verification step finishes
onErrorfunctionNoCalled when the widget hits an error
onClosefunctionNoCalled when the widget closes, for any reason

Callbacks​

CallbackReceivesNotes
onResult{ module, status }module is the step, e.g. bvn, nin, liveness. status is that step's result, e.g. completed or failed. Fires once per step.
onError{ error, reason }error identifies the failure; reason describes it.
onClose{ reason, sessionId }reason is finished (all steps done), dismissed (user closed it) or error. sessionId is missing if the session was never created — skip the backend check in that case.

Callbacks are signals only. Always confirm the session on your backend (Step 5) before granting access, regardless of what onResult or onClose report.


Step 3: User Completes Verification​

Inside the widget the user goes through the services on the session in the configured order, e.g. enter BVN → face capture. Each service moves from pending to completed or failed, and onResult fires as each one finishes (e.g. bvn: completed).

When the user is done, the widget closes and onClose fires with reason: "finished".


Step 4: Receive the Webhook​

When a verification finishes, CreditChek sends the verified profile to your registered webhook URL.

EventSent when
identity.bvn.verifiedBVN verification succeeds
identity.nin.verifiedNIN / vNIN verification succeeds

Deliveries are signed with webhook-id, webhook-timestamp and webhook-signature headers. If you didn't set a custom signing secret, your app's live secret key is the signing secret.


Step 5: Confirm the Session (Backend)​

GET /v1/auth/widget-session/:sessionId
curl -X GET https://api.creditchek.africa/v1/auth/widget-session/412275c7-5be5-433a-873d-3dd32d6b9ff2

Response 200

{
"success": true,
"message": null,
"data": {
"sessionId": "412275c7-5be5-433a-873d-3dd32d6b9ff2",
"widgetId": "64b2c1f0a9e3b2c4d5e6f7a8",
"status": "completed",
"services": {
"bvn": { "status": "completed" },
"liveness": { "status": "completed" }
},
"bvn": "22233344455",
"expiresAt": "2026-09-29T14:10:00.000Z"
}
}
Session statusMeaning
activeUser hasn't finished yet
completedAll services passed — safe to proceed
failedAt least one service failed — prompt the user to retry
Status codeMeaning
404Session not found
410Session expired (older than 20 minutes)

Step 6: Fetch Verified Data (Optional)​

The webhook already contains the verified profile. Use these endpoints if you need it on demand — e.g. to show the user's details right away, as a fallback if your webhook listener missed a delivery, or for reconciliation.

GET /v1/auth/widget-session/bvn-data/:sessionId
GET /v1/auth/widget-session/nin-data/:sessionId
  • bvn-data returns the profile for the BVN on the session.
  • nin-data returns the profile for the NIN or vNIN on the session.
  • Both work with sessions created from a live or sandbox key.
StatusMessage
404Widget session not found
404Bvn not found for widget session / Nin not found for widget session — user hasn't completed that step
404Bvn data not found for session / Nin data not found for session — live only; no verified record

Testing in Sandbox​

Use your sandbox secret key in Step 1 and an SDK set to the sandbox environment. The test numbers below return fixed mock profiles and never call live providers or debit your wallet.

ServiceTest valueResult
BVN12345678901Verified
BVN12345678902Verified (watchlisted)
BVN22233344455Verified
BVN22113344556Verified
NIN12345678901Verified

In sandbox(development mode), any other BVN/NIN with no stored record returns a default mock profile instead of a 404.