Skip to content

Environments and base URLs

The bank issues your production host when your partner API client is approved. Throughout this documentation the placeholder https://api.bankcore.ng stands in for it; substitute the host you were given. Every path in these pages is relative to that host, for example:

https://api.bankcore.ng/api/auth/channel/token
https://api.bankcore.ng/api/legacy/agent/virtual_account/create

Three path families exist, and they behave differently enough that it is worth recognising them:

Prefix Who acts Response style
/api/legacy/provider/** You, moving money from your own accounts or an agent’s you may debit Legacy envelope: HTTP 200 with code and desc
/api/legacy/agent/** An agent or merchant named by X-Agent-Account Legacy envelope
everything else under /api/** You BankCore-native: real HTTP status, structured error body

See Responses and error codes for both styles.

The API is served over HTTPS only. There is no plain-HTTP listener and no redirect; a request to http:// simply fails to connect. Keep your TLS stack current: the bank’s edge accepts modern cipher suites and may retire older ones without notice.

A sandbox (UAT) host is issued alongside your credentials for integration testing. Sandbox and production are separate clients, not one client with two hosts:

  • Each has its own client_id and client_secret. A token from one is meaningless on the other.
  • Each has its own scope list, IP allowlist and rate limits. Ask for the production allowlist to be set up before go-live rather than discovering it on the day; see the Go-live checklist.
  • Each has its own settlement account, fee account and webhook subscriptions.
  • Data does not cross over. Agents, merchants and virtual accounts you create in sandbox do not exist in production.

Two date conventions are in play, matching the two response styles.

BankCore-native endpoints emit timestamps as ISO-8601 instants in UTC with a Z suffix and millisecond precision, for example 2026-04-01T20:57:11.298Z. Query parameters that take a date (from, to) accept yyyy-MM-dd.

Legacy endpoints carry a transdatetime field on money-movement responses in the compact jCard format yyyyMMddHHmmss, for example 20260401143000. It has no zone designator.

Virtual account time-to-live (ttl) is a duration in minutes from creation, so it is zone-independent.

  • Send Content-Type: application/json on every request with a body. Legacy endpoints that take no body (balance, statement, agent details) are plain GETs.
  • KYC document uploads are the one exception and take multipart/form-data. See KYC uploads.
  • Responses are always application/json, including the filter refusals (scope, IP, rate limit) that are produced before your request reaches a controller.
  • Amounts are decimal numbers in naira (50000.00), not kobo, on every endpoint documented here. Legacy responses return balances as strings with two decimal places ("145000.00").
  • Account numbers are 10-digit strings. Always send them as strings; a leading zero is significant.

Legacy list endpoints are 1-based: page=1 is the first page, with size (or pageSize on the biller catalogue) as the page length, and they answer { "success", "total", "data" }. BankCore-native list endpoints follow the Spring convention and are 0-based. The two never mix on one endpoint, so check which family the endpoint belongs to. See Responses and error codes.

The API access page shows the client your organisation holds in that environment, with its status, scopes, rate limits and IP allowlist. Each environment has its own portal.