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
| Event | Fires when |
|---|---|
einvoice.generated | An IRN reaches the generated state. |
einvoice.cancelled | An IRN reaches the cancelled state. |
einvoice.failed | An IRN reaches the failed_terminal state. |
ewaybill.generated | An EWB is generated. |
ewaybill.cancelled | An EWB is cancelled. |
ewaybill.expired | An EWB transitions to expired. |
ewaybill.rejected | A 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:
- Concatenate
tand the raw request body with a.between them. - Compute
HMAC-SHA256(signing_secret, "<t>.<body>"). - Constant-time-compare against the
v1value. - Reject deliveries where
tis 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.statusand 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.
Updated about 5 hours ago
