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

    Checkouts

    Checkouts let you send your customer to a hosted payment page on KutanaPay to pay you. One checkout is one payment session: create it from your server, share the checkout_url, and track the outcome with webhooks (and optional API reads).
    If you have not done so yet, read Authentication (API keys) and Webhooks (callbacks and signatures) before building this flow.

    What hosted checkout is#

    Your backend calls POST /api/v1/merchants/checkouts (API host, e.g. https://dev.kutanapay.com).
    KutanaPay returns data.checkout_url: a link to the customer-facing app (not the API host).
    The customer opens that link in a browser and pays on the hosted page.
    Your webhook handler receives events such as checkout.paid and updates your order.
    The customer never sees your x-api-key. Only your server uses the key.

    What the customer sees#

    With one API call and one link, the customer can pay you.
    1.
    Open the link you sent (email, SMS, or redirect from your site).
    2.
    Choose how to pay (mobile money, bank transfer, or other methods enabled for that currency).
    3.
    Complete payment on the hosted page (for example approve a mobile money prompt on their phone).
    4.
    Success or closed state on the page; your branding redirect URL may send them back to your site when configured in the merchant platform.
    Screens and methods depend on currency, KYB, and branding on your merchant account.

    Creating and using a checkout#

    Step 1: Create the checkout#

    Send a request to POST /api/v1/merchants/checkouts with header x-api-key.
    Typical e-commerce order (fixed amount and currency):
    Minimal request (only required fields):
    {
      "customer_email": "customer@example.com",
      "amount": 99.99,
      "currency_code": "GHS"
    }
    You receive a response immediately:
    {
      "status": "success",
      "message": "Checkout created",
      "data": {
        "id": "c4e8b1a2-9f3d-4e7a-b6c5-1d2e3f4a5b6c",
        "merchant_id": "7bb54443-6fc9-4a1d-ab46-d787ec90c87f",
        "customer_email": "customer@example.com",
        "amount": 150.0,
        "currency_code": "GHS",
        "status": "pending",
        "payment_reference": "PAY-K7M2Q9X4",
        "checkout_url": "https://dev.kutanapay.com/public/checkouts/PAY-K7M2Q9X4#token=9f3e2a1b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2",
        "expires_at": "2026-03-26T12:40:00.000000",
        "created_at": "2026-03-26T12:30:00.000000"
      }
    }
    Store in your system before redirecting the customer:
    FieldUse
    data.idCheckout UUID for GET .../checkouts/{id} and cancel
    data.payment_referenceHuman-readable ref (PAY-…)
    data.checkout_urlFull link to send to the customer
    meta_data.order_id (if you sent it)Tie webhooks back to your order
    The checkout_url host comes from KutanaPay configuration (DOMAIN_NAME on the API). Use the URL exactly as returned. Do not build links from payment_reference alone.

    Request parameters#

    ParameterRequiredBehaviour
    customer_emailYesCustomer email
    amountYesPositive number
    currency_codeYesSupported code: GHS, KES, NGN, USD, EUR, GBP, ETB, etc.
    customer_nameNoShown where supported
    customer_phoneNoUseful for mobile money flows
    descriptionNoShort label for the payment
    expires_in_minutesNoOverrides default session lifetime
    meta_dataNoYour JSON; included in webhook payloads where applicable
    Supported currencies and payment methods depend on your merchant account and KYB.

    Step 2: Send the customer to the payment page#

    Forward the customer to data.checkout_url.
    Common patterns:
    PatternExample
    HTTP redirectAfter create, respond with 302 Location: {checkout_url}
    Pay buttonLink href="{checkout_url}" on your site
    Email / SMSPaste the full URL including #token=...
    The hosted page loads the session using the token in the URL, then calls KutanaPay public checkout APIs with header X-Checkout-Token. That token is not your merchant API key.
    Important: If the link is missing the #token= fragment (or legacy ?token=), the hosted page cannot open. Always use checkout_url from the create response.
    Email clients: Some clients handle URL fragments poorly. Prefer redirect from your website after the customer clicks "Pay", or open the link from your own domain flow.

    Step 3: Track checkout status#

    A checkout has its own lifecycle. Prefer webhooks for fulfillment.
    ApproachWhen to use
    Webhook checkout.paid (and related events)Primary: mark orders paid, send receipts
    GET /api/v1/merchants/checkouts/{checkout_id}Polling or support tools
    GET /api/v1/merchants/checkoutsList recent sessions
    Example poll:
    Subscribe to webhook events in the merchant platform. See Webhook event reference for payload fields.

    Step 4: Cancel an unused checkout#

    If the customer should not pay anymore and the checkout is still pending, call:
    Paid or completed checkouts cannot be cancelled.

    Checkout lifecycle#

    Statuses on the checkout record (exact set can vary by payment rail):
    StatusMeaning
    pendingCreated; waiting for customer payment
    awaiting_payment_initiationPayment flow starting
    processingPayment in progress (e.g. STK push sent)
    paid / completedPayment recorded
    failedPayment failed
    cancelledCancelled (merchant or customer flow)
    expired / timeoutSession or provider timeout
    Treat checkout.paid (webhook) as the main signal to fulfill orders. Use GET .../checkouts/{id} when you need to reconcile or recover from a missed webhook.

    Return to your website#

    If you set a success redirect URL in merchant platform branding, the customer may be sent there after a successful payment. That URL is separate from checkout_url.
    Do not rely only on the customer landing on your site. Always confirm payment with webhooks or a authenticated GET checkout call.

    How to find out the result#

    1.
    Webhook (recommended)
    Verify X-Webhook-Signature, read event_type, use idempotency_key so you process each delivery once.
    See Webhooks and Webhook event reference.
    2.
    Poll checkout
    GET /api/v1/merchants/checkouts/{checkout_id} with x-api-key.
    3.
    After expiry
    Pending checkouts can expired. Handle checkout.expired or failed events if you subscribed to them.

    Keeping your system consistent#

    Handle statuses defensively:
    Paid: webhook checkout.paid (or checkout status paid / completed) → mark order paid.
    Still open: pending, processing → keep order pending; wait or poll.
    Closed without pay: cancelled, expired, failed → do not fulfill; let customer create a new checkout if needed.
    Network errors on create: If you are unsure whether create succeeded, use GET .../checkouts/{id} only if you stored data.id. If you never got a response and have no id, list checkouts or create a new session according to your idempotency rules.
    Idempotency on webhooks: Store idempotency_key from each delivery before updating orders.

    End-to-end example (merchant server)#

    1. Customer clicks "Pay" on your site (order ORD-7842).
    2. Your server POST /api/v1/merchants/checkouts with amount, currency, customer_email, meta_data.order_id.
    3. Your server saves data.id and redirects browser to data.checkout_url.
    4. Customer pays on hosted KutanaPay page.
    5. Your webhook handler receives checkout.paid → verify signature → mark ORD-7842 paid.
    See Use the API in your application for curl and Apidog Try it.

    Branding, KYB, and go-live#

    Logo, colors, and redirect URL are set in the merchant platform. Production checkouts may require approved KYB.

    API reference#

    OpenAPI on this site lists the four checkout endpoints with JSON examples (no full schema catalog):
    POST /api/v1/merchants/checkouts
    GET /api/v1/merchants/checkouts
    GET /api/v1/merchants/checkouts/{checkout_id}
    POST /api/v1/merchants/checkouts/{checkout_id}/cancel

    What to do next#

    StepGuide
    Configure webhooksWebhooks
    Event payloadsWebhook event reference
    Try requests in ApidogUse the API in your application
    Modified at 2026-09-26 21:58:52
    Previous
    Webhooks Events
    Next
    Create checkout
    Built with