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 2xx within 10 seconds.
  • Be idempotent — Nova may redeliver the same event.

Delivery semantics

  • At-least-once. The same eventId can arrive more than once.
  • Out-of-order. Use occurredAt if 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.