How The Kyshi API Works

Conventions that apply to every endpoint — envelopes, references, listing, and async behaviour.

These conventions hold across the whole API. Learning them once saves reading them on every endpoint page.

One Response Envelope

Every response uses the same shape, success or failure.

{
  "status": true,
  "message": "Success",
  "code": 200,
  "data": {}
}
FieldMeaning
statustrue on success, false on failure.
messageHuman-readable summary. Log it; do not branch on it.
codeMirrors the HTTP status code.
dataThe payload. {} on failure.

Branch on the HTTP status code and on status. Never branch on message — the wording can change without notice.

const res = await fetch(url, { headers: { 'x-api-key': key } });
const body = await res.json();

if (!res.ok || !body.status) {
  throw new KyshiError(res.status, body.message);
}

return body.data;

Versioning

Every public endpoint is namespaced under /v1:

https://api.kyshi.co/v1/transactions/initialize

The base URL is the same in test and live mode. Your key decides which one you are in. See Test Mode And Sandbox.

References Are Your Idea, Not Ours

Most creation endpoints accept a reference that you supply. Use your own order or invoice ID.

This matters more than it looks. Your reference is how you:

  • verify a payment without storing a Kyshi ID
  • reconcile a settlement batch back to your orders
  • recognise a webhook for something you already processed
{
  "email": "[email protected]",
  "amount": 1000,
  "localCurrency": "NGN",
  "reference": "ORDER-10001"
}

Then verify by the same reference:

GET {{host}}/v1/transactions/verify/ORDER-10001

References must be unique within a mode. Because test and live data are isolated, a reference used in test mode is free to reuse in live mode.

If you do not supply one, Kyshi generates it and returns it. Store whatever comes back.

Payments Are Asynchronous

A 201 means Kyshi accepted your request, not that the customer has paid. Almost nothing about a payment is decided at the moment you create it.

You callYou get backThe money arrives
Initialize transactionA checkout URLWhen the customer completes checkout
Charge (bank transfer)Payment instructionsWhen the customer makes the transfer
Create virtual accountAccount detailsWhenever the customer chooses to send
Initiate transferAn accepted payoutWhen the rail completes it

Design for the gap. Never release goods, credit, or access on the response to the creation call.

There are two ways to learn the outcome:

Webhooks tell you as soon as something changes. Fast, but a delivery can be missed. See Webhook.

Verification endpoints are authoritative. Slower, but definitive.

Use both: act on the webhook, confirm with verification before giving value, and reconcile periodically with the list endpoints to catch anything missed.

Listing And Filtering

List endpoints share a common set of query parameters.

ParameterDefaultNotes
page1Page number, starting at 1.
limit100Maximum 100.
orderDESCASC or DESC.
sortField to sort by.
queryFree-text search.
GET {{host}}/v1/transactions/history?page=1&limit=50&order=DESC

Because the default order is newest first, paging through a list while new records are arriving can shift rows between pages. For reconciliation, filter to a closed time range rather than walking pages of live data.

See Pagination And Filtering for the full detail.

Amounts

Amounts are in major units. 1000 means one thousand Naira. See Countries And Currencies.

Errors

Failures use the same envelope with status: false and an HTTP status code that tells you what kind of problem it is. 4xx means fix the request or the configuration; 5xx means Kyshi. See Errors.

Next


Did this page help you?