Skip to main content
PeerPesa webhooks push real-time notifications to your server when something changes, such as a deposit confirming or an offramp payout completing. Instead of polling GET /transactions, register an HTTPS endpoint and PeerPesa sends a signed POST request for every event you subscribe to. This page covers managing endpoints, the event catalog, signature verification, and retries.

How webhooks work

1

Register an endpoint

Enter your webhook URL in the dashboard. PeerPesa checks that the URL is valid and returns 200, then gives you a webhook key.
2

Receive events

When an event occurs, PeerPesa sends a POST with a JSON body, signed with your webhook key in the X-Signature and X-Timestamp headers.
3

Verify and acknowledge

Verify the signature, return a 2xx status within 10 seconds, then process the event asynchronously.
Sandbox and production have separate webhook URLs and separate webhook keys. Register a URL in each environment, and verify each environment’s events with that environment’s webhook key.

Set up your webhook in the dashboard

1

Prepare your endpoint

Deploy a URL on your server that accepts POST requests and responds with HTTP 200. It must be a valid, publicly reachable URL.
2

Enter the URL

In the PeerPesa dashboard, open Settings > Webhooks and enter your webhook URL.
3

Pass URL validation

PeerPesa validates the URL format and sends a test request to it. The URL is saved only if your endpoint returns 200.
4

Copy your webhook key

After the URL is saved, the dashboard shows your webhook key. Store it securely, for example in an environment variable such as PEERPESA_WEBHOOK_KEY. You use it to verify signatures.
If the URL is malformed, unreachable, or returns anything other than 200 (including redirects, 201, or 204), the dashboard rejects it. Make sure your handler is live and returns 200 before you save the URL.
You do not have the webhook key until the URL is saved, so the validation request cannot be verified yet. Have your handler return 200 at setup, then turn on signature checks once you have stored the key.

Manage webhook endpoints

Register your webhook URL and get your webhook key in the dashboard, as described above. The endpoints below let you manage webhooks with the API. The same URL rules apply: the URL must be valid and return 200.

POST /webhooks

Registers a new endpoint.
string
required
Public HTTPS URL that receives events.
string[]
required
Event types to subscribe to. Use ["*"] to receive every event.
string
Label to identify the endpoint.
Response

Other endpoints

Event types

Transactions

Deposits and wallets

Quotes, beneficiaries, and account

Recurring payments

Event payload

Every event uses the same envelope. data.object contains the full resource at the time of the event.
transaction.completed
string
Unique event ID. Use it to deduplicate.
string
Event type from the tables above.
boolean
true for production, false for sandbox.
object
The resource the event describes.

Signature verification

Every webhook PeerPesa sends is signed so you can confirm it came from PeerPesa and was not modified in transit. Signed webhooks include two headers: The signature is computed with the webhook key shown in the dashboard after you saved your webhook URL:
Signature formula
For example, if X-Timestamp is 1784784828000 and the body is {"id":"evt_2p9x4m",...}, the signed string is 1784784828000.{"id":"evt_2p9x4m",...}.
1

Read the headers

Get X-Signature and X-Timestamp from the request. Reject the request if either is missing.
2

Build the signed string

Join the X-Timestamp value, a period (.), and the raw JSON request body exactly as received.
3

Compute the expected signature

Compute HMAC-SHA256 of the signed string using your webhook key, and hex-encode the result.
4

Compare and check freshness

Compare your result with X-Signature using a constant-time comparison. Reject events whose X-Timestamp is more than 5 minutes from your server time to block replayed requests.
Sign the raw request body exactly as received. Parsing and re-serializing the JSON changes spacing and key order, which produces a different signature.
The webhook key is separate from your API keys. Never use it to authenticate API requests, and never expose it in client-side code. If you change your webhook URL or the key is regenerated in the dashboard, update the key in your handler.

Retries and best practices

  • Return a 2xx status within 10 seconds. Any other response or a timeout counts as a failure.
  • Failed deliveries are retried with exponential backoff for up to 3 days (about 1m, 5m, 30m, 2h, 6h, then every 12h).
  • After repeated failures, the endpoint is set to disabled and you are notified by email. Re-enable it with PATCH /webhooks/{id}.
  • Events can arrive more than once or out of order. Deduplicate on event id and re-fetch the resource with the API if you need the latest state.
  • Only accept requests with a valid signature, and use HTTPS for every endpoint.