KetaPay sends events to the endpoints you register on the dashboard’s Developers page or with POST /webhook_endpoints. Most integrations need one endpoint that receives every event: register it without enabled_events and ignore the types you don’t handle.

Events

Each event’s payload is in the API reference.

Verify the signature

Each delivery is a POST with the event as its JSON body and a signature header:
v1 is the hex HMAC-SHA256 of "{t}.{raw request body}", keyed with the endpoint’s signing secret (whsec_...). The libraries check it for you, against the raw body, in constant time, rejecting timestamps older than 5 minutes:
Laravel verifies every delivery before your listeners run (see Laravel).

Delivery rules

  • Respond with any 2xx within 10 seconds. Anything else is retried with exponential backoff for 3 days, after which the endpoint is marked failing and its owner is emailed.
  • Events can arrive more than once and out of order. Deduplicate on id, and fetch the object (GET /escrows/{id}) when you need the current state.
  • Treat an event as a hint: fetch the object before acting on large amounts.
  • Send yourself a test event with POST /webhook_endpoints/{id}/test.

Rotating the secret

POST /webhook_endpoints/{id}/rotate_secret issues a new secret. For 24 hours both secrets sign every delivery and the header carries one v1 per secret (t=...,v1=<new>,v1=<old>): accept the request if any v1 matches. In Node, pass both: verify(body, header, [newSecret, oldSecret]).