POST to your endpoint when something changes, for example subscription.started or invoice.payment_status_updated. This page is about those webhooks. For the events Stripe and Razorpay send to Nozle, see Webhooks.
Register an endpoint
Create an endpoint in the dashboard under Developers > Webhooks, or withPOST /webhook_endpoints:
signature_algo is jwt (the default) or hmac. The URL must be valid and each URL can be registered once per organization. The dashboard form selects hmac by default, while the API uses jwt when you send no value. The API reference has a Webhook Endpoints section.
Until January 19, 2027, payloads also carry the old, former-prefix key names beside nozle_id and the new keys. Read the new keys: see legacy key names.
Each delivery is a JSON body with a webhook_type such as subscription.started and the object it is about, for example subscription. The event types are listed in the API reference under Webhooks.
A failed credit note refund is sent as credit_note.refund_failure. To receive only some types, send an event_types array when you create or update the endpoint (no array means every type). credit_note.refund_failure is accepted there; the former name credit_note.provider_refund_failure is still accepted and saved as credit_note.refund_failure, and endpoints saved with the former name are moved to it.
Headers
Verify the signature
Verify the raw request body before you parse it. A framework that parses and re-serialises the JSON can change the bytes and break the check.With the SDK
The server SDKs check both formats and return the parsed event. Forjwt they read Nozle’s public key once with your secret key and cache it. For hmac, pass the signing secret. Webhook verification requires @nozle-js/node 0.13.0, nozle-sdk 0.13.0 or github.com/nozle-dev/nozle-go v0.12.0.
- Node.js
- Python
- Go
nozle.webhooks.verify({ body, headers, hmacKey }) with the raw body; it throws WebhookVerificationError with a code.id (the X-Nozle-Unique-Key, for skipping duplicates), type, objectType (Python object_type), organizationId, object and the whole payload. A failed check has the code missing_signature, unsupported_algorithm, missing_hmac_key, invalid_signature or invalid_payload.
Without the SDK
hmac
The signature is Base64(HMAC-SHA256(hmac_key, raw body)). The hmac_key is your organization’s signing secret, shown on the Developers > Webhooks page of the dashboard.
- Node.js
- Python
- Go
jwt
The signature is an RS256 JWT. Its claims are data, the payload as a JSON string, and iss. Fetch the public key from GET /webhooks/json_public_key with your secret key. The response is {"webhook": {"public_key": "..."}}, where the key is the PEM text encoded in Base64.
GET /webhooks/public_key returns the same key as plain text and is deprecated.
Webhooks to the Engine
An endpoint that points at Nozle’s Engine (/webhooks/nozle) is verified with the sending organization’s own signing key, the same hmac_key as above. It must use the hmac signature algorithm: jwt endpoints are rejected. An unsigned, forged or cross-organization request, or one whose organization is unknown, gets 401 in every environment and nothing is processed. If Nozle cannot read the key, the Engine answers 503 and Core retries. A signed webhook that names another organization’s subscription does not create that subscription’s credit grants.
Delivery, retries and ordering
- Respond with a
2xxwithin 30 seconds. Any other status, a timeout or a connection error is a failed attempt. - Nozle makes up to 3 attempts, the second about 3 seconds after the first and the third about 20 seconds after the second. After the third failure the webhook is marked failed and is not sent again.
- Delivery is at least once. Deduplicate on
X-Nozle-Unique-Key. - Order is not guaranteed. Treat a payload as the state of the object at that moment and read the object from the API when you need the latest.
- The signature does not contain a timestamp, so a replayed delivery cannot be rejected by its age. The unique key is what protects you from handling one twice.
- Return
200for event types you do not handle, so they are not retried.