.. _errors: Error Reference =============== Every error returned by the External Payments API uses a single structured envelope. This page documents the envelope, the response headers that accompany errors, and every error code the API can return. Error Envelope -------------- All errors are returned as JSON with a single top-level ``error`` object: .. code-block:: json { "error": { "type": "invalid_request_error", "code": "parameter_unknown", "errorCode": "E1002", "message": "property payer should not exist", "param": "payer", "docUrl": "https://docs.miraclecash.info/errors#E1002", "userSafeMessage": false, "requestId": "8f14e45f-ceea-4f3a-9a5a-1c0d2e3f4a5b" } } **Envelope Fields:** .. list-table:: :widths: 22 15 63 :header-rows: 1 * - Field - Type - Description * - ``type`` - string - The broad error category. See :ref:`error_types` below. * - ``code`` - string - Machine-readable error slug (e.g. ``parameter_unknown``). Use this for programmatic error handling. * - ``errorCode`` - string - Short alphanumeric code (e.g. ``E1002``) for support and documentation references. * - ``message`` - string - Human-readable, developer-facing description of what went wrong. * - ``param`` - string - The request parameter the error relates to, when applicable. Omitted otherwise. * - ``docUrl`` - string - Link to the documentation section for this error code. * - ``userSafeMessage`` - boolean - ``true`` when ``message`` is safe to display to your end customer as-is. When ``false`` (the default for almost all codes), treat ``message`` as developer-facing and show your own copy to customers. * - ``requestId`` - string - Unique ID of this request. Include it when contacting support about an error. Response Headers ---------------- .. list-table:: :widths: 25 75 :header-rows: 1 * - Header - Description * - ``X-MP-Should-Retry`` - ``true`` means the exact same request may succeed if repeated (the failure is transient — e.g. rate limiting, clock skew, an internal error). ``false`` means the request must be changed before retrying. * - ``Retry-After`` - Present on ``429`` rate-limit responses and on ``409`` idempotency in-progress responses (:ref:`E4003 `). Number of seconds to wait before retrying. .. _error_types: Error Types ----------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Type - Description * - ``invalid_request_error`` - The request body, parameters, or referenced resources are invalid. * - ``authentication_error`` - The request signature, API key, timestamp, or nonce failed verification. * - ``permission_error`` - The API key is valid but lacks the scope required by the endpoint. * - ``idempotency_error`` - A problem with the ``Idempotency-Key`` header or a conflicting replay. * - ``rate_limit_error`` - Too many requests — slow down and retry after the window clears. * - ``api_error`` - Something failed on MiraclePay's side. Safe to retry. Error Codes ----------- Validation Errors (E1xxx) ~~~~~~~~~~~~~~~~~~~~~~~~~ .. raw:: html invalid_request (E1000) ^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no The request is malformed in a way not attributable to a single parameter — for example an unreadable JSON body. Fix the request before retrying. .. raw:: html parameter_invalid (E1001) ^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no A request parameter failed validation — wrong type, out of range, or an invalid combination (e.g. passing both ``startingAfter`` and ``endingBefore``). The ``param`` field names the offending parameter and ``message`` contains the validation detail. .. raw:: html parameter_unknown (E1002) ^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no The request contains a field the API does not recognize. Unknown fields are rejected, not silently ignored — remove the field named in ``param``. .. raw:: html redirect_domains_not_configured (E1010) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no You passed a ``redirectUrl`` but your merchant account has no allowed redirect domains configured. Add the domain in the dashboard under **Developer Settings** first. .. raw:: html redirect_url_invalid (E1011) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no The ``redirectUrl`` is not a valid URL (or is not ``https`` where required). Fix the URL format. .. raw:: html redirect_domain_not_allowed (E1012) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no The hostname of the ``redirectUrl`` is not on your allowed redirect domains list. The hostname must exactly match one of the configured domains. .. raw:: html blockchain_not_configured (E1020) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no One or more of the requested ``blockchainIds`` are not available for your merchant account — either the network is not active or no payment address is configured for it. Use ``GET /external/v1/blockchains/active`` to see which networks you can accept, and configure the missing ones in the dashboard. .. raw:: html merchant_not_configured (E1030) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``invalid_request_error`` · Retry: no Your merchant account is missing configuration required to create payments (for example, no main branch). The ``message`` explains what is missing; contact support if unclear. .. raw:: html conflict (E1040) ^^^^^^^^^^^^^^^^ **HTTP 409** · ``invalid_request_error`` · Retry: no The request conflicts with the current state of a resource. Inspect the ``message`` for detail. Authentication and Permission Errors (E2xxx) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. raw:: html authentication_required (E2001) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no One or more of the required signing headers (``X-MP-KEY-ID``, ``X-MP-PASSPHRASE``, ``X-MP-TIMESTAMP``, ``X-MP-NONCE``, ``X-MP-SIGNATURE``) is missing. See :ref:`authentication`. .. raw:: html timestamp_invalid (E2002) ^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no ``X-MP-TIMESTAMP`` is not a valid Unix timestamp in seconds. Send an integer number of seconds since the epoch, as a string. .. raw:: html timestamp_expired (E2003) ^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · **Retry: yes** The request timestamp is outside the ±300 second acceptance window. This usually means your server clock has drifted — sync it (NTP) and retry with a freshly signed request. .. raw:: html api_key_invalid (E2004) ^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no The ``X-MP-KEY-ID`` does not correspond to a known API key, or the passphrase does not match. Check that you copied the key ID and passphrase exactly as shown at creation. .. raw:: html api_key_revoked (E2005) ^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no The API key has been revoked. Create a new key in the dashboard. .. raw:: html api_key_expired (E2006) ^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no The API key has passed its configured expiry date. Create a new key or rotate the existing one in the dashboard. .. raw:: html signature_invalid (E2007) ^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no The ``X-MP-SIGNATURE`` does not match the expected HMAC. The most common causes: the signed ``path`` differs from the path actually sent (missing ``/external/v1`` prefix or query string), the body was re-serialized after signing, or the wrong secret was used. See :ref:`authentication` for the canonical string rules. .. raw:: html merchant_disabled (E2008) ^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no The merchant account that owns this API key is inactive. Contact support. .. raw:: html api_signature_replayed (E2009) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 401** · ``authentication_error`` · Retry: no The ``X-MP-NONCE`` was already used within the timestamp window — the request looks like a replay. Do **not** resend the identical signed request; a genuine retry must be re-signed with a fresh nonce and timestamp. .. raw:: html insufficient_scope (E2101) ^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 403** · ``permission_error`` · Retry: no The API key is valid but does not have the scope this endpoint requires (e.g. calling ``POST /payments/prompt`` with a key lacking ``payment_prompts:write``). Create or update a key with the required scope in the dashboard. .. raw:: html merchant_onboarding_incomplete (E2102) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 403** · ``permission_error`` · Retry: no Your Merchant Onboarding has not been approved yet, so the signed API is unavailable (US merchant accounts). Finish Merchant Onboarding in the dashboard; requests succeed once it is approved. Retrying without completing onboarding will keep failing. Resource Errors (E3xxx) ~~~~~~~~~~~~~~~~~~~~~~~ .. raw:: html resource_missing (E3001) ^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 404** · ``invalid_request_error`` · Retry: no The requested resource does not exist — or does not belong to your merchant account. A payment ID owned by another merchant returns this same error; existence is never leaked. Also returned for unknown pagination cursors. Idempotency Errors (E4xxx) ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. raw:: html idempotency_key_invalid (E4001) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 400** · ``idempotency_error`` · Retry: no The ``Idempotency-Key`` header is malformed (e.g. longer than 255 characters). Fix the key value. .. raw:: html idempotency_params_mismatch (E4002) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 409** · ``idempotency_error`` · Retry: no An ``Idempotency-Key`` was reused with a different request body than the original request. Use a new key for a new request, or resend the exact original body to receive the cached response. .. raw:: html idempotency_in_progress (E4003) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 409** · ``idempotency_error`` · **Retry: yes** A request with the same ``Idempotency-Key`` is still being processed. Wait for the number of seconds indicated by the ``Retry-After`` header, then retry — you will receive the original request's response. Internal Errors (E5xxx) ~~~~~~~~~~~~~~~~~~~~~~~ .. raw:: html internal_error (E5001) ^^^^^^^^^^^^^^^^^^^^^^ **HTTP 500** · ``api_error`` · **Retry: yes** Something went wrong on MiraclePay's side. Safe to retry with backoff. This is the only error whose ``message`` is flagged ``userSafeMessage: true``. If the error persists, contact support with the ``requestId``. .. raw:: html service_unavailable (E5002) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ **HTTP 503** · ``api_error`` · **Retry: yes** A backing dependency is temporarily unavailable and the API refused to run a state-changing request without it. Retry with backoff once the dependency recovers. Rate Limiting (E9xxx) ~~~~~~~~~~~~~~~~~~~~~ .. raw:: html rate_limited (E9001) ^^^^^^^^^^^^^^^^^^^^ **HTTP 429** · ``rate_limit_error`` · **Retry: yes** You exceeded the rate limit (60 requests per 60 seconds). The exact same request will succeed once the window clears — honor the ``Retry-After`` header and retry with backoff.