Error Codes

Complete reference for all error codes returned by the CoinMENA Partner API.

The CoinMENA Partner API uses two layers of error information to help you identify and handle failures precisely:

  • HTTP status codes indicate the broad category of failure (authentication, validation, not found, etc.)
  • Application error codes (code field) explain the exact business or validation reason for the failure

Always handle errors using the application code field — it is stable and intended for programmatic use. The msg field is human-readable and may change over time. Multiple errors can share the same HTTP status code but have different application codes — always rely on code for precise handling.


Error Response Structure

Every error response returns a JSON object with the following fields:

{
  "code": 2008,
  "msg": "Invalid client ID",
  "msg_detail": null
}
FieldTypeDescription
codeintegerApplication-level error code. Use this for programmatic error handling
msgstringHuman-readable error message. May change — do not rely on it for logic
msg_detailobject, array, or nullAdditional error context. Present on validation errors and some trading errors. Null otherwise

How to Interpret an Error Response

When you receive an error, follow this order:

  1. Check the HTTP status — determines the broad failure category
  2. Check code — identifies the exact error reason
  3. Check msg — provides a human-readable description for logging or display
  4. Inspect msg_detail — if present, contains field-level validation errors or trading context
📘

Common debugging flow

If you receive an unexpected error:

  1. Check the HTTP status first
  2. Review the application code against this reference
  3. Use msg_detail to identify which field or value caused a validation failure
  4. Compare your request payload with the documented trigger for that error code

Decimal Fields and Scientific Notation

Decimal fields are returned as JSON strings and may use scientific notation when the value is very small or zero (e.g. "0E-8", "1e-8"). Always parse decimal fields using a decimal-aware type.

⚠️

Important

Do not parse decimal fields as JavaScript number or Python float — these types lose precision with financial values. Use Decimal in Python or a library like decimal.js in JavaScript.


HTTP Status Codes

StatusMeaning
200 / 201Request succeeded
204Request succeeded, no response body (e.g. client activation)
400Application-level error — check code for the exact reason
401Authentication failed — check the 401 section below
404Resource not found
409Conflict — duplicate partner_order_ref
422Request validation failed — check msg_detail for field-level errors

401 — Unauthorized

A 401 response can be returned for multiple reasons — invalid signature, expired timestamp, missing headers, or IP not whitelisted. All triggers return the same response body, so you cannot distinguish the cause from the response alone.

{
  "code": 401,
  "msg": "Unauthorized",
  "msg_detail": null
}
Trigger
Missing X-Partner-ID, X-Timestamp, or X-Signature headers
Invalid X-Partner-ID format
Invalid X-Timestamp format
Timestamp outside the 60-second validity window
Partner not found or inactive
Partner has no public key configured
Client IP not in the partner's IP whitelist
Ed25519 signature verification failed
📘

Debugging 401 errors

Since all 401 triggers look identical, work through the Authentication guide's troubleshooting checklist systematically. See the Authentication guide for the full checklist, and the IP Whitelisting guide if IP issues are suspected.


422 — Validation Error

Returned when the request body or parameters fail schema validation. The msg_detail field contains an array of field-level errors.

{
  "code": 422,
  "msg": "Validation Error",
  "msg_detail": [
    {
      "type": "email_parsing",
      "loc": ["body", "email"],
      "msg": "Input should be a valid email"
    }
  ]
}

Each object in msg_detail contains:

FieldDescription
locLocation of the invalid field as an array — tells you exactly where the validation failed (e.g. ["body", "email"])
msgHuman-readable description of what is wrong with that field
typeClassifies the validation failure type (e.g. email_parsing, greater_than, missing)

Common 422 Triggers

TriggerAffected Endpoints
Invalid JSON bodyAll endpoints that accept a request body
Missing or invalid required fieldsPOST /v1/partner/clients, PUT /v1/partner/clients/{id}, POST /v1/partner/deposits, POST /v1/partner/withdrawals, POST /v1/partner/quotes, POST /v1/partner/quotes/execute
Invalid email formatPOST /v1/partner/clients, PUT /v1/partner/clients/{id}
Invalid phone formatPOST /v1/partner/clients, PUT /v1/partner/clients/{id}
Employment fields missing for statusPOST /v1/partner/clients, PUT /v1/partner/clients/{id}
Forbidden employment fields for statusPOST /v1/partner/clients, PUT /v1/partner/clients/{id}
account_purpose is emptyPOST /v1/partner/clients, PUT /v1/partner/clients/{id}
Invalid or negative amountPOST /v1/partner/deposits, POST /v1/partner/withdrawals
Invalid amount for quotesPOST /v1/partner/quotes
page < 1, page_size < 1, or page_size > 100GET /v1/partner/clients, GET /v1/partner/orders, GET /v1/partner/clients/{id}/documents
Invalid enum value for filtersGET /v1/partner/clients, GET /v1/partner/orders, POST /v1/partner/clients, POST /v1/partner/quotes
Invalid datetime formatGET /v1/partner/clients, GET /v1/partner/orders
Invalid token formatPOST /v1/partner/quotes/execute
Field-level validation on any request schemaAll endpoints with request bodies or query parameters

Application Error Codes

Client Status Errors

Errors related to existing clients — identity, verification status, and activity state.

CodeHTTPMessageTriggerEndpoints
2008400Invalid client IDpartner_client_id does not exist or does not belong to this partnerAll endpoints that accept partner_client_id
2009400The client is not yet verifiedClient is not in verified statusPOST /v1/partner/deposits, POST /v1/partner/withdrawals, POST /v1/partner/quotes, POST /v1/partner/quotes/execute
2010400The client is deactivatedClient active is falsePOST /v1/partner/deposits, POST /v1/partner/withdrawals, POST /v1/partner/quotes, POST /v1/partner/quotes/execute

Client Onboarding Errors

Returned by POST /v1/partner/clients (create) and PUT /v1/partner/clients/{id} (update) when client payload validation fails.

CodeHTTPMessageTriggerApplies To
2016400Government ID is already being used by another approved clientDuplicate government_id_number already registered for another clientCreate, Update
2021400Client is under the legal agebirth_date below the legal age thresholdCreate only
2022400Invalid residency countryresidency_id is not a supported or acceptable residency countryCreate, Update
2023400Invalid citizenship countrycitizenship_id is not a supported or acceptable citizenship countryCreate, Update
2024400Invalid place of birth countryplace_of_birth_id is not a supported countryCreate only
2025400Residency visa number and expiry are requiredresidency_visa_number or residency_visa_doe missing when requiredCreate, Update
2026400A client with this partner_client_id already existsDuplicate partner_client_id already registered under this partnerCreate only
2027400A client with this email already existsDuplicate email already registered under this partnerCreate, Update
2028400A client with this phone already existsDuplicate phone already registered under this partnerCreate, Update
📘

2024 and 2026 on update

place_of_birth_id and partner_client_id are immutable after client creation — they cannot be modified via PUT /v1/partner/clients/{id}. Errors 2024 and 2026 can only occur on client creation.


Asset Errors

CodeHTTPMessageTriggerEndpoints
2012400Invalid assetAsset not found, not published, not fiat, or not depositablePOST /v1/partner/deposits
2012400Invalid assetAsset not found, not published, not fiat, or not withdrawablePOST /v1/partner/withdrawals
2012400Invalid assetAsset not found or not supportedGET /v1/partner/balances/{asset_id}
2013400Invalid asset pairAsset pair not found or not available to this partnerPOST /v1/partner/quotes
📘

GET /v1/partner/balances/{asset_id} — two possible 400 errors

This endpoint can return either 2012 (invalid asset) or 2008 (invalid client) when a partner_client_id query parameter is supplied and doesn't match. Check the code field to determine which.


Order and Funds Errors

CodeHTTPMessageTriggermsg_detailEndpoints
2020409An order with this partner_order_ref already existsDuplicate partner_order_ref for the same partnernullPOST /v1/partner/quotes/execute, POST /v1/partner/deposits, POST /v1/partner/withdrawals
3005400Insufficient fundsClient balance is insufficient for the trade{"quote": {...}}POST /v1/partner/quotes
3005400Insufficient funds for paymentClient balance is insufficient for the withdrawalnullPOST /v1/partner/withdrawals
📘

3005 on quotes

When returned on POST /v1/partner/quotes, the response includes a quote object in msg_detail with the calculated price and amounts. You can use this to show the client the current market rate even when the trade cannot be executed.

{
  "code": 3005,
  "msg": "Insufficient funds",
  "msg_detail": {
    "quote": {
      "market_price": "74100.4093",
      "base_amount": "0.13000000",
      "quote_amount": "9633.15",
      "fee_amount": "0.09",
      "vat_percentage": null,
      "vat_amount": "0.00",
      "lifetime": 15,
      "token": null
    }
  }
}

Trading Errors

CodeHTTPMessageTriggermsg_detail
4000400Trading is not availableAsset pair is not tradable{"quote": {...}}
4001400Trading is temporarily unavailablePrice feed is down for this asset pair{"quote": {...}}
4003400Amount exceeds the maximum allowedRequested amount is above the asset pair's maximum volume{"limit": "...", "quote": {...}}
4004400Amount is below the minimum allowedRequested amount is below the asset pair's minimum volume{"limit": "...", "quote": {...}}
4008400Trading token is invalidToken expired, client mismatch, or invalid/corrupted tokennull

Trading errors 4000, 4001, 4003, 4004 apply to POST /v1/partner/quotes. Error 4008 applies to POST /v1/partner/quotes/execute.

📘

Trading errors and msg_detail

Errors 4000, 4001, 4003, and 4004 return a quote object in msg_detail even on failure. For 4003 and 4004, a limit field is also returned showing the applicable minimum or maximum volume. Use this to show the user the current market price and explain why their trade was rejected.

{
  "code": 4004,
  "msg": "Amount is below the minimum allowed",
  "msg_detail": {
    "limit": "0.00020000",
    "quote": {
      "market_price": "74815.8482",
      "base_amount": "0.00000200",
      "quote_amount": "0.15",
      "fee_amount": "0.00",
      "vat_percentage": null,
      "vat_amount": "0.00",
      "lifetime": 15,
      "token": null
    }
  }
}

Not Found Errors

{
  "code": 404,
  "msg": "Not Found",
  "msg_detail": null
}
CodeHTTPMessageTriggerEndpoints
404404Not FoundAsset not foundGET /v1/public/assets/{asset_id}
404404Not FoundCountry not foundGET /v1/public/countries/{country_id}
404404Not FoundAsset pair not found or not available to this partnerGET /v1/partner/asset-pairs/{asset_pair_id}
404404Not FoundOrder not found or does not belong to this partnerGET /v1/partner/orders/{order_id}, GET /v1/partner/orders/ref/{partner_order_ref}
404404Not FoundDocument not found or does not belong to this clientGET /v1/partner/clients/{id}/documents/{document_id}

Recommended Error Handling

ScenarioRecommendation
401 errorsDo not retry without fixing the signature, timestamp, or IP. Check the Authentication and IP Whitelisting guides
422 errorsDo not retry without fixing the request — use msg_detail to identify which field failed
409 errors (2020)Do not retry — use a new unique partner_order_ref or check whether the order already succeeded
404 errorsVerify the resource ID is correct and belongs to your partner account
400 client onboarding errorsDo not retry — fix the duplicate or invalid field identified by the error code
400 trading errors (40004004)Use msg_detail to surface context to the user — the quote object contains the current market price
400 3005Client has insufficient funds — fund the client via POST /v1/partner/deposits or reduce trade amount
500 errorsUnexpected server errors — retry with exponential backoff and contact support if persistent
📘

Integration best practices

  • Always use the application code for programmatic error handling — not msg
  • Log both the HTTP status and the application code for every error
  • Surface user-friendly messages in your app rather than raw API error messages
  • Never retry 422, 409, or client onboarding 400 errors without modifying the request first


What’s Next
Next StepDescription
AuthenticationFull breakdown of the signing algorithm, rules, and troubleshooting
IP WhitelistingAdd a second security layer to your integration
PaginationHow to work with paginated list endpoints