## Overview

Reservepay uses a standardized error format called **error triples**. Almost all business errors return HTTP `400` with a JSON array containing three elements: a machine-readable code, a human-readable message, and additional details.

An unexpected server error returns HTTP `500` with the code `UNHANDLED_ERROR`. In your code, branch on the error code rather than the HTTP status.

## The error triple

Every error response follows this exact structure:

```plain
[ERROR_CODE, ERROR_MESSAGE, ERROR_DETAILS]
```

| Element | Type | Description |
| :--- | :--- | :--- |
| **Code** | `string` | A unique, machine-readable identifier for the error (e.g., `INVALID_ARGUMENTS`). |
| **Message** | `string` | A short description of what went wrong, intended for developers. |
| **Details** | `any` | Additional data to help diagnose the issue. This can be an object, an array, or `null`. |

## When errors occur

HTTP `400` covers expected failures:

*   **Validation failures:** Missing required fields or invalid data formats.
*   **Business logic errors:** Eligibility failures, conflicts, or invalid transitions.
*   **Authentication issues:** Missing or invalid API keys.

Not-found, conflict, validation, and eligibility failures all return `400`. Use the triple code to tell them apart.

An error triple means your API call failed. It's different from a failed payment: when a payment ends up `FAILED`, the call that fetched it succeeds, and the payment object carries its own failure `code`, such as `insufficient_funds`. See [Payment failure codes](/guides/payment-failure-codes) for that list.

## Working with details

The third element of the triple, `ERROR_DETAILS`, provides context that varies depending on the error code.

For validation errors, it often contains an array of specific field issues:

```json
[
  "INVALID_ARGUMENTS",
  "One or more of the supplied arguments are invalid",
  [
    {
      "type": "invalid",
      "argument": "month",
      "message": "Invalid format, expected YYYY-MM, got 12/2025"
    }
  ]
]
```

In other cases, such as a generic authentication failure, the details might be `null`:

```json
[
  "UNAUTHORIZED",
  "Invalid API key provided.",
  null
]
```

Your error handling logic should check if `details` is present before attempting to parse it.

## Common errors

While specific endpoints may define their own error codes, here are some you will encounter across the API:

| Code | Description |
| :--- | :--- |
| `INVALID_ARGUMENTS` | This error occurs when the request contains invalid or missing parameters. Common cases include missing required fields, or values that don't match the expected format or type. |
| `NOT_FOUND` | This error occurs when some records could not be found for the given ID(s). |
| `UNAUTHORIZED` | This error occurs when the request lacks valid authentication credentials. |
| `BAD_VERSION` | This error occurs when making requests to an API version that does not exist. This commonly happens when using an outdated SDK or when the `Api-Version` header is missing or incorrect. |
| `UNHANDLED_ERROR` | This error occurs when the server encounters an unexpected internal error that it cannot handle gracefully. This typically happens due to bugs, infrastructure issues, or edge cases that weren't anticipated during development. HTTP `500` indicates this code. Check the operation's outcome before retrying a write. |

## Retrying requests

* **Reads:** Retry network timeouts and `UNHANDLED_ERROR` after a short delay.
* **Writes:** Find out whether the first request succeeded before you retry. A timeout or `UNHANDLED_ERROR` can happen after Reservepay has already accepted the request. See [Idempotency and timeouts](/guides/calling-api-endpoints#idempotency-and-timeouts) for how to check each operation.
* **Unknown codes:** Handle the codes listed in each endpoint's reference and add a default branch for anything else. For an unknown code, stop retrying, log it, and check the payment or payout state. The error alone doesn't tell you the final status.

## Support

For technical issues, email [support@reservepay.com](mailto:support@reservepay.com). Check [https://status.reservepay.com](https://status.reservepay.com) for platform incidents.
