Webhooks

Webhooks let you stop polling. Subscribe to lifecycle events on your OAuth client and we'll POST a signed payload to your URL each time something happens.

Where to manage webhooks. Subscriptions, secret rotation, delivery audit and replay are managed from the Developer hub in your OneFinOps dashboard. Webhooks are not on the public REST API yet — only the receive side is in scope here.

Events

EventFires when
einvoice.generatedAn IRN reaches the generated state.
einvoice.cancelledAn IRN reaches the cancelled state.
einvoice.failedAn IRN reaches the failed_terminal state.
ewaybill.generatedAn EWB is generated.
ewaybill.cancelledAn EWB is cancelled.
ewaybill.expiredAn EWB transitions to expired.
ewaybill.rejectedA counter-party EWB is rejected.

(Subscribe to the subset you care about; new events will only fire to subscriptions that include them.)

Payload shape

{
  "id": "evt_01HRXY...",
  "type": "einvoice.generated",
  "createdAt": "2026-05-04T11:42:18Z",
  "data": {
    "id": "einv_01HRXY...",
    "object": "einvoice",
    "status": "generated",
    "irn": "...",
    "ackNumber": "...",
    "ackDate": "...",
    "sellerGstin": "...",
    "invoiceNumber": "...",
    "totalInvoiceValue": 11800
  }
}

data mirrors the same shape returned by GET /v1/einvoices/{id} (or /ewaybills/{id}). You can refetch via the API any time the webhook arrives — useful if your handler needs more fields than the event surfaces.

Verifying signatures

Each delivery carries an HMAC-SHA256 signature in the OneFinOps-Signature header:

OneFinOps-Signature: t=1714820538,v1=5e29...

To verify:

  1. Concatenate t and the raw request body with a . between them.
  2. Compute HMAC-SHA256(signing_secret, "<t>.<body>").
  3. Constant-time-compare against the v1 value.
  4. Reject deliveries where t is more than 5 minutes out — replay protection.

The signing_secret is shown once when you create the subscription (and on rotation). Store it the same way you store your client_secret.

Delivery semantics

  • At-least-once. Network blips and 5xxs cause retries; design your handler to be idempotent on event.id.
  • Retry policy. Failed deliveries (non-2xx, network error) are retried with exponential backoff for up to 24 hours, then dead-lettered.
  • Order is not guaranteed. Process events as you receive them; if order matters, use the data.status and timestamps in the payload.
  • Auto-disable. A subscription that fails 50+ deliveries in a row is automatically deactivated. You'll see the failure in the Developer hub and can re-enable after fixing your endpoint.

Replay from the dashboard

The Developer hub shows every delivery — status code, attempt count, response body, and a Replay button. Use this to redrive after fixing a downstream bug.