Skip to content
MultigateAPI
Support Staff

Get started

Environments and sandbox

Multigate has two environments. Build and test everything in the sandbox, then switch the base URL and credentials to go live.

Sandbox Production
Base URL https://api-gateway-uat.mmacs.io/platform https://api-gateway.mmacs.io/platform
Dashboard uat.multigate.app multigate.app
Money Simulated. Nothing reaches a real bank account. Real.
Credentials Sandbox API key and client secret (from the sandbox dashboard) Production API key and client secret (from the production dashboard)
IP allow-list Its own list, enforced Its own list, enforced
Webhook URL Registered in the sandbox Registered in production
Funding your accounts Simulate an inflow Real bank transfers to your virtual accounts

Every path in these docs is relative to the base URL. For example, getting the current user in the sandbox is:

GET https://api-gateway-uat.mmacs.io/platform/user-service/api/v1/users/current-user
mp-api-key: <your sandbox API key>

A key works only in the environment whose dashboard generated it, and its start tells you which one: sandbox keys start with mgk_sandbox_ and production keys with mgk_live_.

Keep the base URL in configuration

Read the base URL and credentials from configuration, for example the environment variables MG_BASE_URL, MG_API_KEY and MG_CLIENT_SECRET used throughout these docs (set up in the Quickstart). Going live is then a configuration change, not a code change.

How the sandbox differs from production

Read this before you test

The sandbox doesn't behave exactly like production. A few checks are off (FX balance checks, NGN beneficiary account checks, disposable email domains), some jobs are much slower (payout results, customer reviews), and payout outcomes come from test banks, sometimes at random.

Every difference, with what to do about it, is on Sandbox vs production.

Sandbox Production
Incoming payments Only through Simulate an inflow. From payers' banks. The simulate endpoint does nothing.
Payouts Full flow (validation, screening, approvals) against test banks and simulated partners. Results can take 15 minutes or more. Paid to real accounts, usually within seconds of the bank answering.
Checks that are off FX balance check on lock, NGN account check when saving a beneficiary, disposable email domains. All on.
Webhooks and emails Sent, with the same format and signing. Emails go to real addresses. Sent.
IP allow-list Enforced (its own list). Enforced (its own list).
Data Separate from production. Nothing carries over when you go live.

Simulate an inflow

Fund a sandbox account, or test your inflow handling, by pretending a payer sent money to one of your virtual accounts.

Find an active account number

Use List accounts and pick an account whose status is active. Use one of its virtual account numbers from fundingDetails (the numbers payers would send to). The account must belong to your business or one of your active customers. The Quickstart stores it in MG_VIRTUAL_ACCOUNT_NUMBER.

Send the simulated inflow
curl -s -X POST "$MG_BASE_URL/client-service/api/v1/webHook/publishInflow" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"accountNumber\":\"$MG_VIRTUAL_ACCOUNT_NUMBER\",\"amount\":1000000,\"currency\":\"NGN\"}"
{ "message": "inflow initiated" }

amount is in major units (1000000 is 1,000,000.00 NGN). currency is required but ignored: the credit always uses the account's own currency. The response contains no reference.

Watch it arrive

The response only means the inflow was queued. It is then screened (checked against Multigate's compliance rules) and credited like a real one. In the sandbox this usually takes a few minutes; there is no fixed time. Then:

  • your webhook receives account / inflow;
  • your business contact receives a "Payment Received" email;
  • the balance (Get an account balance) and statement of the account show the credit, minus any collection fee (a fee on money received) configured for your business.

A simulated inflow has no sender bank or sender account number (null in the webhook), and its paymentReference/sessionId is a generated ID the call doesn't return. The sender name is the account's own name, and the narration looks like MULTIGATE-<account name>-<masked account number>.

Check the response body, not only the status

If the account isn't active yet, the endpoint still answers 200, but with an error body: [{"errors":{"message":"account has not been approved"}}]. Wait for the account_opened webhook before simulating inflows into a new account.

Check the credited amount

For some NGN and GHS sandbox accounts, depending on the partner bank behind them, the simulated amount is read as minor units (kobo or pesewas) and credited at one hundredth: 1000000 credits 10,000.00. Compare amount in the webhook with what you sent, and send 100 times the amount if needed.

In production the endpoint answers 200 but does nothing, so keep it out of your production code paths entirely.

Test checklist

Before you ask for production access, run each of these in the sandbox:

  • Call the API with your sandbox API key, rotate it to a second key without errors, and handle a 401 from a revoked key (Authentication).
  • Fund an account with a simulated inflow and process the inflow webhook (Collections).
  • Create a payout, and process transfer_completed and transfer_failed (Payouts).
  • Retry a payout with the same uniqueRequestId and confirm nothing is paid twice (Idempotency).
  • Trigger and handle errors: insufficient balance, invalid account, unknown bank (Errors).
  • Reject a webhook with a tampered body (Verifying signatures).

Then read Sandbox vs production and work through the go-live checklist.