Webhooks
Receiving secure, asynchronous verification decisions.
Because identity verification involves manual compliance reviews and asynchronous database checks, your application must rely on Webhooks to learn the final status of a session.
When you create a session, you provide a callbackUrl. When the session reaches a terminal state (approved or declined), Nyota will send a POST request to that URL.
The Webhook Payload
{
"event": "verification.completed",
"sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"externalEndUserId": "user_987654321",
"type": "kyc",
"status": "approved",
"reason": null,
"timestamp": "2026-07-23T15:41:04.471Z"
}If the verification was declined (due to poor image quality, expired documents, or failure to pass liveness checks), the status will be "declined" and the reason field will contain a human-readable explanation.
Verifying Webhook Signatures
To prevent attackers from sending fake "approved" webhooks to your server, you must verify the cryptographic signature attached to every request.
Nyota signs the raw request body using your Workspace Webhook Secret (available in the Nyota Accounts Dashboard) and attaches it to the x-nyota-signature header.
Node.js Example:
import crypto from "crypto";
import express from "express";
const app = express();
const WEBHOOK_SECRET = process.env.NYOTA_WEBHOOK_SECRET;
app.post(
"/nyota-webhooks",
express.text({ type: "application/json" }),
(req, res) => {
const signature = req.headers["x-nyota-signature"];
const rawBody = req.body; // Ensure you are hashing the RAW string, not the parsed JSON object
const expectedSignature = crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");
if (signature !== expectedSignature) {
console.error("Invalid webhook signature!");
return res.status(401).send("Unauthorized");
}
// Signature is valid! Safe to parse and update your database.
const payload = JSON.parse(rawBody);
if (payload.status === "approved") {
console.log(`User ${payload.externalEndUserId} is verified!`);
}
res.status(200).send("OK");
},
);Auto-Expiry and Abandonment
If a user opens the verification modal but abandons it, the session will remain pending for 24 hours. After 24 hours, Nyota automatically marks the session as declined (Reason: "Expired/Abandoned"), releases the reserved funds back into your Nyota Wallet, and fires a webhook to your server so you can update your UI.