Overview
When a transaction reaches a terminal state (succeeded, failed or, for deposits, expired), winam-payments sends a POST JSON request to your callback_url.
Payments confirmed after expires_at
What happens when a deposit is paid late depends on its collection mode:
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 carries anX-Winam-Signature header computed with your application’s webhook secret (given to you once by Winam when your application is registered or its secret is rotated):
raw_body is the exact raw bytes of the HTTP request body, as received. Do not parse and re-serialize the JSON before verifying: any change in spacing or key order breaks the signature.
Always verify the signature before processing the webhook:
- Parse
tandv1from the header. - Reject the request if
|now - t|exceeds 5 minutes (replay protection). - Compute
HMAC-SHA256(webhook_secret, t + "." + raw_body)and compare it tov1with a constant-time comparison. - Only then parse the JSON body.
Secret rotation. When Winam rotates your webhook secret, the new secret is given to you once and is used for all webhooks sent from then on. Update your secret before or right after the rotation; a webhook rejected during the switch can be re-sent with Replay Webhook.
Legacy JWT signature
The former JWT RS256 signature is still sent when Winam has it enabled, but in a different header:X-Winam-Signature-Jwt (it used to be sent in X-Winam-Signature). It can be verified with the public key from Callback Public Key. New integrations should verify the HMAC X-Winam-Signature above.
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
2XXwithin 5 seconds - Be idempotent — the same
winam_tx_idmay be delivered more than once - Return
200even if the event was already processed

