Skip to main content

Payment Callback Integration Guide

When a transaction reaches a final state, GoPay sends a signed HTTP POST to the notifyUrl / notify_url you supplied when initiating it. Callbacks reflect the already-settled state of a transaction — they are the authoritative result, unlike browser redirects which can be lost or forged.

Callback Types

C2B Callbacks

Notifications for payments made by customers to your business

B2C Callbacks

Notifications for payouts/disbursements made from your business to customers

Webhook Requirements

Your webhook endpoint must:
  • Use HTTPS — plain HTTP notify URLs are rejected at initiation time and callbacks are never sent over HTTP
  • Be publicly reachable — GoPay refuses to deliver to private, loopback, or link-local addresses
  • Accept HTTP POST requests and return a 2xx status code for successful receipt
  • Respond within 10 seconds — acknowledge first, process asynchronously
  • Not rely on redirects — GoPay does not follow 3xx responses; a redirect counts as a failed delivery

Security Headers

Every callback is signed with GoPay’s gateway Ed25519 private key. You verify it with the corresponding gateway public key, which you receive during onboarding. There is no shared secret: the signature proves the callback came from GoPay, and nothing you store can be used to forge one.

Signature Verification

The signature covers the v1 canonical string (lines joined with \n, no trailing newline):
Verification steps:
  1. Read the raw request body bytes (before any JSON parsing) and compute the lowercase hex SHA-256
  2. Rebuild the canonical string using your registered notify URL’s host, path, and query — if you are behind a proxy or load balancer, use the URL you registered, not the incoming Host header
  3. Strip the ed25519= prefix from X-Signature and base64-decode the 64-byte signature
  4. Verify with the GoPay gateway public key
  5. Reject stale timestamps (e.g. older than 5 minutes) and X-Request-ID values you have already seen

Retry Policy

  • Failed deliveries are retried up to 5 times with increasing delays: 5s, 30s, 2m, 10m, 30m
  • Only HTTP 2xx responses count as successful; timeouts, errors, and redirects are all failures
  • After all retries are exhausted, the callback is parked for manual review — contact support to redrive it
Make your webhook handler idempotent. Retries mean you can receive the same callback more than once — dedupe on X-Request-ID (per delivery) or on txnId + status (per settlement event).

Status Values

All statuses delivered by webhook are final — a transaction never moves out of one of these states.

Key Rotation

GoPay periodically rotates the gateway signing key. During a rotation window both keys are active:
  1. X-Signature-Key-ID tells you which key signed each callback
  2. Keep a small map of key ID to public key, and verify against the matching one
  3. New public keys are announced ahead of time through the merchant dashboard

Testing Your Webhook

  • ngrok — for local development tunneling (remember: the tunnel URL must be HTTPS)
  • curl — for wiring checks before signatures are involved
A correct implementation rejects this request with 401 (the signature is invalid) — that is the expected result. To exercise the success path end to end, use the sandbox environment described in the Testing Guide.