> ## Documentation Index
> Fetch the complete documentation index at: https://docs.c2cpayment.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> HTTP status codes and error response formats returned by the C2C Merchant API.

## Error response formats

The API uses standard HTTP status codes. The body format depends on which layer rejected the request.

<Tabs>
  <Tab title="Business & validation errors">
    Most errors (`400`, `403`, `404`, `409`, `422`) return a single message:

    ```json theme={null}
    {
      "error": "This Idempotency-Key was already used for a different order request."
    }
    ```

    When several validation rules fail, the messages are joined with `; `.
  </Tab>

  <Tab title="Signature errors">
    Signature failures (`401`) and oversized bodies (`413`) return a machine-readable `code` and a `traceId`:

    ```json theme={null}
    {
      "success": false,
      "error": "Request signature verification failed. Sign the request as described in the signature guide.",
      "code": "SIGNATURE_INVALID",
      "traceId": "b46d6b4e36bdcf0b90f5527593af8b46"
    }
    ```
  </Tab>

  <Tab title="Malformed requests">
    Requests that can't be bound (`400`), such as an unknown enum value or a missing `Idempotency-Key`, return RFC 9110 problem details. (On order creation, a body that isn't valid JSON is rejected earlier, by the signature check, with `401 SIGNATURE_MALFORMED`.)

    ```json theme={null}
    {
      "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
      "title": "One or more validation errors occurred.",
      "status": 400,
      "errors": {
        "Idempotency-Key": ["The idempotencyKey field is required."]
      },
      "traceId": "08d783466a8cf7d33462b9f43b83ff43"
    }
    ```
  </Tab>

  <Tab title="Empty body">
    `401` for a missing or invalid **API key** returns **no body**. Branch on the status code.
  </Tab>
</Tabs>

<Tip>
  Branch on the **HTTP status** and, for signature errors, on `code`. The `error` text is meant for humans and can change. Always log the `traceId` when one is present and quote it to support.
</Tip>

## HTTP status codes

| Status | Meaning | Retry? |
| - | - | - |
| `200` | Success. For order creation, also returned when an `Idempotency-Key` replay finds the existing order, and when no member is available yet (the order is accepted as `Awaiting`). | – |
| `400` | Invalid request: validation failed (including amount precision), malformed JSON, unknown enum value, missing `Idempotency-Key`, or a status query without an order ID or `merchantOrderRef` | No. Fix the request first. |
| `401` | API key missing or invalid (empty body), **or** request signature rejected (`code` in body) | No. Fix the credentials or signature. For `SIGNATURE_REPLAYED`, retry with the original `Idempotency-Key`. |
| `403` | Merchant account not active, or caller IP not in your whitelist | No. Contact C2C. |
| `404` | Order not found for your merchant account | No |
| `409` | `merchantOrderRef` already used by an order that is in progress or completed | No. Retry with the same `Idempotency-Key`, or use a new reference for a new payment. |
| `413` | Request body over 64 KB (`PAYLOAD_TOO_LARGE`) | No. Shrink the body. |
| `422` | Business rule declined the order: payment method (`walletType`) disabled for your account, insufficient merchant balance (withdrawals), or `Idempotency-Key` reused with different terms | Method disabled: no. Insufficient balance: after a top-up. Key reused: no. Use a new key for a new order. |
| `500` | Unexpected server error (problem details with `traceId`) | **Yes**, with backoff. For order creation, reuse the same `Idempotency-Key`. |

## Error catalogue

### Authentication and signature

| Status | `code` / message | Cause |
| - | - | - |
| `401` | *(empty body)* | No `C2C-API-Key` (or `Authorization: Bearer mk_...`) header, a `C2C-API-Key` that isn't an `mk_` key, or a key that is unknown or revoked |
| `401` | `SIGNATURE_REQUIRED` | Order creation body has no `signature` field, or it is `null` or empty |
| `401` | `SIGNATURE_MALFORMED` | Body isn't a single JSON object, `signature` isn't a string, or a key appears twice in different cases |
| `401` | `SIGNATURE_INVALID` | Signature doesn't match, or the API key has no signing secret |
| `401` | `SIGNATURE_REPLAYED` | The same signed body was already accepted with a different `Idempotency-Key`; retry with the original key |
| `413` | `PAYLOAD_TOO_LARGE` | Body larger than 64 KB |

See the [Signature Generation Guide](/api-reference/signature-guide#common-mistakes-and-troubleshooting) for fixes.

### Order creation (`POST /api/merchant/orders`)

| Status | Message (examples) | Cause |
| - | - | - |
| `400` | `'Amount' must be greater than '0'.` | Invalid amount |
| `400` | `Amount must have at most 4 decimal places and be less than 100,000,000,000,000.` | Amount too precise or too large |
| `400` | `Currency must be one of: PKR, INR, BDT.` | Unsupported currency |
| `400` | `CustomerAccountName can only be sent together with CustomerAccountNumber.` | Withdrawal with an account holder name but no account number |
| `400` | `CallbackUrl must be a valid absolute http(s) URL.` | Not an absolute `http://` / `https://` URL. Same for `SuccessUrl` / `FailureUrl`. |
| `400` | `'Txn Ref Digits Required' must be between 4 and 8. You entered 3.` | `txnRefDigitsRequired` out of range. The option only concerns the account number and Till ID methods; the QR methods don't ask for transaction ID digits. |
| `400` | `JazzCashQR is a deposit-only payment method. A withdrawal's walletType must be one of: JazzCash, Easypaisa, TillID, BankAccount.` | Withdrawal with `walletType` `JazzCashTillID`, `JazzCashQR` or `EasypaisaQR`. See [Payment methods](/guides/payment-methods#withdrawals). |
| `400` | Problem details, `errors.Idempotency-Key` | Header missing |
| `400` | Problem details, `errors.$.walletType` | Unknown `orderType` / `walletType` value |
| `403` | `Merchant account is suspended; new orders are not accepted.` | Account not active |
| `403` | `IP not in whitelist.` | Your IP whitelist doesn't allow the caller's IP for this order type |
| `422` | `Insufficient merchant balance: 2500.00 PKR available, 3000.00 PKR required …` | Withdrawal's amount + fee not covered by your available balance, which already excludes withdrawals in progress |
| `409` | `merchantOrderRef 'INV-10045' is already used by order ORD-…. Reuse the same Idempotency-Key to retry a request, or use a new reference for a new payment.` | Another order that is in progress or completed already uses this reference. References of failed orders can be reused. |
| `422` | `JazzCash deposits are disabled for this merchant.` | That payment method (`walletType`) is disabled for your account and order type. Each of the methods is switched on or off separately. |
| `422` | `This Idempotency-Key was already used for a different order request.` | Same key, different `orderType`, `amount`, `walletType`, `currency`, `merchantOrderRef` or `customerAccountNumber`. See [Idempotency](/api-reference/idempotency). |

<Note>
  There's no "no member available" error. When no eligible member is online, the order is accepted with status `Awaiting` and assigned later. See [Order status](/guides/order-status).
</Note>

### Order status and balance

| Status | Message | Cause |
| - | - | - |
| `400` | `Provide an orderId, an orderReference or a merchantOrderRef.` | Status query by reference without a `merchantOrderRef` or `orderReference` value |
| `400` | `Provide either an orderReference or a merchantOrderRef, not both.` | Status query by reference with both parameters |
| `404` | `Order not found.` | No order with this `orderId`, `orderReference` or `merchantOrderRef` for your merchant account |
| `404` | `API key not found or inactive.` | Key revoked while the request was being processed |

## Recommended handling

```javascript Node.js theme={null}
async function handle(response) {
  if (response.ok) return (await response.json()).data;

  const text = await response.text();
  const body = text ? JSON.parse(text) : null;

  switch (response.status) {
    case 401:
      // body === null → API key problem; body.code → signature problem
      throw new Error(body?.code ? `Signature rejected: ${body.code} (trace ${body.traceId})` : 'Invalid API key');
    case 409:
      // merchantOrderRef already in use: look the existing order up instead of creating another
      throw new Error(`Duplicate reference: ${body.error}`);
    case 422:
      // Payment method disabled, insufficient balance, or Idempotency-Key reused with different terms
      throw new Error(`Declined: ${body.error}`);
    case 500:
      throw Object.assign(new Error(`Retryable HTTP ${response.status}`), { retryable: true, traceId: body?.traceId });
    default:
      throw new Error(`HTTP ${response.status}: ${body?.error ?? body?.title ?? 'request failed'}`);
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.