Z Zise Developers 简体中文
Account Center › Guides

Acting for a member: when x-on-behalf-of is required and what happens if it is wrong.

Calling on Behalf of a Member

Your API Key represents your merchant. Most business operations, however, act on a particular member— whose balance, whose card, or who is remitting. x-on-behalf-of selects the member for this call.


POST /v1/remittances
x-auth-token: Bearer eyJ…
x-on-behalf-of: u_88213

Which Endpoints Require It

The badge at the top of each endpoint page tells you: Member requires it; Merchant does not.

A rough rule is “whose money does this operation affect?”:

SubjectExamples
MemberBalances, transactions, deposit reporting, withdrawals, remittances, card issuance, wealth, exchange, transfers, QR payments, KYC
MerchantCreating members, updating member attributes, suspending members, your prepaid balance, statements, product catalogs, corridor lists

Endpoints requiring member scope always return 400 member_context_required when this header is missing— there is no fallback to a default member.

Including it on an endpoint that does not need it does not cause an error; it simply is not read. Therefore, “it did not error when I added it” does not mean the endpoint honors it.

Two Accepted Identifiers

Both are accepted; use either:

FormSourceExample
Your external member IDexternal_member_id supplied at member creationu_88213
Our internal member IDThe id field in any member responsemem_0a3f…

The deciding factor is the mem_ prefix: with it, we look up our internal ID; otherwise, your external ID.

⚠ This was added on 2026-08-11. Previously only external IDs worked, even though every member response's id was mem_…. The most natural approach—sending our returned ID back unchanged—therefore produced member_not_found, an error that looked like “this member does not exist” but actually meant “you used the wrong identifier.” Path parameters such as /v1/members/{id} use the same parser, consistently with this header.

Values returned to your side always use your external ID: on_behalf in audit logs and member fields in webhook payloads, regardless of which identifier you supplied in the request.

What Is Returned When the Member Cannot Be Resolved

One response only: 404 / member_not_found / Member not found.

This deliberately covers four indistinguishable cases:

Actual situation
The member ID does not exist on our platform
It exists but belongs to another merchant
It belongs to you but is suspended (suspend)
It belongs to you but you have blacklisted it

⚠ Cross-merchant access and nonexistence must look identical. Distinguishing them would provide a cross-merchant member enumeration endpoint: someone could test a list of phone numbers or emails to discover which people are other merchants' customers. Likewise, suspension and blacklisting do not get separate codes—revealing the exact enforcement stage would provide a free status probe.

For troubleshooting, first confirm that you created this member ID, then check its status in the admin console. Both checks must be made in your console; the API does not identify which case applies.

⚠ Suspension and blacklisting are independent flags, not two positions of one switch. Restoring a suspended member does not also remove the blacklist entry. Remove it separately, or this header will continue to be rejected.

One Endpoint Identifies the Member in the Path, Not This Header

GET /v1/members/{id}/limits identifies the member through the path parameter and deliberately does not attach x-on-behalf-of parsing.

This is intentional. Attaching both would let /v1/members/A/limits with x-on-behalf-of: B return B's data while silently ignoring A in the path. The caller would receive a 200 that asks for A and returns B, without any error.

Therefore, put the member ID in the path when calling it. Both identifier forms are accepted there too. Adding x-on-behalf-of neither errors nor has an effect.

Can One Call Switch Between Members?

No. One request acts on one member. To do the same thing for N members, send N requests, each with its own x-idempotency-key.

⚠ Idempotency keys are not member-scoped, and same-key matching checks the body, not headers. x-on-behalf-of is a header. Sending the same key and body for two different members therefore means the second receives neither a new order nor an error, but an exact replay of the first member's result (with X-Idempotent-Replay: true). Nothing happens to the second member, while your system sees a 200.

Moving key generation outside a batch loop creates exactly this problem. Use a new key for each member.