Skip to main content

Overview

When a transaction reaches a terminal state (succeeded or failed), winam-payments sends a POST JSON request to your callback_url. A late deposit confirmation (operator SMS/USSD arriving after the transaction expired or failed) does not auto-credit: the transaction first moves to requires_manual_resolution and waits for a Winam operator decision. The webhook is sent only once that decision resolves it to succeeded (payment.succeeded) or failed (payment.failed). See State Machine.
Webhooks are the recommended way to receive payment outcomes — faster and more reliable than polling. Always provide a callback_url in your deposit and withdrawal requests.

Webhook payload

Signature verification

Each webhook includes an X-Winam-Signature header containing a JWT RS256 token signed with Winam’s private key. Always verify this signature before processing the webhook.
1

Fetch the public key (once)

Cache this response — the key rotates rarely.
2

Verify the signature

Retry policy

winam-payments retries 3 times with exponential backoff (1 s → 2 s → 4 s) if your endpoint responds with a status ≥ 400 or does not respond within 5 seconds. Your endpoint must:
  • Respond 2XX within 5 seconds
  • Be idempotent — the same winam_tx_id may be delivered more than once
  • Return 200 even if the event was already processed
If all retries fail, no further delivery attempts are made. Use Replay Webhook for manual recovery.
For the public key endpoint reference, see Callback Public Key.