Skip to content

Ownership model

Your scopes say what your client may do. They never say whose accounts it may do it to. That second question is answered by the ownership guard, which runs on every balance read, statement read, identity update and debit a partner client makes, regardless of whether you reach the money core through a provider money route, an agent route or a BankCore-native route.

The guard only exists for partner clients (clientType is PARTNER in your token). The bank’s own channel servers act across the whole tenant and are not subject to it. A partner client with no linked customer is refused everything: that is a misconfigured client, not a licence to act tenant-wide.

Your estate is exactly two things, and the guard recognises nothing else.

Your own customer. Your client is linked to exactly one customer record, the corporate (or agent) your organisation is registered as. Every account owned by that customer is yours: the settlement account, the fee account, and anything else the bank opened for you. Reading and debiting those needs nothing beyond the ordinary scope for the call.

The agents and merchants you onboarded. When you create an agent or merchant through Onboard an agent or merchant, whether an individual or a registered business, its agent profile is stamped with the client that created it. That stamp is the authority. It survives a secret rotation and it is shared across every client your organisation holds, because the check asks whether the creating client belongs to the same customer as the calling client. The commission hierarchy the bank may also record (an “aggregator” link) confers nothing; only the creation stamp does.

Seeing a sub-agent and spending its money are different rights, held separately on purpose: a sub-agent’s account holds a different legal person’s money.

Grant Who sets it What it unlocks
Sub-agent access The bank, as a switch on your client (sub_agent_access_enabled) Balance, statement, transaction list, downline listing and agent listing for every sub-agent you onboarded. Read live on each request, so switching it off takes effect at once, not when your token expires.
sub-agents:debit scope The bank, when granting scopes Moving money out of a sub-agent’s accounts: charge, transfer, interbank transfer, bill payment, airtime, move income. Read access does not imply it.
sub-agents:create scope The bank, when granting scopes Onboarding agents and merchants parented to you.

With sub-agent access switched off, a sub-agent’s accounts are as unreachable as any stranger’s. With it on but without sub-agents:debit, you get an estate view and no spending power over it. The guard asks both questions on the account in hand: is its owner one of your sub-agents with access switched on, and, for a debit, do you hold the scope.

Operation Your own accounts A sub-agent’s accounts Anyone else’s
Balance (A4 agent/balance, A21 downlines/{realId}/balance) Allowed Needs sub-agent access Refused
Statement and transaction list (A5 agent/statement, A23 agent/tranlist) Allowed Needs sub-agent access Refused
Agent details and profile (A2, A3) Allowed Needs sub-agent access Refused
Update identity (PATCH agent/update) Allowed Needs sub-agent access Refused
Debits: agent transfer (transact/transfer/mobile, transact/transfer/direct_debit), pay bill and airtime (transact/paybill, transact/airtime), move income (A19), and the provider money routes with an agent’s account as fromAccountNumber Allowed Needs sub-agent access and sub-agents:debit Refused
Fund or deposit from your settlement account The source is your settlement account; the destination is not ownership-checked Same Same
Downlines and agent list (A20, A25) Returns your estate Needs sub-agent access, otherwise refused outright Not applicable
Find agent by phone (A24) Found Found “Not found”

Finding an agent grants nothing on its own: an agent appearing in a result set is not proof you can read its balance or statement. The guard runs on the follow-up call. The provider money routes (fund, charge, transfer, interbank, bills) are documented under Moving money; they take an account number in the body and the same rule applies to the account you name as the source.

Attribution on the sub-agent’s statement

Section titled “Attribution on the sub-agent’s statement”

When you debit your own account, the actor and the owner are the same party and the transaction needs no explanation. When you debit a sub-agent’s account, two legal persons are involved, and the sub-agent would otherwise see a debit it did not initiate with nothing to attribute it to. So the platform writes your identity into the transaction’s metadata:

Key Value
initiatedByPartner Your client_id, for example pa_ab12cd34.
initiatedByPartnerCustomerId The id of your own customer record, not the sub-agent’s.

That metadata is carried to the sub-agent’s statement entries, to transaction detail pages in the bank’s own tools, and into webhook payloads. It is never written on a debit of your own accounts. See Acting on an agent’s money.

Ownership refusals are business errors, not authentication errors, and they are shaped by the endpoint family you called.

  • Legacy routes (/api/legacy/...) answer HTTP 200 with code 0012 and a desc that names the reason, for example Account 6020012345 is not linked to this API client.
  • BankCore-native routes (for example POST /api/nip-transfers) answer HTTP 400 with errorCode PARTNER_ACCOUNT_FORBIDDEN or PARTNER_SUBAGENT_FORBIDDEN.
  • Find agent by phone answers HTTP 404 with code 0012 whether the agent does not exist or simply is not yours. A distinguishable refusal would turn that endpoint into a phone-number oracle.
  • An account that does not exist is never answered by the guard. The endpoint’s own not-found handling replies (0012 on legacy routes, HTTP 404 on native ones), so the guard never reveals whether a number you are not allowed to touch is real.

HTTP 403 is reserved for scope and IP refusals (SCOPE_DENIED, IP_NOT_ALLOWED). If you see a 403 you are missing a scope, not an ownership grant. The full list is in Ownership errors.

The Agents page lists the sub-agents your organisation has onboarded, with status, account count, available balance and last activity. It appears in the rail only once you have at least one agent. The API access page shows whether sub-agent access is switched on for each client and which scopes it holds.