Skip to main content
Webhooks let your application receive real-time HTTP callbacks when events occur on the Zeam platform. Instead of polling for changes, your server is notified automatically.
For background on why webhooks are required and how transactions move through states, see Event-driven design.

Setting up webhooks

Register a webhook endpoint

curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/webhook \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://your-domain.com/webhooks/zeam",
    "method": "POST"
  }' | jq

Manage webhooks

MethodPathPurpose
GET/v1/application/{id}/webhookList all webhooks
POST/v1/application/{id}/webhookAdd a webhook
PATCH/v1/application/{id}/webhook/{webhookId}Update a webhook
DELETE/v1/application/{id}/webhook/{webhookId}Remove a webhook
POST/v1/application/{id}/webhook/{webhookId}/rotate-secretRotate the signing secret

Verifying webhook signatures

Every webhook delivery is signed with your webhook secret using HMAC-SHA256. Always verify the signature before processing the payload.
1

Extract the signature

Read the signature from the delivery headers.
2

Compute the expected signature

Calculate HMAC-SHA256 over the raw request body using your current webhook secret.
3

Compare signatures

Use constant-time comparison. Reject the delivery if the signatures don’t match.

Using the Go SDK

The SDK provides constant-time webhook verification with replay protection:
import "github.com/ZeamMoney/zeam-sdk-go/webhook"

err := webhook.Verify(requestBody, signatureHeader, webhookSecret)
if err != nil {
    http.Error(w, "invalid signature", http.StatusUnauthorized)
    return
}
// Process the webhook payload

Rotating webhook secrets

Rotate your webhook secret periodically:
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/webhook/$WEBHOOK_ID/rotate-secret \
  -H "Authorization: Bearer $TOKEN" | jq
During rotation, the previous secret remains valid for a brief overlap period. Verify against both the current and previous secret to avoid rejecting deliveries during the transition.

Best practices

  • Respond with 200 quickly — acknowledge receipt before doing heavy processing. Queue the event for async handling.
  • Handle duplicates — webhook deliveries may be retried. Use the event ID for idempotency.
  • Verify every delivery — never process unverified webhook payloads.
  • Use HTTPS — webhook URLs must use HTTPS in production.
  • Rotate secrets regularly — treat webhook secrets like passwords.