> For the complete documentation index, see [llms.txt](https://slippay.gitbook.io/slippay-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://slippay.gitbook.io/slippay-docs/api-reference/errors.md).

# Errors

SlipPay returns errors as JSON with consistent shape:

```json
{
  "error": "validation_error",
  "detail": "brl_amount: must be string with 2 decimals",
  "issues": [ ... ]
}
```

| field    | type   | when present                                     |
| -------- | ------ | ------------------------------------------------ |
| `error`  | string | always; machine-readable code                    |
| `detail` | string | optional; human-readable explanation             |
| `issues` | array  | only on `validation_error`; per-field zod issues |

## Status code conventions

| status | meaning                                                              |
| ------ | -------------------------------------------------------------------- |
| 2xx    | success                                                              |
| 400    | malformed request, validation failure, business-rule violation       |
| 401    | missing or invalid credentials                                       |
| 403    | authenticated but forbidden from the resource                        |
| 404    | resource not found OR you don't have permission to see it (no leak)  |
| 409    | resource state conflicts with the action (e.g., charge after cancel) |
| 422    | semantic error in input that schema didn't catch                     |
| 5xx    | SlipPay broke; safe to retry with backoff                            |

## Common error codes

### Authentication

| status | code                    | meaning                            |
| ------ | ----------------------- | ---------------------------------- |
| 401    | `missing_authorization` | no `Authorization` header          |
| 401    | `invalid_api_key`       | API key doesn't match any merchant |
| 401    | `invalid_jwt`           | JWT signature failed or expired    |
| 403    | `forbidden`             | wrong owner                        |

### Validation

| status | code               | meaning                              |
| ------ | ------------------ | ------------------------------------ |
| 400    | `validation_error` | zod failed; see `issues` for details |
| 400    | `empty_update`     | PATCH body had no editable fields    |

### Orders

| status | code            | meaning                                      |
| ------ | --------------- | -------------------------------------------- |
| 400    | `create_failed` | DB insert error; `detail` has the message    |
| 400    | `cannot_cancel` | order is not in `pending` state              |
| 404    | `not_found`     | order doesn't exist or doesn't belong to you |

### Subscriptions

| status | code                  | meaning                                                  |
| ------ | --------------------- | -------------------------------------------------------- |
| 404    | `not_found`           | subscription doesn't exist or wrong owner                |
| 409    | `not_active`          | status is paused, cancelled, or expired                  |
| 409    | `expired`             | expires\_at has passed                                   |
| 409    | `max_periods_reached` | charges\_done >= max\_periods                            |
| 400    | `order_create_failed` | charge failed to materialize order; `detail` has message |
| 400    | `cannot_cancel`       | already cancelled                                        |

### Merchants

| status | code            | meaning                                            |
| ------ | --------------- | -------------------------------------------------- |
| 400    | `create_failed` | DB insert failed (likely duplicate auth\_user\_id) |
| 400    | `update_failed` | PATCH failed                                       |
| 400    | `rotate_failed` | key rotation failed                                |
| 404    | `not_found`     | no merchant for this auth user                     |

## Retry guidance

| status                  | retry?                                                                                                                                       |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| 4xx                     | no — the request is wrong; fix and retry manually                                                                                            |
| 5xx                     | yes — exponential backoff, max 5 attempts                                                                                                    |
| network error / timeout | yes — but be careful about idempotency (orders are not idempotent on POST; use the `subscription.charge` idempotency contract for recurring) |

## Validation issue shape

When `error` is `validation_error`, `issues` contains zod's per-field errors:

```json
{
  "error": "validation_error",
  "issues": [
    {
      "path": ["brl_amount"],
      "code": "invalid_string",
      "message": "must be string with 2 decimals"
    },
    {
      "path": ["period_seconds"],
      "code": "too_small",
      "message": "Number must be greater than or equal to 86400"
    }
  ]
}
```

Use `issues[i].path` to map back to your form fields.

## Reporting bugs

If you hit an error code that's not documented here, or a 5xx with no useful detail, file an issue at [github.com/Galmanus/slippay/issues](https://github.com/Galmanus/slippay/issues) with:

* the request you sent (sanitize the API key)
* the response body and status
* timestamp (so we can find the request in server logs)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://slippay.gitbook.io/slippay-docs/api-reference/errors.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
