Skip to main content

Kuda Business API Request Format and Environments

Understand the Kuda request envelope, UAT and production URLs, request references, and service type rules.

Written by Nosa O

Most Kuda Business API operations use the same HTTP endpoint and request envelope. You choose the operation by setting serviceType.

Base URLs

Use UAT for testing and production only after your workflow has been validated.

Bank codes, bill catalogs, and test data can differ between environments. Always test and fetch reference data in the same environment where you will submit the request.

Request envelope

A standard request has three top-level fields:

Field

Type

Description

serviceType

string

The operation you want to run.

requestRef

string

Your unique reference for tracking and reconciliation.

data

object

The operation-specific payload.

Example:

curl -X POST "https://kuda-openapi-uat.kudabank.com/v2.1" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "serviceType": "BANK_LIST",
    "requestRef": "BANK001",
    "data": {}
  }'

serviceType rules

Use uppercase serviceType values.

Examples:

  • BANK_LIST

  • NAME_ENQUIRY

  • SINGLE_FUND_TRANSFER

  • TRANSACTION_STATUS_QUERY

  • GET_BILLERS_BY_TYPE

  • ADMIN_PURCHASE_BILL

  • BILL_TSQ

  • ADMIN_CREATE_DYNAMIC_COLLECTION_ACCOUNT

requestRef rules

Your requestRef is important. It helps you:

  • identify the request in your own logs

  • reconcile pending transactions

  • run status queries

  • prevent accidental duplicate submissions

  • support customer or operations investigations

Use a short, unique reference. Avoid very long references, UUID-style values, or descriptive strings with many special characters for money movement calls.

Good examples:

TRF20260603001
BILL20260603001
BULK20260603001
DVA20260603001

Keep the original requestRef after every money movement request. You may need it for a status query.

Envelope exceptions

Most operations send data as an object. A few operations are different:

Operation

Exception

BULK_NAME_ENQUIRY

data is an array of beneficiaries.

BULK_PAYMENT_TSQ

The request can be sent without a data field. Use the original bulk payment requestRef as the top-level requestRef.

Example BULK_NAME_ENQUIRY:

{
  "serviceType": "BULK_NAME_ENQUIRY",
  "requestRef": "BNE001",
  "data": [
    {
      "accountNumber": "2000000000",
      "bankCode": "999129"
    }
  ]
}

Example BULK_PAYMENT_TSQ:

{
  "serviceType": "BULK_PAYMENT_TSQ",
  "requestRef": "BULK20260603001"
}

Server-side example

Keep this code on your backend.

type KudaEnv = "uat" | "production";const baseUrls: Record<KudaEnv, string> = {
  uat: "https://kuda-openapi-uat.kudabank.com/v2.1",
  production: "https://kuda-openapi.kuda.com/v2.1"
};function activeEnv(): KudaEnv {
  return process.env.KUDA_ENV === "production" ? "production" : "uat";
}function makeRequestRef(prefix: string) {
  return `${prefix}${Date.now()}`;
}export async function kudaRequest(serviceType: string, data: unknown) {
  const response = await fetch(baseUrls[activeEnv()], {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.KUDA_ACCESS_TOKEN}`
    },
    body: JSON.stringify({
      serviceType: serviceType.toUpperCase(),
      requestRef: makeRequestRef(serviceType.slice(0, 4)),
      data
    })
  });  const text = await response.text();
  const payload = text ? JSON.parse(text) : null;  if (!response.ok) {
    throw new Error(`Kuda request failed with HTTP ${response.status}`);
  }  return payload;
}

Testing checklist

Before going live:

  • Confirm your app is using the UAT URL during testing.

  • Confirm secrets are stored server-side only.

  • Call BANK_LIST successfully.

  • Call NAME_ENQUIRY successfully with UAT bank codes.

  • Confirm you are logging requestRef for every operation.

  • Confirm status-query handling exists before enabling money movement.

  • Switch to production only after production credentials and production reference data are configured.

Did this answer your question?