Skip to main content

Introduction

PesaHub notifies your application of payment and payout status changes by sending an HTTP POST request to the callback_url configured on your API token. Each request body is a JSON payload with an event field identifying what happened. Payment events:
  • payment.received — a payment completed successfully
  • payment.failed — a payment attempt failed
Payout events:
  • payout.completed — a payout was paid out to the beneficiary
  • payout.failed — a payout failed
  • payout.refunded — a payout was refunded by the provider
  • payout.reversed — a payout was reversed by the provider
Use the event field to branch your handling logic. Your endpoint should respond with a 2xx status once it has accepted the webhook — a non-2xx response or timeout is treated as a failed delivery and retried.
Because deliveries can be retried, your handler must be idempotent. A redelivered webhook carries the same payload, so don’t assume you’ll only ever see an event once.

Checksum verification

Every delivery is signed with an HMAC-SHA256 signature so you can confirm a webhook is genuinely came from PesaHub and wasn’t altered in transit.

Setting up your passphrase

Signing is enabled per API token. Set a passphrase on the token under Settings > API Access — this is the secret key used to sign every webhook delivered for that token.
If no passphrase is set, webhooks are still sent to your callback_url, but without a signature.

The signature header

Signed webhooks include a Pesahub-Signature header alongside the JSON body:

The algorithm

The signature is computed over the JSON payload as follows:
1

Canonicalize

Recursively sort object keys alphabetically at every nesting level. Sequential (list) arrays keep their original order; only associative objects are sorted.
2

Serialize

JSON-encode the canonicalized payload with slashes unescaped and no extra whitespace.
3

Hash

Compute HMAC-SHA256(json, passphrase) and take the 64-character hex digest.
Because canonicalization sorts keys recursively, the signature is stable regardless of field order — just decode the JSON and recompute over the resulting data.

Verifying a webhook

1

Read the request

Read the raw JSON body and the Pesahub-Signature header.
2

Decode the payload

Decode the JSON body into an associative array/object.
3

Recompute the signature

Recompute the signature over the payload using your passphrase as the key.
4

Compare signatures

Compare the recomputed value against Pesahub-Signature using a timing-safe comparison (e.g. hash_equals in PHP).
5

Reject on mismatch

Reject the request (401/403) if they don’t match, or if the header is missing while you have a passphrase configured.
Always verify the signature before acting on the payload (e.g. before crediting an order or updating a payout status).

Notes

  • If you rotate your passphrase, PesaHub immediately starts signing new deliveries with the new value — update your verification code at the same time.
  • Retried webhooks carry the same payload and therefore the same signature — a repeated signature does not indicate a replay attack.