Webhooks
How Wajub tells your server what happened, and how to trust it.
A webhook tells your server the outcome of a payment, a transfer or any other change, without you asking for it. Three rules make an integration correct; the rest of this section details them.
| Rule | Why |
|---|---|
| Verify the signature before reading the body | Anyone can POST to your URL |
| Answer inside 10 seconds, work afterwards | A slow handler is retried, so it duplicates |
| Key on the event id | The same event can legitimately arrive twice |
The envelope
Every delivery has the same shape. The payload never varies by event type, only data does.
The event type is in `event`, not `type`
Reading event.type gives you undefined, and a switch on it silently falls through to your
default branch. The field is named event. The SDKs hand back this envelope unchanged, so the
same rule applies whether you parse it yourself or not.
data is the full resource, byte for byte what GET /payments/{id} returns under transaction.
You never need a second call to learn what happened, though making one is a reasonable way to
re-check a payment you consider high value. Match an event to your own order through
data.reference, the reference you supplied, or data.metadata.
| Field | What it carries |
|---|---|
id | The event id, your deduplication key |
event | The type, for example payment.succeeded |
livemode | false in sandbox, true in live |
created | When the event was recorded, ISO 8601 |
api_version | The version the payload was serialised at |
pending_webhooks | How many endpoints this event is going to |
data | The resource itself |
The headers
X-Wajub-Signature: v1=8f3c1b0e4a7d...
X-Wajub-Timestamp: 1748081269
X-Wajub-Event: payment.succeeded
X-Wajub-Delivery-Id: whd_7Yh2MpL4tRb3nP8sZcXv
Content-Type: application/jsonThe first two are what you verify against. X-Wajub-Event lets you route before parsing, and
X-Wajub-Delivery-Id identifies the delivery of this event to this endpoint: it stays the same on
every retry, and differs from one endpoint to the next.
What happens end to end
- 1
You register an endpoint
A URL, in Konsole or through
POST /webhooks. A live endpoint must usehttps://; a sandbox endpoint may usehttp://. Each endpoint gets its own signing secret. - 2
Something happens
A payment succeeds, a transfer fails, a dispute opens. Wajub records an event.
- 3
Wajub posts it
Signed, to every endpoint subscribed to that type, with a 10 second timeout.
- 4
You answer 2xx
Anything else, or no answer in time, and the delivery is tried again for up to 72 hours.
Where to go next
| You want to | Read |
|---|---|
| Receive one on your laptop | Quickstart |
| Prove it came from Wajub | Signature verification |
| Know which events exist | Event catalogue |
| Understand a duplicate | Retries and failures |
| Decide against webhooks | Webhooks or polling |
You do not need a public URL to start
wajub listen --forward-to http://localhost:3000/webhooks streams live events straight to your
machine, signed the same way as production. The quickstart
starts there.