Webhooks
Intro
Khaime sends an HTTP POST request to your webhook URL whenever a notable event happens on your account — a payment succeeds, a subscription renews, a payout settles, a dispute opens. Webhooks are the most reliable way to track transaction state; don’t rely solely on redirect callbacks, since a customer can close their browser before the redirect fires.Context
Webhooks are configured per Partner API key (sandbox or live), so sandbox activity notifies your sandbox webhook URL and live activity notifies your live one. You set the URL and read the signing secret from the same place you manage API keys. This page is the entry point for the webhooks documentation. Once you understand the envelope and delivery model here, go to:- Events — the full catalog of event types and payload shapes
- Signature Verification — how to confirm a request really came from Khaime
- API Versioning — how payload schemas change over time
- Best Practices — patterns for reliable handling
Hows
Setup
- Go to Khaime Dashboard → Settings → API
- Set your Webhook URL (e.g.,
https://yoursite.com/webhooks/khaime) - Copy your Webhook Secret (
whsec_...)
Envelope structure
Every webhook delivery shares the same outer envelope regardless of event type:The
event_id is the idempotency key. You must store processed event_id values and skip duplicates — retries reuse the same event_id.Webhook headers
Every webhook request includes these headers:Delivery
Shared data types
These types appear across multiple event payloads.MoneyAmount
All monetary values are in the smallest currency unit (cents for USD, kobo for NGN). Never floats.MulticurrencyBreakdown
Present on payment and order events. Provides a full breakdown of amounts, fees, and currency conversion.conversion is omitted and customer_paid equals merchant_gross.
Customer
id field is present only if the customer has a platform account.
Example handler
Whys
Webhooks exist because payment, subscription, and settlement state changes asynchronously and often outside the request/response cycle your customer is in — a bank transfer settles hours later, a dispute is opened by a card network days later, a subscription renews on a schedule with no customer present at all. A redirect callback only covers the moment right after checkout; it can’t tell you about anything that happens afterward. The envelope carries a stableevent_id specifically so retries are safe to replay: delivery is at-least-once, not exactly-once, so your handler has to be idempotent rather than relying on the network to deliver each event exactly one time. Signing over the raw request body (rather than a parsed-and-reserialized one) means the check only depends on bytes you actually received, with no dependency on your JSON library preserving key order or whitespace.
Why nots
Webhooks are not a substitute for reconciliation. Delivery to your endpoint can fail — DNS issues, deploys, firewall rules — and after 3 attempts Khaime stops retrying. For payments created through the Charge API, treat the webhook as the primary signal but don’t assume silence means nothing happened; if you must be certain, check the record directly (see Best Practices). Khaime does not guarantee webhook delivery order across event types — apayment.succeeded and its companion wallet.credited are fired independently, so design handlers that don’t assume strict ordering between related events. Webhooks also don’t carry a response contract beyond the HTTP status code: whatever your endpoint returns in the body is logged for debugging but never parsed or acted on.