Skip to content
MultigateAPI
Support Staff

Products

Customers

Onboard the businesses you serve, so you can open accounts, convert and pay out for them. The API calls a customer a sub-client. Multigate checks each customer (KYB, know your business: verifying the company, its owners and its documents) before it can transact.

When to use it

Use customers when you hold money or make payments for other businesses: a fintech's or marketplace's merchants, a remittance company's business clients, a bank's corporate clients, or a corporate's subsidiaries. If you only move your own money, you don't need customers.

There are two types:

subClientType For Review
client An external business you serve. Approved in your business, then Multigate screens the business name (checks it automatically against sanctions and watch lists). A possible match goes to Multigate's compliance team.
subsidiary A company in your own group. Approved in your business only. Multigate doesn't screen it.

Before you start

  • You've completed the Quickstart environment setup: MG_BASE_URL, MG_API_KEY and MG_CLIENT_ID (your client ID).
  • Your own business must be active and approved on Multigate.
  • Your API user needs the manage customers permission. To skip the second approver, it also needs the approve customers permission (see the submit step below).
  • Your webhook URL is registered, so you receive the review outcome (client / subclient_approved).
  • Have the customer's registration details, its directors and beneficial owners (people who own or control it, usually 25% or more), and its KYB documents as PDF or image files.

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 The {clientId} part of every customer URL.
Customer ID entityId returned by Create a customer The {id} part of customer URLs; onBehalfOf for accounts, payouts and conversions; subClientId when you save a beneficiary; clientEntityId to list its beneficiaries.
Person ID entityId returned by Add a director or owner businessUserId when you upload or list that person's documents; {shareHolderId} in Update a director or owner.

Every example below uses customer ID Kx81mQ2pZr4tV9wYa3Bc5 and person ID Hq3vT8nLm2Xc5RzW: replace them with yours.

How onboarding works

sequenceDiagram
    autonumber
    participant You as Your backend
    participant MG as Multigate
    participant AP as Your approver
    participant CO as Multigate compliance
    You->>MG: POST create customer
    MG-->>You: entityId, status draft
    You->>MG: POST add each director and owner
    You->>MG: POST upload each document
    You->>MG: POST submit for review
    MG-->>You: approval request, customer now processing
    alt Your API user can't approve customers
        MG->>AP: Email "Sub-client Creation Request for Approval"
        AP->>MG: Approve in the dashboard
    end
    MG->>MG: Screen the business name
    alt Nothing found
        MG-)You: Webhook client / subclient_approved, status active
    else Possible match
        MG->>CO: Review
        CO->>MG: Approve or decline
        MG-)You: Webhook client / subclient_approved, status active or rejected
    end

A subsidiary skips screening: it becomes active as soon as it's approved in your business, and no webhook is sent.

Create the customer
curl -X POST "$MG_BASE_URL/client-service/api/v1/clients/$MG_CLIENT_ID/sub-clients" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subClientType": "client",
    "businessName": "Kola Stores Ltd",
    "businessType": "Limited Liability Company",
    "customerType": "corporate",
    "businessAddressLine1": "4 Allen Avenue",
    "city": "Ikeja",
    "state": "Lagos",
    "countryOfRegistration": "NGA",
    "operatingCountries": ["NGA"],
    "businessContactEmail": "finance@kolastores.example",
    "registrationNumber": "RC1234567"
  }'
{
  "message": "Sub-Client information saved successfully",
  "entityId": "Kx81mQ2pZr4tV9wYa3Bc5",
  "businessName": "Kola Stores Ltd",
  "subClientType": "client",
  "status": "draft",
  "approvalStatus": "pending",
  "stagesRemaining": ["documentation", "director", "owner"],
  "parentClientId": "Ab3kP9xQ2mN7vR1sT4uV6"
}

Store the returned entityId: it's the customer ID. The customer is draft: nothing is reviewed until you submit it.

Required fields: subClientType, businessName, businessType (Public Limited Company, Limited Liability Company, Ordinary Business Registration or Government Agency), businessAddressLine1, city, state, countryOfRegistration, operatingCountries and businessContactEmail. Countries are upper-case ISO 3166-1 alpha-3 codes (NGA, GHA). customerType is corporate or financialInstitution. See Create a customer for every optional field.

  • businessContactEmail must not be used by any other customer on Multigate, including declined ones. A duplicate returns 409.
  • Give each customer a distinct businessName. Two customers with the same name can't both be used for payouts and conversions.
  • Creating isn't idempotent. If the call times out, look for the customer with List customers (businessName filter) before you retry.
Add directors and owners

Add each person with Add a director or owner, one call per person. Use designation to say what they are.

curl -X POST "$MG_BASE_URL/client-service/api/v1/clients/$MG_CLIENT_ID/sub-clients/Kx81mQ2pZr4tV9wYa3Bc5/business-users" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Mrs", "firstName": "Adaeze", "lastName": "Kola", "gender": "female",
    "occupation": "Director", "dateOfBirth": "1980-04-12",
    "identificationType": "PASSPORT", "identificationNumber": "A01234567",
    "issuedDate": "2022-01-10", "expiryDate": "2032-01-09",
    "countryIso3Code": "NGA", "country": "Nigeria",
    "address": "4 Allen Avenue", "city": "Ikeja", "state": "Lagos", "postalCode": "100001",
    "designation": "BeneficialOwnerDirector", "shareholderPercentage": 60
  }'

The response is the person, with their entityId: store it as the person ID. Dates are YYYY-MM-DD; the identity document's issuedDate can't be in the future and its expiryDate can't be in the past.

stagesRemaining is a checklist for you; Multigate doesn't enforce it:

designation Removes from stagesRemaining
BeneficialOwner, BeneficialOwnerSignatory, BeneficialOwnerDirector, BeneficialOwnerDirectorSignatory owner
Director, DirectorSignatory director
Signatory nothing

A BeneficialOwnerDirector clears owner only. Uploading documents never clears documentation.

Upload documents

Upload each file with Upload a customer document as multipart/form-data, one file per call. Company documents go on the customer. A person's documents go on the customer too, with the person ID in businessUserId.

A company document:

curl -X POST "$MG_BASE_URL/client-service/api/v1/clients/$MG_CLIENT_ID/sub-clients/Kx81mQ2pZr4tV9wYa3Bc5/upload-kyc" \
  -H "mp-api-key: $MG_API_KEY" \
  -F "file=@certificate.pdf" \
  -F "documentType=CERTIFICATE_OF_INCORPORATION" \
  -F "issueDate=2019-03-14"

A director's passport:

curl -X POST "$MG_BASE_URL/client-service/api/v1/clients/$MG_CLIENT_ID/sub-clients/Kx81mQ2pZr4tV9wYa3Bc5/upload-kyc" \
  -H "mp-api-key: $MG_API_KEY" \
  -F "file=@adaeze-passport.pdf" \
  -F "documentType=PASSPORT" \
  -F "businessUserId=Hq3vT8nLm2Xc5RzW" \
  -F "issueDate=2022-01-10" \
  -F "expiryDate=2032-01-09"

Pick the documentType that matches each file:

Document documentType Uploaded on
Certificate of incorporation or registration CERTIFICATE_OF_INCORPORATION or REGISTRATION_CERTIFICATE The customer
Memorandum and articles of association ARTICLE_OF_ASSOCIATION The customer
List of directors, list of shareholders LIST_OF_DIRECTORS, LIST_OF_SHAREHOLDERS The customer
Ownership chart SHAREHOLDING_STRUCTURE_CHART The customer
Business proof of address (for example a utility bill) PROOF_OF_ADDRESS The customer
Tax registration, business or regulatory licence TAX_REGISTRATION, BUSINESS_LICENSE, REGULATORY_LICENSE The customer
Board resolution BOARD_RESOLUTION The customer
Recent bank statement RECENT_BANK The customer
Passport, national ID card, NIN slip, driver's licence, voter's card PASSPORT, IDCARD, NIN, DRIVERS_LICENSE, VOTERS_CARD The person (businessUserId)
Personal proof of address PROOF_OF_ADDRESS The person (businessUserId)

Check what's uploaded with List customer documents (add businessUserId for a person's documents).

  • Send PDF or image files. Plain-text files (.txt, .csv) fail with 500.
  • A second file with the same documentType is added to the same document. Files can't be removed through the API.
  • The API doesn't say which documents are required, and submission doesn't check them. Your Multigate contact tells you which documents your market requires; a customer without them can be declined.
Submit for review
curl -X POST "$MG_BASE_URL/client-service/api/v1/clients/$MG_CLIENT_ID/sub-clients/Kx81mQ2pZr4tV9wYa3Bc5/submit-for-approval" \
  -H "mp-api-key: $MG_API_KEY"

The response is the approval request (type creation), not the customer. What happens next depends on your API user:

  • It has both the manage customers and approve customers permissions: the customer is approved in your business at once. A client becomes processing and is screened; a subsidiary becomes active.
  • It doesn't: the customer becomes processing with approvalStatus pending. Your approvers receive a "Sub-client Creation Request for Approval" email and approve or decline in the dashboard. If they decline, the customer is removed: it disappears from lists, its email can't be reused, and no webhook is sent.
Submit once

Submit only draft customers, and only once. The endpoint doesn't check the status: submitting again moves an active or rejected customer back to processing, even when the call then fails with 409. Use Resubmit a declined customer for declined customers.

Wait for the outcome
  • Nothing found by screening: the customer becomes active, usually within minutes, and you receive client / subclient_approved.
  • Possible match: Multigate compliance reviews it. The customer stays processing with no webhook until they decide; this can take days if they need more information.

When subclient_approved arrives, check status: active means approved, rejected means declined. The same event is used for both.

If declined, read approvalComments, fix what was asked (update the customer, add people or documents), then call Resubmit a declined customer. Compliance reviews it again and you receive subclient_approved with the new outcome.

If you miss the webhook, poll Get a customer no more than every few minutes.

Customer statuses

stateDiagram-v2
    direction LR
    [*] --> draft: created
    draft --> processing: submitted
    draft --> active: subsidiary approved at once
    processing --> active: screening clear, compliance approves, or subsidiary approved
    processing --> rejected: compliance declines
    processing --> inactive: your approver declines, customer removed
    rejected --> processing: resubmitted
    active --> inactive: deactivated
    inactive --> active: reactivated
    active --> deleted: deleted
    active --> blocked: blocked by Multigate
    blocked --> active: unblocked by Multigate
status Meaning Can you open accounts, pay out or convert for it? What to do
draft Created, not submitted. No Add people and documents, then submit.
processing Submitted. Waiting for your approver, for screening, or for Multigate compliance. No Wait for subclient_approved.
active Approved. Yes Open accounts (Accounts).
rejected Declined by Multigate compliance. No Read approvalComments, fix, then resubmit.
inactive Deactivated in your business. Customers declined by your own approver are also set to inactive, but they're removed, so you won't see them. No Reactivate it in the dashboard.
deleted Deleted in your business. No Create a new customer (with a new email).
blocked Blocked by Multigate compliance. No Contact Multigate.

Deactivating, reactivating and deleting customers are dashboard actions that go through your approvers. Accounts are opened only for active customers ("Sub-Client not active" otherwise).

approvalStatus shows approval inside your business only: pending (created, or waiting for your approver), approved (approved in your business; Multigate's review may still be running) or declined (declined by your approver). It stays approved when Multigate compliance declines the customer. Always use status for the outcome.

The subclient_approved webhook

The body is the customer, as returned by Get a customer: entityId, businessName, status, approvalStatus, parentClientId (your client ID) and the other customer fields.

  • Sent: for a client customer, when screening finds nothing (status active) or when Multigate compliance decides (active or rejected), including after a resubmission.
  • Not sent: for subsidiaries, when your approver declines, while compliance is still reviewing, or for creating, updating, uploading or submitting.
  • approvalComments and approvalDate appear only after a compliance decision. approvalDate isn't ISO 8601 (it looks like Sat Oct 10 2026 14:20:00 GMT+0000 (Coordinated Universal Time)).
  • De-duplicate by entityId and status: the same outcome can arrive more than once.

Things to know

  • Active customers become usable for payouts and conversions after a short delay (up to a few minutes) while the change reaches those services. Until then, payouts for them fail with "Invalid sub onBehalfOf".
  • Updates aren't reviewed. Update a customer works in any status and applies at once. It doesn't check country codes, prohibited countries or email uniqueness, so send the same kind of values you'd send on create.
  • Countries. A customer registered or operating in a country Multigate prohibits is refused when you create it ("The selected country or countries are prohibited"). Use upper-case ISO 3166-1 alpha-3 codes.
  • Email domains. Production refuses disposable email domains (yopmail.com, mailinator.com and similar) for the customer and its people. The sandbox accepts them.
  • Emails go to your business. Approval requests go to your approvers, and approval results ("Subclient Creation Request Approved", "Sub-client Creation Request Declined") go to the user who submitted, which is your API user. Customers never receive emails from these steps.
Sandbox: reviews are slow

In the sandbox, a submitted client customer can stay processing for days, because screening results are collected far less often than in production. Until it's active you can't open accounts for it. Ask your Multigate contact to complete the review for your test customers. See Sandbox vs production.

Errors

Message Cause Fix
Client not found (400) The clientId in the path isn't your client ID, or your business isn't active. Use currentAuthenticatedClientId from Get the current user.
Client is inactive (400) Your own business isn't active and approved yet. Contact Multigate.
Sub-Client not found (400) The customer doesn't exist, isn't yours, or was declined by your approver and removed. Check the entityId.
Resource not found (404) Your API user lacks the permission. Ask your administrator for the manage customers permission.
Sub-Client already exists (409) The contact email is already used by a customer on Multigate. Use the customer's own unique email.
The selected country or countries are prohibited (400) A country Multigate can't serve. Remove it.
Country not found (404) An unknown country code. Use upper-case ISO 3166-1 alpha-3 codes.
Email domain is not allowed (400) A disposable email domain, in production. Use a real business domain.
ShareHolder not found (404) The businessUserId isn't a person on this customer. Use the entityId from Add a director or owner.
Pending approval request for creation already exists (409) A submission is still open. Wait for the outcome. Don't submit again.
Sub-Client not eligible for resubmission (400) Only rejected customers can be resubmitted. Check status.
Sub-Client in review (400) The customer is already being reviewed. Wait for the outcome.

Next

Wallets and virtual accounts with onBehalfOf.

How onBehalfOf works across the API.