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

# Error Codes, HTTP Status Codes, and Retry Strategy

> Learn the Lyseis Pay error response format and how to handle authentication, validation, conflict, and service errors, with a clear retry strategy.

Every error response from Lyseis Pay follows a consistent JSON shape. At minimum you'll receive a `status` field (always `false` on error), a human-readable `message`, and a `path` indicating the endpoint that produced the error. When a request fails schema validation, the response also includes an `errors` array — each entry identifies the specific field, explains what went wrong, and provides a machine-readable `type` you can map to user-facing copy.

## Error Response Format

**Simple error**

```json theme={null}
{
  "status": false,
  "message": "Invalid or missing API key",
  "path": "/payments/initialize"
}
```

**Validation error with `errors` array**

```json theme={null}
{
  "status": false,
  "message": "Validation error for 'currency': String should match pattern '^[A-Z]{3}$'",
  "errors": [
    {
      "field": "currency",
      "message": "String should match pattern '^[A-Z]{3}$'",
      "type": "string_pattern_mismatch"
    }
  ],
  "path": "/payments/initialize"
}
```

***

## Authentication Errors (401 / 403)

These errors mean the request was rejected before it reached any business logic. Check your credentials, signing implementation, and timestamp freshness before retrying. All requests (except `GET /health`) must include the `X-Key-Id`, `X-Timestamp`, and `X-Signature` headers.

| Status | Message                      | Meaning                                                                       |
| ------ | ---------------------------- | ----------------------------------------------------------------------------- |
| 401    | Invalid or missing API key   | `X-Key-Id` is missing, inactive, unknown, or the request signature is invalid |
| 401    | Invalid request timestamp    | `X-Timestamp` is not a valid Unix timestamp                                   |
| 401    | Request timestamp is too old | Timestamp falls outside the 5-minute allowed request window                   |
| 403    | Missing required capability  | The API key does not have the capability required for this operation          |

***

## Validation Errors (400)

Validation errors indicate something wrong in your request body or parameters. Use the `field` and `message` values from the `errors` array to surface precise feedback to your users or flag the issue in your integration.

| Status | Message                                          | Meaning                                                                                 |
| ------ | ------------------------------------------------ | --------------------------------------------------------------------------------------- |
| 400    | Validation error for `{field}`: ...              | A field is missing, uses the wrong format, is unrecognised, or fails schema validation  |
| 400    | Invalid refund amount                            | The refund amount is not valid for this transaction                                     |
| 400    | Bank details must be provided for this operation | Destination bank information is missing from the request                                |
| 400    | Failed to resolve bank account details           | The bank account number could not be resolved — verify the bank code and account number |
| 400    | Minimum transaction amount is `{limit}`          | The submitted amount is below the minimum allowed                                       |
| 400    | Maximum transaction amount is `{limit}`          | The submitted amount exceeds the maximum allowed                                        |

<Note>
  When you receive a `400` with an `errors` array, iterate over each entry and display `errors[n].message` next to the relevant form field. Do not display the top-level `message` string directly to end users — it is intended for developers.
</Note>

***

## Not Found Errors (404)

A `404` means the reference or resource you provided does not match any record in Lyseis Pay. Double-check that the reference was created under the same API key and environment (live vs. sandbox) you are currently using.

| Status | Message                       | Meaning                                               |
| ------ | ----------------------------- | ----------------------------------------------------- |
| 404    | Invalid transaction reference | The reference does not identify a valid transaction   |
| 404    | Transaction record not found  | No payment record exists for the given identifier     |
| 404    | Refund record not found       | No refund was found for the supplied refund reference |
| 404    | Disbursement record not found | No transfer record was found for the given reference  |
| 404    | Virtual account not found     | No virtual account matches the provided identifier    |

***

## Conflict Errors (409)

Conflict errors indicate a state or uniqueness problem. The request was understood, but it cannot be fulfilled given the current state of the resource. Do not retry a `409` without first resolving the underlying cause.

| Status | Message                                                     | Meaning                                                                        |
| ------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------ |
| 409    | Reference already exists                                    | The reference is already in use — generate a new unique reference              |
| 409    | Duplicate transaction reference                             | This reference was already submitted for a transaction                         |
| 409    | Refund already exists for the given reference               | A refund was already created with this reference                               |
| 409    | Disbursement already processed for the given reference      | This transfer reference has already been processed                             |
| 409    | Invalid transaction status                                  | The requested operation is not valid for the payment's current status          |
| 409    | Invalid disbursement status                                 | The requested operation is not valid for the transfer's current status         |
| 409    | Mandate is not active or authorized                         | The mandate must be active and authorised before you can use it                |
| 409    | Mandate activation needs to be initiated first              | You must initiate mandate activation before calling validate                   |
| 409    | Direct debit payment already exists for the given reference | This direct debit reference has already been used                              |
| 409    | Insufficient funds                                          | Your merchant balance is too low to complete this operation — top up and retry |

***

## Expiry and Service Errors (410 / 500 / 503)

| Status | Message                           | Meaning                                                                     |
| ------ | --------------------------------- | --------------------------------------------------------------------------- |
| 410    | Transaction reference has expired | The reference can no longer be used — create a new transaction              |
| 503    | Payment service unavailable       | An upstream payment service is unreachable — retry with exponential backoff |
| 500    | Internal server error             | An unexpected error occurred on our end — contact support if it persists    |

***

## Retry Strategy

Knowing when to retry — and when not to — prevents duplicate transactions and wasted requests.

**Do not retry** errors in the `400`, `401`, `403`, `404`, and `409` families without first changing the request. These errors indicate a problem with the request itself (bad credentials, wrong field values, a duplicate reference, or an invalid state transition). Sending the same request again will produce the same error.

**Do retry** `502`, `503`, and transient `500` errors. These indicate a temporary infrastructure or upstream service problem that is likely to resolve on its own.

When retrying, follow an **exponential backoff** strategy:

```text theme={null}
Attempt 1 — wait 1 s
Attempt 2 — wait 2 s
Attempt 3 — wait 4 s
Attempt 4 — wait 8 s
...up to a maximum of 60 s between attempts
```

<Warning>
  Always preserve the **original reference** when retrying a request. Generating a new reference on retry can result in duplicate charges or transfers if the original request actually succeeded on the server before the network error occurred. Reusing the same reference lets Lyseis Pay deduplicate the request safely.
</Warning>
