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

# ABP Error Handling

> ABP API error codes, validation errors, order decline reasons, and resilience patterns. Learn how to handle errors in your integration.

## Error response format

ABP returns errors in two shapes, depending on where the error originates:

* **Auth / rate-limit middleware** errors use an `error` key:

  ```json theme={null}
  { "error": "Invalid or inactive API key" }
  ```

* **Application / route** errors (validation, not-found, etc.) use the FastAPI-standard `detail` key:

  ```json theme={null}
  { "detail": "No odds found for given parameters" }
  ```

Handle both shapes in your client.

Request-body validation errors (`422`) include field-level detail with a `loc` path:

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "orders", 0, "orderStake"],
      "msg": "Input should be greater than 0",
      "type": "greater_than"
    }
  ]
}
```

## HTTP status codes

| Status | Description                                                                   |
| ------ | ----------------------------------------------------------------------------- |
| `200`  | Success                                                                       |
| `201`  | Resource created                                                              |
| `204`  | Resource deleted (no content)                                                 |
| `400`  | Bad request — invalid or missing parameters                                   |
| `401`  | Unauthorized — invalid or inactive API key                                    |
| `403`  | Forbidden — missing API key header, or resource belongs to a different client |
| `404`  | Not found — resource does not exist                                           |
| `409`  | Conflict — every order in the request is a duplicate (see below)              |
| `422`  | Validation error — request body failed validation                             |
| `429`  | Rate limited — exceeded requests per second                                   |
| `500`  | Internal server error                                                         |
| `501`  | Not implemented — futures markets (`futureId`) are not yet supported          |
| `503`  | Service unavailable — database or dependency down                             |

## Order decline reasons

When placing orders via `POST /place-orders`, orders that fail business validation are returned in the `declinedOrders` array (not as HTTP errors). Each declined order includes a `declineReason`:

| Decline reason               | Description                                                     |
| ---------------------------- | --------------------------------------------------------------- |
| Stake exceeds limit          | `orderStake` is higher than the available bookmaker limit       |
| Stake below minimum          | `orderStake` is below the bookmaker's or account's minimum      |
| Invalid odds                 | `orderPrice` is not available or the market is suspended        |
| No active accounts           | No active bookmaker accounts available for this market          |
| Currency conversion failed   | Could not convert between order currency and bookmaker currency |
| Bookmaker not available      | Specified bookmaker doesn't have odds for this fixture/outcome  |
| Odds temporarily unavailable | Odds could not be fetched in time; retry                        |

<Note>
  Duplicate `requestUuid`s are not returned as decline reasons. A duplicate is silently skipped; if **every** order in the request is a duplicate, the request returns `409` instead (see below).
</Note>

**Example declined order response:**

```json theme={null}
{
  "status": "declined",
  "acceptedOrders": [],
  "declinedOrders": [
    {
      "requestUuid": "fb5f2dd9-c855-4ba9-8ef9-4c2278ca2f1d",
      "fixtureId": "id1000000861624412",
      "outcomeId": 161,
      "declineReason": "Order stake 15000.00 USD exceeds available limit 5000.00 USD",
      "bets": []
    }
  ]
}
```

## Common errors

### Authentication (401 / 403)

```bash theme={null}
# Missing header → 403 {"detail": "Missing API key header: x-api-key"}
curl https://v2.55-tech.com/accounts

# Invalid or inactive key → 401 {"error": "Invalid or inactive API key"}
curl -H "x-api-key: wrong-key" https://v2.55-tech.com/accounts
```

### Forbidden (403)

Returned when the API key header is missing, when the key is not allowed for the requested endpoint/sport/bookmaker, or when you attempt to access a resource that belongs to a different client.

```json theme={null}
{"detail": "Missing API key header: x-api-key"}
{"error": "Access denied to endpoint"}
{"detail": "Access denied: client not resolved"}
```

### Duplicate request (409)

Returned only when **every** order in the request is a duplicate — each `requestUuid` was already processed or is in progress within the last **30 minutes**. If only some orders are duplicates, those are skipped and the rest are processed normally.

```json theme={null}
{
  "detail": {
    "error": "All orders are duplicates",
    "duplicateUuids": ["eb45b192-317b-42d5-9f65-af497b9fa8c1"],
    "inProgressUuids": []
  }
}
```

### Validation error (422)

Request body contains invalid data. Check the `loc` field for the problematic path:

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "orders", 0, "fixtureId"],
      "msg": "Field required",
      "type": "missing"
    }
  ]
}
```

### Rate limiting (429)

Exceeded requests per **second** for your client. Default limit: 100/second (configurable per client).

```json theme={null}
{
  "detail": "Rate limit exceeded",
  "limit": "100",
  "retry_after": 1
}
```

The window resets every second — wait the `retry_after` interval before retrying.

## Resilience patterns

ABP implements several resilience mechanisms that may affect your integration:

### Circuit breakers

Per-bookmaker circuit breakers prevent cascading failures. If a bookmaker is experiencing issues, orders targeting that bookmaker may be declined until the circuit recovers.

Opens after consecutive failures, automatically tests recovery, and resumes normal operation once the bookmaker responds successfully.

### Emergency mode

In rare cases, the system may temporarily pause order processing during maintenance or upstream issues. The `emergency` WebSocket channel broadcasts status changes.

### Order expiry

Orders have a default `expiresAt` of 5 seconds from creation (capped at 24 hours maximum). If a bet hasn't been placed within this window, the order status changes to `EXPIRED`. Set a custom `expiresAt` for longer-lived orders.

## Next steps

<Columns cols={2}>
  <Card title="Order Placement" icon="bullseye-arrow" href="/abp-api/order-placement">
    Understand fills, partial stakes, and decline reasons.
  </Card>

  <Card title="WebSocket" icon="bolt" href="/abp-api/websocket">
    Track order and bet status in real time.
  </Card>
</Columns>
