Skip to content
MultigateAPI
Support Staff

Products

Beneficiaries

A beneficiary is a person or business you pay. Save one, then send transfers with its beneficiaryId instead of repeating the bank details every time.

When to use it

Saving is optional. Create a transfer also accepts full beneficiaryDetails, and in that case Multigate saves the beneficiary for you (or reuses the matching saved one), with the same checks as below. So your beneficiary list also contains everyone you paid with beneficiaryDetails.

Save beneficiaries yourself when you want to check and approve bank details once, before the first payment.

Prerequisites

  • An API user with the manage beneficiaries permission to save, update and delete, or view beneficiaries to list and read.
  • The beneficiary's bank code from List banks, or the bank's BIC (SWIFT code: the 8- or 11-character international bank identifier, for example GTBINGLA).

IDs you'll use

ID Where you get it Where you send it
Your client ID (MG_CLIENT_ID) currentAuthenticatedClientId in Get the current user clientId in the body of every save.
Customer ID entityId from Create a customer subClientId when you save for a customer; clientEntityId to list its beneficiaries.
Beneficiary ID beneficiary.entityId from Create a beneficiary, or entityId in List beneficiaries beneficiaryId in Create a transfer; the {entityId} in get, update and delete URLs.

Save a beneficiary

Check the account name (NGN)

For a Nigerian account (a 10-digit NUBAN, Nigeria's standard account number), ask the bank for the account holder's name first. This is called a name enquiry:

curl -X POST "$MG_BASE_URL/client-service/api/v1/beneficiaries/validate" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "bankAccountNumber": "0123456789", "bankCode": "058", "currencyIso3Code": "NGN", "countryIso3Code": "NGA" }'
{
  "message": "beneficiary successfully validated",
  "nameEnquiryResponse": { "accountName": "ADA OKAFOR", "bankName": "Guaranty Trust Bank" }
}

The response is always 200. When the account can't be verified, nameEnquiryResponse is null: don't save or pay that account until the number is corrected.

Save it

Use the name the bank returned as accountName:

curl -X POST "$MG_BASE_URL/client-service/api/v1/beneficiaries" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "Ab3kP9xQ2mN7vR1sT4uV6",
    "name": "Ada Okafor",
    "accountName": "ADA OKAFOR",
    "accountNumber": "0123456789",
    "bankBicOrCode": "058",
    "bankName": "Guaranty Trust Bank",
    "currencyIso3Code": "NGN",
    "country": "NGA",
    "addressLine1": "12 Marina Road",
    "city": "Lagos",
    "state": "Lagos"
  }'
{
  "message": "beneficiary created",
  "beneficiary": {
    "entityId": "Bn4kQ8rT2vX6yZ1aC3dEf",
    "name": "Ada Okafor",
    "accountName": "ADA OKAFOR",
    "accountNumber": "0123456789",
    "bankBicOrCode": "058",
    "bankName": "Guaranty Trust Bank",
    "bankCountry": "NGA",
    "currencyIso3Code": "NGN",
    "country": "NGA",
    "postCode": "000000",
    "status": "active",
    "clientEntityId": "Ab3kP9xQ2mN7vR1sT4uV6",
    "subClientId": "",
    "isPlatformAccount": false,
    "beneficiaries": []
  }
}

The response is shortened here. Store beneficiary.entityId: it's the beneficiaryId for transfers. The beneficiary is active straight away; no webhook is sent.

Pay it
{
  "uniqueRequestId": "po_20261010_0002",
  "reference": "Supplier payment Oct",
  "amount": 125000,
  "sourceCurrencyIso3Code": "NGN",
  "sourceAccountNumber": "1029384756",
  "beneficiaryId": "Bn4kQ8rT2vX6yZ1aC3dEf"
}

Send this body to Create a transfer. sourceAccountNumber is the wallet you pay from (see IDs and numbers you'll use). Send beneficiaryId or beneficiaryDetails, never both. See Payouts.

Rules by currency

Every save needs clientId, name, accountName, accountNumber, bankBicOrCode, bankName, currencyIso3Code, country, addressLine1, city and state. What goes in the bank fields depends on the currency:

Currency country accountNumber bankBicOrCode Checked with the bank? Also send
NGN NGA 10-digit NUBAN Bank code from List banks (for example 058), or a BIC (translated to the local code) Yes. Production refuses an account the bank can't confirm. accountName from the name check
GHS GHA The local account number The local bank code for the bank's country, or a BIC No
XOF The bank's country, for example SEN or CIV The local account number The local bank code for that country, or a BIC No
ETB ETH The local account number The local bank code, or a BIC No
SGD SGP The local account number Saved as sent; not checked No
USD, EUR, GBP and other currencies The beneficiary's country, for example DEU The account number, or the IBAN where the country uses one The bank's BIC (8 or 11 characters) No A real postCode (it defaults to 000000); intermediaryBank if the payment must go through a correspondent bank

bankBicOrCode must match a bank in Multigate's bank list. The saved code is normalised: the local bank code for NGN, GHS, ETB and XOF, the bank's BIC for other currencies, so it can differ from what you sent. For a local code, country must be the bank's country. The name you send in accountName is saved as it is; it isn't compared with the bank's.

  • Upper-case codes. Send currencyIso3Code and country in upper case. A lower-case currency is saved as sent and treated as international, so an NGN account isn't checked.
  • Letters and digits only in accountNumber: no spaces or dashes.
  • Duplicates. The same account number, currency and bank can be saved once per business and once per customer (409 "beneficiaries already exist"). An 8-character BIC and its 11-character XXX form count as the same bank.
  • Email. Production refuses disposable email domains such as yopmail.com ("Email domain is not allowed").
The sandbox saves NGN accounts the bank can't find

In the sandbox, a failed NGN account check doesn't stop the save, so a wrong account number is accepted there and refused in production. Sandbox name lookups are answered by test banks, so names can be fixed test values. See Sandbox vs production.

Beneficiaries for your customers

Add subClientId (the customer ID) when you save a beneficiary for one of your customers. That beneficiary belongs to the customer: use it for the customer's payouts.

  • Listing. List beneficiaries returns only your own business's beneficiaries unless you pass the customer ID in clientEntityId.
  • Reading, updating, deleting. Today these endpoints only find your own business's beneficiaries. For a customer's beneficiary they return 400 "beneficiary not found". Read it through the list instead; to change its bank details, save a new beneficiary.

Statuses

A saved beneficiary is always active. Deleted beneficiaries are no longer returned.

Some international payout channels need the beneficiary registered with them before they pay. Multigate does this automatically the first time you pay the beneficiary through such a channel, and shows the registration as an entry in the beneficiary's beneficiaries array. The transfer stays processing until the registration is ready, and fails (with the money returned) if it's refused.

stateDiagram-v2
    direction LR
    [*] --> processing: first transfer through the channel
    processing --> active: channel accepts the beneficiary
    processing --> failed: channel refuses it
    active --> [*]
    failed --> [*]
Registration status Meaning Waiting transfer
processing or pending Being registered with the channel. Stays processing.
active Ready. Is sent.
failed The channel refused the beneficiary. Fails, and the debit is reversed.

Updating a beneficiary discards its registrations, so the next transfer through that channel waits again. In the sandbox, registrations can take much longer than in production.

How it works

sequenceDiagram
    autonumber
    participant You as Your backend
    participant MG as Multigate
    participant Bank as Beneficiary's bank
    You->>MG: POST /beneficiaries/validate (NGN)
    MG->>Bank: Name enquiry
    Bank-->>MG: Account name
    MG-->>You: 200, nameEnquiryResponse
    You->>MG: POST /beneficiaries
    MG->>MG: Check bank code, duplicates
    MG->>Bank: Account check (NGN)
    MG-->>You: 200, beneficiary active
    You->>MG: Create a transfer with beneficiaryId
    MG-->>You: 200, transfer processing

Check an account

Use When If the account can't be verified
Validate a beneficiary account (NGN) Nigerian accounts. The lookup always uses the Nigerian network. 200 with nameEnquiryResponse: null.
Look up an account name Other local rails. An error response.

Manage beneficiaries

Action Endpoint Notes
List List beneficiaries Oldest first. Page with pageOffset and pageSize. Filter by accountName, sourceAccountNumber, sourceBankBicOrCode or sourceCurrencyIso3Code. 404 when nothing matches.
Get Get a beneficiary Your own business's beneficiaries only.
Update Update a beneficiary Send only what changes, but always send postCode if it was set, or it resets to 000000. Changing bank details repeats the bank checks. The response can leave out unchanged fields: read the beneficiary again.
Delete Delete a beneficiary It can't be used for new transfers. Past transfers are unaffected, and you can save the same account again.

Errors and recovery

Status Message Cause What to do
400 Invalid Bank or Swift code The code isn't in Multigate's bank list for that country, or the bank has no BIC (non-local currencies). Check the code with List banks, or send the BIC.
400 Invalid beneficiary account number Production, NGN: the bank couldn't confirm the account. Check the number with Validate a beneficiary account (NGN).
400 Sub-Client currently in {status} status The customer is rejected, inactive, blocked or deleted. Use an active customer.
400 beneficiary not found Get, update or delete of an unknown, deleted or customer's beneficiary. Check the ID with List beneficiaries.
400 Validation error A required field is missing or too long, or accountNumber has spaces or symbols. Fix the fields listed in errors.
404 Client not found clientId or subClientId isn't you or one of your customers. Use your client ID and your customers' IDs.
404 Currency not found, Country not found The code isn't supported. Use an upper-case ISO code Multigate supports.
404 beneficiary not found List: nothing matches, or the page is past the last one. Relax the filters or go back a page.
404 Resource not found Your API user lacks the permission. Ask your administrator for the permission.
409 beneficiaries already exist The account is already saved. Find it with sourceAccountNumber and use its entityId.

Beneficiaries send no webhooks or emails.

Next steps