Skip to content

Request headers

Header Required Value
Authorization Always, except on the token endpoint Bearer <access_token> from Authentication
Content-Type On any request with a body application/json; multipart/form-data for KYC uploads only
X-Agent-Account On every /api/legacy/agent/** call The 10-digit transaction account of the agent or merchant the call acts for
X-Tenant-Id No Ignored for partners; the tenant comes from your token
X-Device-Context No Base64-encoded JSON describing the end user’s device
X-Request-Id No Your correlation id; echoed back and stored in the audit log

Send the bearer token from the token endpoint on every other call. A missing, malformed or expired token is refused with HTTP 401 before anything else is looked at. Treat a 401 as “get a new token and retry once”; if the retry also fails, your client has probably been suspended, and the token endpoint will tell you so.

Everything under /api/legacy/agent/** acts for an agent: its balance, its statement, a virtual account from its range, a bill paid from its account. The agent is named by this header, and the value is the agent’s 10-digit transaction account number (not its fee account, and not an agent code).

X-Agent-Account: 6020012345

The agent you name must be one you may reach: your own agent profile, or a sub-agent you onboarded. Naming any other agent’s account fails the ownership guard; see Ownership model.

Leaving the header off an agent endpoint returns the legacy envelope { "code": "0012", "desc": "Missing required header: X-Agent-Account" }.

BankCore is multi-tenant, and its controllers read a tenant id from this header. For partner clients the value is overridden from your token before the controller sees it: send it or not, send it right or wrong, the request is pinned to the tenant your client belongs to. A mismatching value is logged on the bank’s side and otherwise ignored. You can omit it.

Optional, and useful only when a real end user is behind the call (a customer in your app rather than a batch job). The value is a Base64-encoded JSON object:

{
"deviceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"deviceModel": "Samsung Galaxy S24",
"os": "Android 14",
"appVersion": "2.5.1",
"coordinates": { "lat": 6.5244, "lng": 3.3792 }
}
Field Required Notes
deviceId Yes A stable identifier for the physical device. Without it the whole header is ignored.
deviceModel, os, appVersion No Free text.
coordinates.lat, coordinates.lng No Decimal degrees. Note the short key names.

The header is fail-open: a missing, undecodable or incomplete value never rejects the request. When present, deviceId and the coordinates are stamped into the metadata of any transaction the call creates (deviceId, deviceLat, deviceLng) and feed the bank’s device-change and location checks. Unknown fields are ignored.

Send any string you like to correlate a call with your own logs. The API echoes it back unchanged in the X-Request-Id response header and records it against the request in your client’s audit log. If you do not send one, the API generates a UUID and echoes that instead. Either way, quote the value when raising a support case; it is how the bank finds your request.

X-Request-Id is a correlation id, not an idempotency key. Two calls with the same X-Request-Id are two calls. For idempotency use the reference fields described in Idempotency.

Accept is not required; responses are always JSON. Do not send X-Forwarded-For or X-Real-IP; the bank’s edge resolves your address from the connection itself, and values you add are never trusted for the IP allowlist.

The API access page shows the time and source address of your client’s last use.