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

# Errors

> REST status codes, WebSocket close codes, and how Struct surfaces failures.

Every Struct surface returns errors in a consistent shape. This page covers the wire format for REST and WebSocket. The TypeScript SDK exposes a typed hierarchy on top, documented in [SDK Errors](/sdk/errors).

## REST

Failed REST requests return the same envelope as successful ones, with `success: false` and a human-readable `message`. The HTTP status reflects the error class.

```json theme={null}
{
  "success": false,
  "data": null,
  "message": "Invalid API key"
}
```

### Status codes

| Status                      | Meaning                                        | Common causes                                                                           |
| --------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------- |
| `400 Bad Request`           | Invalid parameters.                            | Missing required query string, malformed `condition_id`, unsupported candle resolution. |
| `401 Unauthorized`          | Missing or invalid credentials.                | `X-API-Key` header absent, key disabled, or JWT signature invalid.                      |
| `403 Forbidden`             | Auth succeeded but the key is over its limits. | Org out of credits, key revoked, or quota exceeded.                                     |
| `404 Not Found`             | Resource does not exist.                       | Market, event, or trader not indexed (yet) or wrong identifier.                         |
| `429 Too Many Requests`     | Rate limit exceeded.                           | See [Rate Limits](/guides/rate-limits).                                                 |
| `500 Internal Server Error` | Unexpected server failure.                     | Transient. Retry with backoff.                                                          |
| `502`, `503`, `504`         | Upstream or timeout.                           | Transient. Retry with backoff.                                                          |

### Headers

On `429`, the response includes `Retry-After` (seconds) when applicable. Honour it before retrying.

### Retrying

Any `5xx`, `429`, network failure, or timeout is retryable. Use exponential backoff with jitter; never tight-loop. The TypeScript SDK does this automatically when [`retry`](/sdk/configuration) is configured.

## WebSocket

### In-band errors

Invalid messages on either the rooms (`/ws`) or alerts (`/ws/alerts`) endpoint return a JSON error frame instead of closing the connection:

```json theme={null}
{
  "error": "unknown event type"
}
```

```json theme={null}
{
  "type": "error",
  "message": "filter limit exceeded"
}
```

These cover protocol-level problems: unknown room IDs, malformed subscribe payloads, filter limits, and similar. The socket stays open; you can correct the message and retry.

### Close codes

When the server closes the connection, it uses a standard WebSocket close code:

| Code   | Reason                                                     | Action                                                                            |
| ------ | ---------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `1000` | Normal closure.                                            | Client disconnected cleanly. No action.                                           |
| `1001` | Server going away (restart, deploy).                       | Reconnect with backoff.                                                           |
| `1008` | Policy violation. Usually auth failure.                    | Fix credentials before reconnecting. Do not retry blindly.                        |
| `1009` | Message too large.                                         | Reduce filter size or split into multiple subscriptions.                          |
| `1011` | Server error.                                              | Reconnect with backoff.                                                           |
| `4001` | Authentication failed.                                     | Check `api-key` and `token` query parameters.                                     |
| `4002` | Connection limit reached.                                  | Increase your plan or close idle sockets. See [Rate Limits](/guides/rate-limits). |
| `4003` | Ping timeout (no client activity within keepalive window). | Send pings every 30s.                                                             |
| `4004` | Out of credits.                                            | Top up credits in the dashboard.                                                  |

### Reconnection

When the socket drops for any non-auth reason, reconnect with exponential backoff and resubscribe to every room you were previously in. Subscriptions are not persisted server-side; they live only for the lifetime of the connection.

The TypeScript SDK handles reconnect and resubscribe automatically. See [SDK WebSockets](/sdk/websockets#reconnection-and-replay).

```typescript theme={null}
let attempt = 0;

function connect() {
  const ws = new WebSocket("wss://api.struct.to/ws?api-key=YOUR_API_KEY");

  ws.onopen = () => {
    attempt = 0;
    resubscribe(ws);
  };

  ws.onclose = (event) => {
    if (event.code === 1008 || event.code === 4001) return;
    const delay = Math.min(30_000, 1_000 * 2 ** attempt);
    attempt += 1;
    setTimeout(connect, delay + Math.random() * 500);
  };
}
```

## Webhooks

Webhook deliveries are retried automatically when your endpoint returns a non-2xx response, with exponential backoff. Endpoints that fail repeatedly are paused; see [Webhooks](/webhooks/getting-started) for the full retry schedule.

## SDK errors

The TypeScript SDK lifts these wire-level failures into a typed hierarchy:

```
StructError
├── HttpError          (REST: non-2xx response)
├── NetworkError       (REST: fetch failed)
├── TimeoutError       (REST: request timed out)
└── WebSocketError
    └── WebSocketClosedError
```

See [SDK Errors](/sdk/errors) for the full hierarchy, retry behaviour, and example handlers.
