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 beneficiary, 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 beneficiary.
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) |
current 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; client to list its beneficiaries. |
| Beneficiary ID | beneficiary. 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
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, name is null: don't save or pay that account until the number is corrected.
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.: it's the beneficiaryId for transfers. The beneficiary is active straight away; no webhook is sent.
{
"uniqueRequestId": "po_20261010_0002",
"reference": "Supplier payment Oct",
"amount": 125000,
"sourceCurrencyIso3Code": "NGN",
"sourceAccountNumber": "1029384756",
"beneficiaryId": "Bn4kQ8rT2vX6yZ1aC3dEf"
}
Send this body to Create a transfer. source is the wallet you pay from (see IDs and numbers you'll use). Send beneficiaryId or beneficiary, never both. See Payouts.
Rules by currency
Every save needs clientId, name, accountName, accountNumber, bankBicOrCode, bankName, currency, 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); intermediary 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
currencyandIso3 Code countryin 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-characterXXXform count as the same bank. - Email. Production refuses disposable email domains such as yopmail.com ("Email domain is not allowed").
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
client.Entity Id - 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, source, source or source. 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 source and use its entityId. |
Beneficiaries send no webhooks or emails.
Next steps
- Payouts: pay a saved beneficiary.
- Bulk payouts: pay many beneficiaries at once.
- Acting for your customers: customer IDs and
onBehalfOf.