1. Webhooks
Kutanapay Merchant API
  • Getting Started
  • Authentication
  • Use the API in your application
  • Webhooks
    • Webhooks Events
  • Merchant Checkout
    • Create checkout
      POST
    • List checkouts
      GET
    • Get checkout
      GET
    • Cancel checkout
      POST
    • Create checkout button embed session
      POST
  • Webhook Events
    • Checkout created
    • Checkout paid
    • Customer says they paid
    • Checkout approved
    • Checkout rejected
    • Checkout failed
    • Checkout timed out
    • Checkout expired
    • Checkout refunded
    • A second collection arrived
    • Test event
  • Schemas
    • RequestBodies
      • CheckoutEvent
    • DetailError
    • WebhookEnvelope
    • CheckoutEventData
  1. Webhooks

Webhooks Events

Register webhooks in the merchant platform (URL, secret, subscribed events). KutanaPay delivers POST requests to your HTTPS endpoint. This page describes the payload you receive.

Delivery envelope#

Every event uses the same top-level JSON shape:
FieldTypeDescription
versionstringPayload format version. Currently v1.
event_typestringEvent name, e.g. checkout.paid.
timestampstringISO-8601 UTC when the event was emitted.
idempotency_keystringUnique per delivery. Store it to avoid processing twice.
merchant_idstringYour business id in KutanaPay.
dataobjectEvent-specific fields (tables below).

HTTP headers#

Verify X-Webhook-Signature with your webhook secret before using the body.

Recommended subscriptions (hosted checkout)#

For a typical hosted checkout integration, subscribe in the platform to:
EventWhy
checkout.paidCustomer payment recorded. Often used to mark an order paid.
checkout.approvedBank-transfer checkout approved after review (when applicable).
checkout.rejectedBank-transfer checkout rejected.
checkout.createdOptional audit trail when a checkout session is created.
Use checkout.paid and/or checkout.approved depending on payment method; confirm fulfillment rules with your KutanaPay contact.
Do not rely on events marked not subscribable yet until they appear in the platform event picker.

Checkout events#

Subscribable today (live in catalog)#

These can be selected when configuring a webhook in the platform.

checkout.created#

Emitted when a checkout is created (from the merchant platform or programmatic API).
Field in dataTypeRequiredDescription
checkout_idstringyesCheckout id or payment reference.
amountnumberyesAmount in checkout currency.
currency_codestringyesCurrency code.
statusstringyesCheckout status at emit time.
customer_emailstringnoCustomer email when present.

checkout.paid#

Emitted when customer payment is recorded for the checkout.
Same fields as checkout.created, plus:
Field in dataTypeRequiredDescription
paid_atstringnoWhen payment was recorded (ISO-8601).

checkout.approved#

Emitted when a bank-transfer checkout is approved after review.
Uses the same core checkout fields as checkout.created.

checkout.rejected#

Emitted when a bank-transfer checkout is rejected.
Uses the same core checkout fields as checkout.created.

In catalog but not subscribable yet#

You may see these in documentation or future platform releases. They cannot be added to subscribed_events until marked available in the platform.
EventMeaning
checkout.expiredCheckout expired before payment (expiry job may emit; subscription coming later).
checkout.completedTerminal success state (reserved).
checkout.failedPayment attempt failed (reserved).

Example: checkout.paid#

{
  "version": "v1",
  "event_type": "checkout.paid",
  "timestamp": "2026-03-26T14:22:01.000000Z",
  "idempotency_key": "8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d",
  "merchant_id": "7bb54443-6fc9-4a1d-ab46-d787ec90c87f",
  "data": {
    "checkout_id": "c4e8b1a2-9f3d-4e7a-b6c5-1d2e3f4a5b6c",
    "amount": 150.0,
    "currency_code": "GHS",
    "status": "paid",
    "customer_email": "ama.mensah@acmecustomer.com",
    "paid_at": "2026-03-26T14:22:00.000000Z"
  }
}
data may include additional checkout fields from your tenant schema; treat unknown keys as optional.

Other catalog events (platform / treasury)#

These exist in the event catalog for future or internal use. They are not subscribable yet unless the platform lists them. Hosted checkout integrators usually ignore them.
EventCategorySummary
deposit.receivedMoneyFunds credited to merchant wallet (reserved).
payout.processedMoneyPayout completed (reserved).
withdrawal.completedMoneyWithdrawal completed (reserved).
settlement.completedMoneySettlement batch completed (reserved).
user.invitedTeamTeam invite sent (reserved).
user.joinedTeamTeam member joined (reserved).
test.eventSystemTest delivery from the platform test action.

Subscribing to events#

In the merchant platform, when you configure a webhook:
Empty or “all events” (if offered): delivers every live catalog event your endpoint is allowed to receive.
Explicit list: only listed types are delivered, e.g. ["checkout.paid", "checkout.approved"].
Unknown or not-yet-live event names are rejected when saving webhook configuration.

Handler reminders#

1.
Verify signature on the raw body.
2.
Dedupe on idempotency_key.
3.
Return 2xx quickly; retry on 5xx only for transient errors.
4.
Fulfill orders idempotently
Modified at 2026-09-26 21:46:22
Previous
Webhooks
Next
Merchant Checkout
Built with