# Errors

Slingshot APIs use a standardized error envelope: consistent HTTP status codes, machine-readable `error.code` values, and structured JSON so integrations can handle failures predictably.

## Error responses

HTTP status is carried on the response status line. The JSON body uses a single root property, `error`, whose value describes what went wrong. Published OpenAPI specs model the same shape (for example `ErrorResponse` and `ErrorBody`).

### Error categories

#### 4xx Client errors

Invalid authentication, missing permissions, validation issues, throttling, or a missing resource—these are problems the client can usually correct or retry with a different request.

#### 5xx Server errors

Unexpected failures or upstream issues. Often transient; retry with backoff and use `request_id` when contacting support.

### Error response format

All error responses follow this structure:

>\_ ERROR ENVELOPECopy

```
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error description",
    "request_id": "req_a1b2c3d4e5f6",
    "timestamp": "2026-03-02T14:30:00Z",
    "details": {
      // optional; shape varies by error type (omitted when not applicable)
    }
  }
}
```

Fields inside `error`:

| Field      | Type   | Description                                                          |
|------------|--------|----------------------------------------------------------------------|
| code       | string | Machine-readable code (uppercase with underscores)                  |
| message    | string | Human-readable description                                           |
| request_id | string | Identifier for support and log correlation                          |
| timestamp  | string | ISO 8601 time when the error was produced                          |
| details    | object | Optional context; e.g. 429 uses retry and ratelimit fields; 402 uses SPU fields |

### Rate limiting (public API)

Limits apply to normal customer traffic **after** authentication and authorization, so counting uses a known caller identity. This layer is separate from any upstream or internal throttling—whichever limit is stricter in practice wins.

On `429 Too Many Requests`, rate metadata uses [RFC 9297](https://www.rfc-editor.org/rfc/rfc9297.html) field names: `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` (Unix seconds), and `Retry-After` (seconds). Do not rely on legacy `X-RateLimit-*` headers for this API. Successful `2xx` responses do **not** include those `RateLimit-*` headers from this layer—handle throttling via `429`, the JSON body (`RATE_LIMIT_EXCEEDED`), and these headers when you are blocked.

### Example default windows (configurable per deployment)

| Metric                    | Limit         |
|---------------------------|---------------|
| Requests per second       | 100           |
| Requests per minute       | 1,000         |
| Requests per day          | 10,000        |

### Error handling best practices

- Check the HTTP status code before assuming a success-shaped body.
- For `429`, honor `Retry-After` and `error.details.retry_after_seconds` when present.
- Implement exponential backoff for `429` and `5xx` responses.
- Log `error.request_id` when contacting support.
- Use `error.code` for programmatic branching (e.g. `UNAUTHORIZED`, `INSUFFICIENT_SPU`).

## Error reference

| Code | Description                                               |
|------|-----------------------------------------------------------|
| 401  | **Unauthorized**: Authentication is required or your credentials are invalid. |
| 402  | (Details not provided)                                    |
| 403  | (Details not provided)                                    |
| 404  | (Details not provided)                                    |
| 429  | (Details not provided)                                    |
| 500  | (Details not provided)                                    |

### Recommended action for 401

Verify your API key in the Authorization header as Bearer YOUR_API_KEY and try again.
