Skip to main content
A webhook is a URL you register so Natural can push Events to your server as they happen, instead of you polling for changes. When a payment completes, a deposit lands, or a customer connects, Natural sends the event to your URL. Each webhook subscribes to the event types you choose, every delivery is signed with the webhook’s secret so you can verify it came from Natural, and failed deliveries are retried. Natural signs every delivery with the Standard Webhooks spec; verify it before trusting the payload. See the Event catalog for every event type and its full payload.

1. Register an endpoint

POST /webhooks registers your URL and subscribes it to event types. The signing secret is returned once in the response; store it immediately.
enabledEvents accepts any event type from the Event catalog, or the wildcard "*" (which must be the only entry). description and tags are optional.
The signingSecret (whsec_...) appears only in this response. If you lose it, rotate it with POST /webhooks/{webhookId} /rotate-secret.

2. Verify the signature

Every delivery is a POST whose JSON body is the event object. Three signature headers ride on each delivery (lowercase, per the Standard Webhooks spec): Always verify before trusting a payload. Use the official standardwebhooks library (Python and Node); construct it with your whsec_ secret and pass the raw body plus headers. verify returns the parsed event, or raises on a bad signature:
Verify against the raw request body, the exact bytes Natural sent. Parsing and re-serializing the JSON first changes the bytes and breaks verification.
The library handles two details for you: it rejects deliveries whose webhook-timestamp is outside a tolerance window (replay defense), and it accepts a delivery if any of the space-separated signatures verifies, which is what lets a secret rotation overlap two valid secrets.
The signed content is the string {webhook-id}.{webhook-timestamp}.{body}. Strip the whsec_ prefix from the secret, base64-decode the remainder for the HMAC key, compute HMAC-SHA256, and base64-encode the result. Compare it against each space-separated v1,<sig> entry.

3. Delivery, retries & failures

Natural treats any 2xx response as success. The delivery request times out after 30 seconds. Failed deliveries (non-2xx, network error, or timeout) are retried up to 7 attempts total with jittered backoff (~20% jitter):
An endpoint that fails every attempt for 5 consecutive events is automatically disabled. Re-enable it with PATCH /webhooks/{webhookId} once your endpoint is healthy.

4. Redeliver events

The webhook-id header contains the event ID (evt_...). You can also find events with GET /events and GET /events/{eventId}. You can redeliver an event to a webhook for up to 90 days after the event was created, provided that webhook was one of the event’s original destinations. The endpoint must be enabled, and another manual redelivery for the same event and webhook cannot already be in progress. For a delegated event, the exact delegation that authorized the original delivery must still be active and grant access to that event type. Revoking it permanently closes redelivery for that event and webhook; creating a new delegation does not reopen it. POST /webhooks/{webhookId}/events/{eventId}/redeliver sends the stored event once and returns 202 Accepted with the pending redelivery. It takes no request body and requires an Idempotency-Key header.
A redelivery keeps the original event payload and webhook-id, but uses the webhook’s current URL and active signing secret with a fresh webhook-timestamp and signature. Treat it as a possible duplicate, and do not assume it will arrive in order relative to other events. Automatic retries continue independently, even when the manual redelivery succeeds. The automatic and manual sends can overlap, and another copy can arrive later. A manual failure does not contribute to automatic endpoint disabling. A delegated redelivery is sent only to the same developer webhook that received the original delivery. It does not fan out to the customer’s webhooks or any other endpoint. Natural checks the original delegation again immediately before transmission. If it is no longer valid, the redelivery is marked CANCELED and no request is sent. If authorization is temporarily unavailable, Natural retries that check for a bounded period without consuming the manual attempt; no request is sent unless authorization succeeds.

Best practices

  • Return 2xx fast. Acknowledge as soon as the signature verifies, then process the event asynchronously; slow handlers risk the 30-second timeout and trigger retries.
  • Deduplicate on webhook-id. Retries reuse the same webhook-id, and Natural may deliver an event more than once; record processed IDs and skip duplicates.
  • Store the whsec_ secret in a secrets manager, never in source control. Rotate it with POST /webhooks/{webhookId}/rotate-secret; the previous secret stays valid for the grace period you specify, so both signatures arrive during the overlap.
  • Don’t depend on event ordering. Retries and independent delivery mean events can arrive out of order; use the version field on the resource snapshot, or refetch the resource, when ordering matters.