Connect your systems to KODA. Create intents, verify codes, receive signed webhooks — over a simple, key-authenticated REST API. Calls are metered against your plan; verifications draw down prepaid ACU.
Sign in → Developers → Create API key. The secret is shown once.
Send Authorization: Bearer sk_… (or X-API-Key) on every request.
Hit the endpoints below. Watch usage and ACU in your dashboard.
Base URL https://kodajnn.com/v1 Sandbox https://kodajnn.com/v1 Auth Authorization: Bearer sk_live_xxx (or) X-API-Key: sk_live_xxx curl -H "Authorization: Bearer sk_test_..." https://kodajnn.com/v1/ping
| Method | Path | Description |
|---|---|---|
| GET | /ping | Verify a key and see the merchant it unlocks. |
| POST | /intents | Create a payment intent (amount, currency, operators, expiry). |
| GET | /intents/{id} | Poll intent status. |
| POST | /intents/{id}/verify | Submit the customer's reference code or screenshot. |
| POST | /intents/{id}/cancel | Cancel an awaiting intent. |
| GET | /checkout/{id}?cs= | Customer-facing intent read, authorised by the intent's own client_secret — no API key. Powers the hosted page & widget. |
| POST | /checkout/{id}/verify | The customer submits their SMS code; on success returns the redirect so the order moves forward automatically. |
| GET | /receipts | Filterable ledger of verified payments with audit traces. |
| POST | /sandbox/sms | Inject an operator-formatted SMS and watch KODA structure it. |
| GET | /billing/balance | Prepaid ACU balance. (read:usage) |
| GET | /agents | List the AI agents you can run and their ACU cost. (read:agents) |
| POST | /agents/{type}/run | Run a KODA agent — reconciliation report, trust lookup, dispute evidence, or screenshot extraction. Consumes prepaid ACU. (run:agents) |
| GET | /usage | Your monthly quota, usage and ACU balance. (read:usage) |
| Scope | Grants |
|---|---|
read:receipts | Read the verified-payments ledger |
read:agents | List the AI agent catalogue |
run:agents | Run AI agents (consumes ACU) |
read:usage | Read API usage & ACU balance |
write:intents | Create payment intents. Publishable pk_ keys get only this scope — safe to ship in the browser: they can start a payment, never read your data. |
* | Full account scope (sk_ keys). Restricted rk_live_ keys default to read-only — e.g. a read-only reconciliation key for your accountant. |
Add "Pay by mobile money" to any website or marketplace. The customer picks their operator, pays, pastes the SMS code they received into a KODA panel, and KODA verifies it — then the order moves forward on its own. Two integration paths:
Your server creates the intent with your secret key and gets back a checkout_url + client_secret. Send the customer to the URL, or open it in the widget overlay:
amount is an integer in the currency's minor unit — the same convention as Stripe. 589 USD means $5.89. Zero-decimal currencies have no fractional part, so the amount is the whole number: 25000 CDF is 25 000 FC. KODA shows the customer the natural amount and matches it against the operator SMS.
// your server (secret key) — never exposes anything to the browser
POST /v1/intents { "amount": 25000, "currency": "CDF", // 25 000 FC
"operators": ["orange_cd","mpesa_cd"],
"metadata": { "order_id": "CMD-1042" },
"success_url": "https://shop.example.com/order/success" }
→ { "intent_id": "int_…", "client_secret": "cs_…",
"checkout_url": "https://kodajnn.com/pay/int_…?cs=cs_…" }
// USD example: { "amount": 589, "currency": "USD" } → the customer pays $5.89
<script src="https://kodajnn.com/js/koda.js"></script>
<script>
Koda.checkout({
checkoutUrl: '<checkout_url from your server>',
onVerified: function (r) { window.location = '/order/success'; }
});
</script>
No backend call needed — a pk_ key can only create intents, so it is safe in the page. The widget creates the intent and opens the overlay for you:
<script src="https://kodajnn.com/js/koda.js"></script> <button data-koda-key="pk_live_…" data-koda-amount="25000" data-koda-currency="CDF" data-koda-operators="orange_cd,mpesa_cd" data-koda-order="CMD-1042" data-koda-success-url="https://shop.example.com/order/success"> Payer par mobile money </button>
// or call it directly
Koda.pay({ key: 'pk_live_…', amount: 25000, currency: 'CDF',
operators: ['orange_cd','mpesa_cd'], orderId: 'CMD-1042',
successUrl: 'https://shop.example.com/order/success',
onVerified: function (r) { /* r.receipt_id, r.amount — advance the order */ } });
Behind the scenes the money path is unchanged: the code is matched against the Sentinel SIM ledger, scored by the fraud engine, checked for replay, and a signed payment.verified webhook fires to your server — the browser hand-off is a convenience on top, never the source of truth.
Retry-After.run:agents) consume prepaid ACU at the agent's published rate; an empty balance returns HTTP 402 — after a 72 h merchant-protective grace buffer.TEST-OK-25000 → instant payment.verified TEST-LATE-90 → verifies after 90 s (payment.verified.late) TEST-REPLAY → code_already_used TEST-SUFFIX → msisdn_suffix_mismatch → challenge flow
Human-readable API reference → · machine-readable contract: /v1/openapi.json (import into Postman or generate an SDK). North-star: first verified payment < 10 minutes from signup.
Door 3 is plain HTTPS — it works in any website or app. Ready-made drop-ins and snippets:
/v1/intents then open the checkout_url in a WebView.checkout_url in a Custom Tab / SFSafariViewController.x-koda-signature = HMAC-SHA256 of the raw body).