JKAPay API

JKAPay is a payment infrastructure platform for Ghana. Accept mobile money, manage merchants, and integrate with a single unified API — JKAPay routes payments securely to mobile networks and banks behind the scenes.

Authentication

All API requests are authenticated with a Bearer secret key.

Read more
Quickstart

Accept your first payment in under five minutes.

Start building
Webhooks

JKAPay forwards normalised events to your endpoint with HMAC-signed payloads and automatic retries.

Configure webhooks
API reference

Every endpoint, parameter, and response field — fully documented.

Browse the API

Base URL

Every JKAPay API request goes to a single base URL:

  • https://api.jkapay.com

Test keys (sk_test_…) and live keys (sk_live_…) hit the same URL — JKAPay reads the prefix and routes your request through the sandbox simulator or the live mobile-money networks accordingly. You can switch between the two by changing the secret you load. There is no separate sandbox host, port, or header.

API conventions

  • JSON only. All requests and responses use application/json.
  • Money is in cedis. You may pass amounts as integers in pesewas (e.g. 1500 = GHS 15.00) or as GHS strings ("15.00"). Responses always return GHS strings to avoid floating-point drift.
  • Idempotency. Pass idempotencyKey on every write to safely retry without double-charging. Repeating the same key returns the original transaction.
  • JKAPay reference. JKAPay generates a unique reference per transaction (e.g. JKA_M3A8_8F2E1B…). Treat this as the primary key on your side. Returned in every response and every webhook.
  • Client reference. Pass your own identifier as merchantRef on initialize — JKAPay returns it as clientReference in responses and webhooks so you can correlate against your own order or invoice numbers.
  • Test vs live. Keys prefixed sk_test_ route through the sandbox simulator — no real money moves and specific phone-number endings trigger specific outcomes. Keys prefixed sk_live_ settle real payments. The wire format is identical; switch by changing the secret you load.
  • Errors. All errors return a JSON body with error.code and error.message. See Errors.