Funding

Funding covers how fiat money moves in and out of a client's account — deposits credit a client's balance, withdrawals debit it. This page explains the funding model, asset eligibility, reconciliation, and how balances behave.

Funding is how fiat money moves in and out of your clients' accounts on CoinMENA. You create deposits to credit a client's balance and withdrawals to debit it. Both are bank-based, both are scoped per client, and both create order records you can reconcile against your own internal references.


Overview

The Partner API supports two funding operations:

OperationEndpointWhat It Does
DepositPOST /v1/partner/depositsCredit fiat to a client's available balance
WithdrawalPOST /v1/partner/withdrawalsDebit fiat from a client's available balance

Both operations:

  • Are scoped to a single client via partner_client_id
  • Accept only published fiat assets (e.g. USD)
  • Require a unique partner_order_ref for reconciliation
  • Create an order record that you can retrieve later (see Orders)
  • Are synchronous and immediate — the balance updates in the same call
📘

Funding is bank-based

The Partner API funding endpoints book bank-based fiat deposits and withdrawals on behalf of your clients. Crypto deposits and withdrawals are not supported through this API.


Core Rules

Three rules govern every funding call. All three are hard constraints — violating any one of them rejects the request.

Funding is synchronous and immediate

A successful deposit or withdrawal call returns an order with status: completed. The transaction has been created and completed in the same call — there is no pending/processing state to poll. The client's balance is updated on the response, not later.

⚠️

partner_order_ref must be unique per partner

Every funding call requires a partner_order_ref that has never been used before under your partner account. Reusing one returns error 2020 with HTTP 409 Conflict. This prevents duplicate order creation. It is not silent retry — a conflict means you must fetch the existing order and decide what to do, not retry with the same ref. See Handling a 2020 Conflict.

⚠️

Withdrawals require sufficient available balance

A withdrawal is rejected with error 3005Insufficient funds for payment — if the client's available_balance is less than the requested amount. No partial withdrawal is ever performed. Check the balance before calling if the amount is close to the available total.


Funding Flow

Every funding call follows the same shape:

  1. Submit — Call POST /v1/partner/deposits or POST /v1/partner/withdrawals with the client, asset, amount, and partner_order_ref.
  2. Validate — CoinMENA checks client eligibility, asset eligibility, balance (for withdrawals), and partner_order_ref uniqueness.
  3. Execute — The order is created and the client's balance is updated in the same call.
  4. Respond — The response contains the created order object with status: completed. Persist the order ID and your partner_order_ref.

No polling. No second call. The response is final.


Asset Eligibility

Not every asset can be used for funding. Each asset has three flags on the asset object that control eligibility:

FlagMeaning
publishedThe asset is visible on the platform. Required for both deposits and withdrawals
depositableThe asset can be deposited. Required for POST /v1/partner/deposits
withdrawableThe asset can be withdrawn. Required for POST /v1/partner/withdrawals

The rule: the asset submitted in a funding request must be published and have the correct flag for the operation (depositable for deposits, withdrawable for withdrawals). Funding is for fiat assets only (e.g. USD).

Submitting a crypto asset, an unpublished asset, or an asset missing the correct flag returns error 2012Invalid asset.

You can discover which assets are eligible by calling GET /v1/public/assets and filtering on these flags.


Deposits

Credit fiat to a client's account.

Request

Submit to POST /v1/partner/deposits:

FieldRequiredConstraintsDescription
partner_client_idYesmax 255The client whose balance is being credited
asset_idYesmax 10, must be a published, depositable fiat assetFiat asset identifier (e.g. USD)
amountYesstring decimal, > 0, max 8 decimal placesAmount to deposit
partner_order_refYesmax 255, unique per partnerYour own unique reference for this order. Used for reconciliation

Request Example

{
  "partner_client_id": "user_12345",
  "asset_id": "USD",
  "amount": "1000.00",
  "partner_order_ref": "deposit-abc-123"
}

Response

The deposit call returns the created order object. On a deposit, the debit field holds the deposited amount and credit is null:

{
  "result": {
    "id": 67890,
    "order_no": "MND0000067890",
    "partner_client_id": "user_12345",
    "type": "deposit",
    "source": "bank",
    "status": "completed",
    "credit": null,
    "credit_asset_id": null,
    "debit": "1000.00",
    "debit_asset_id": "USD",
    "fee": "0",
    "fee_asset_id": "USD",
    "vat": "0",
    "partner_order_ref": "deposit-abc-123",
    "price": null,
    "created_at": "2024-06-01T10:00:00Z",
    "transitioned_at": "2024-06-01T10:00:00Z",
    "updated_at": "2024-06-01T10:00:00Z"
  }
}

The client's USD available balance increases on return. See Reading the Response below for how to interpret the debit and credit fields.


Withdrawals

Debit fiat from a client's account.

Request

Submit to POST /v1/partner/withdrawals:

FieldRequiredConstraintsDescription
partner_client_idYesmax 255The client whose balance is being debited
asset_idYesmax 10, must be a published, withdrawable fiat assetFiat asset identifier (e.g. USD)
amountYesstring decimal, > 0, max 8 decimal placesAmount to withdraw
partner_order_refYesmax 255, unique per partnerYour own unique reference for this order. Used for reconciliation

Request Example

{
  "partner_client_id": "user_12345",
  "asset_id": "USD",
  "amount": "500.00",
  "partner_order_ref": "withdrawal-abc-456"
}

Response

The withdrawal call returns the created order object. On a withdrawal, the credit field holds the withdrawn amount and debit is null:

{
  "result": {
    "id": 67891,
    "order_no": "MNW0000067891",
    "partner_client_id": "user_12345",
    "type": "withdrawal",
    "source": "bank",
    "status": "completed",
    "credit": "500.00",
    "credit_asset_id": "USD",
    "debit": null,
    "debit_asset_id": null,
    "fee": "0",
    "fee_asset_id": "USD",
    "vat": "0",
    "partner_order_ref": "withdrawal-abc-456",
    "price": null,
    "created_at": "2024-06-01T10:05:00Z",
    "transitioned_at": "2024-06-01T10:05:00Z",
    "updated_at": "2024-06-01T10:05:00Z"
  }
}

The client's USD available balance decreases on return.


Reading the Response — debit vs credit

Deposits and withdrawals use debit and credit fields in different ways. Read them by looking at the order's type field first.

Order typedebit holdscredit holds
depositThe deposited amount (e.g. USD)null
withdrawalnullThe withdrawn amount (e.g. USD)

How to tell if a balance went up or down — don't rely on the field name. Use type:

  • type: deposit → client's balance increased by debit
  • type: withdrawal → client's balance decreased by credit
📘

Why does a deposit populate debit?

The debit and credit fields reflect CoinMENA's internal accounting convention, not the client's perspective. From CoinMENA's books, a deposit means CoinMENA records a debit entry (an asset received on its side), and a withdrawal means CoinMENA records a credit entry. You do not need to understand the accounting — just follow the mapping table above.

The same fields appear on trade orders (buy / sell) but with different semantics. See the Orders guide for the full mapping across all four order types.


Fee Fields in the Response

Every funding order response includes fee-related fields:

FieldDescription
feeFee amount recorded for this order
fee_asset_idAsset ID in which the fee is denominated
vatVAT amount recorded for this order

Always read these fields from the response rather than assuming a value. Record them on your side for accounting and reconciliation.


partner_order_ref — The Reconciliation Key

partner_order_ref is required for both deposits and withdrawals. It is your system's reference ID for the order, used to reconcile CoinMENA's order records against your own books.

Why It Matters

  • Your system of record stays yours. Store your internal ID as partner_order_ref. Later, fetch the order with GET /v1/partner/orders/ref/{partner_order_ref} — no mapping table needed between your IDs and CoinMENA's numeric id.
  • Duplicate protection. If your system accidentally submits the same funding call twice with the same partner_order_ref, the second call is rejected with 2020. This protects against duplicate order creation — but see the handling rules below.
  • Reconciliation. Every order response echoes back the partner_order_ref you submitted, so you can match CoinMENA's books to yours line by line.

Handling a 2020 Conflict

If you receive 2020 on a funding call:

  1. Do not retry with the same partner_order_ref. The original order already exists.
  2. Fetch the existing order with GET /v1/partner/orders/ref/{partner_order_ref}.
  3. Inspect the order's status:
    • If completed — the original succeeded; treat this as done.
    • If failed / rejected — the original did not succeed; retry with a new partner_order_ref.
  4. Update your internal state to reflect the actual outcome.
⚠️

2020 is not silent idempotency

A 2020 response does not return the existing order's data. You must call GET /v1/partner/orders/ref/{partner_order_ref} yourself to retrieve it.


Balances After Funding

Funding directly affects the client's asset balance. To understand the effect, you need two fields from the balance object:

FieldWhat It Represents
balanceTotal balance, including any amounts reserved or locked
available_balanceBalance available for trading or withdrawal — this is what you check before acting

Effect of Each Operation

OperationEffect on available_balance
DepositIncreases by the deposited amount (the debit value on the order response)
WithdrawalDecreases by the withdrawn amount (the credit value on the order response)
Trade (buy)Decreases the quote asset (e.g. USD), increases the base asset (e.g. BTC)
Trade (sell)Decreases the base asset, increases the quote asset
📘

Deposited funds are immediately usable for trading

Once a deposit response returns, the deposited amount is reflected in available_balance and can be used to calculate and execute quotes. There is no settlement window between depositing and trading.

Retrieving Balances

Two endpoints are available:

EndpointReturns
GET /v1/partner/balancesAll balances for the partner account, or for a specific client with ?partner_client_id=
GET /v1/partner/balances/{asset_id}Balance for one asset, partner-level or client-scoped

To retrieve a client's balance, pass ?partner_client_id=<your_client_ref>. Omitting it returns the partner-level balance.

Balance Response Example

{
  "items": [
    {
      "asset_id": "USD",
      "balance": "1000.00",
      "available_balance": "1000.00",
      "balance_usd": "1000.00",
      "available_balance_usd": "1000.00"
    },
    {
      "asset_id": "BTC",
      "balance": "0.00100000",
      "available_balance": "0.00100000",
      "balance_usd": "67.50",
      "available_balance_usd": "67.50"
    }
  ]
}
📘

Decimal parsing

Balance fields are returned as strings and may use scientific notation (e.g. "0E-8"). Parse with a decimal-aware type — Decimal in Python, decimal.js in JavaScript — never as a float or number.


Why Funding Can Fail

Beyond transport-level errors (timeouts, 5xx, etc.), a funding call can fail for these business reasons:

ReasonError CodeApplies ToFix
Invalid client ID2008Deposits, WithdrawalsVerify partner_client_id exists under your partner account
Client is not verified2009Deposits, WithdrawalsOnly verified clients can be funded
Client is deactivated2010Deposits, WithdrawalsReactivate the client via the activation endpoint
Asset not found, not published, or not depositable2012DepositsSubmit a published, depositable fiat asset
Asset not found, not published, or not withdrawable2012WithdrawalsSubmit a published, withdrawable fiat asset
Duplicate partner_order_ref2020Deposits, WithdrawalsUse a new unique reference — see Handling a 2020 Conflict
Insufficient balance3005WithdrawalsCheck available_balance before calling
Schema validation failure (invalid amount, missing field, etc.)422Deposits, WithdrawalsReview msg_detail to identify the failing field

Common Mistakes

The most frequent issues partners hit when implementing funding:

MistakeFix
Reusing partner_order_ref across ordersEach reference must be unique per partner. Duplicates return 2020
Retrying a failed funding call with the same partner_order_refLook up the existing order first — retry with a new reference only if the original truly failed
Submitting a crypto asset_idFunding endpoints accept fiat assets only
Submitting an asset without the correct eligibility flagCheck depositable for deposits and withdrawable for withdrawals on the asset object
Assuming credit always means "client received"Field meaning depends on order type — use the mapping table in Reading the Response
Parsing amount or balance fields as float / NumberUse a decimal-aware type — scientific notation breaks float parsing
Sending amount as a JSON numberSubmit as a string (e.g. "1000.00") to preserve precision
Withdrawing without checking available_balanceFor edge-case amounts, check balance first to avoid a 3005
Assuming completion is asyncFunding is synchronous — the returned order is final on response
Expecting 2020 to return the existing order2020 only signals the conflict; fetch the existing order separately

Related Error Codes

The errors you are most likely to see during funding:

CodeTriggerEndpoint
2008Invalid client IDDeposits, Withdrawals
2009Client is not yet verifiedDeposits, Withdrawals
2010Client is deactivatedDeposits, Withdrawals
2012Invalid asset (not found, not published, or wrong flag)Deposits, Withdrawals, GET /v1/partner/balances/{asset_id}
2020Duplicate partner_order_refDeposits, Withdrawals (also Execute)
3005Insufficient funds for paymentWithdrawals

See the Error Codes guide for the full reference.


What’s Next
Next StepDescription
OrdersThe order object, statuses, and retrieval patterns
TradingHow to execute trades on behalf of a client
Error CodesFull reference for every error the API returns