Webhooks
Webhooks
Nova sends webhooks for asynchronous events: payment outcomes, survey
completions, DMA (Direct Mobile Access) events, and third-party
provider callbacks.
Configuring an endpoint
Webhook URLs are configured per-MVNO by your account manager. They must:
- Use HTTPS with a valid certificate.
- Respond
2xxwithin 10 seconds. - Be idempotent — Nova may redeliver the same event.
Delivery semantics
- At-least-once. The same
eventIdcan arrive more than once. - Out-of-order. Use
occurredAtif order matters to you. - Retries. Up to 8 attempts with exponential backoff over ~24 hours.
After exhausting retries the event is dead-lettered and surfaced in the
partner portal.
Payload shape
{
"eventId": "evt_01H…",
"type": "payment.succeeded",
"occurredAt": "2026-04-23T10:15:30.123Z",
"data": { … },
"version": 1
}data is shape-stable per type. New event types and new fields on
existing types are added without a breaking-change notice — design your
handler to ignore fields it doesn't recognise.
Signature verification
Each request carries an X-Nova-Signature header:
X-Nova-Signature: t=1714214130,v1=5257a869e7…
t is the unix timestamp at send time, v1 is HMAC-SHA256 over the
exact string <t>.<raw-request-body> using your webhook signing
secret (separate from your API key, also issued by your account
manager).
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(
header.split(',').map((p) => p.split('=') as [string, string]),
);
if (!parts.t || !parts.v1) return false;
const skewSec = Math.abs(Date.now() / 1000 - Number(parts.t));
if (skewSec > 300) return false; // reject > 5 min skew
const expected = createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Always verify against the raw body before any JSON parsing.
Listing event types
The current event-type list is in the API reference under the Webhooks
tag. Each entry documents the data shape with examples.
Updated about 4 hours ago