Skip to content

Commit 5886af4

Browse files
Mlaz-codeclaude
andcommitted
docs(errors): align error code reference with canonical Go list
Replace per-page error tables with the authoritative 19 HTTP + 6 WebSocket-frame codes now defined in sharp-api-go/pkg/errcodes. Remove fabricated codes that never actually shipped: forbidden, unknown_type, stream_limit_exceeded. Replace bad_request and invalid_request (deprecated, collapsed server-side) with validation_error. Document unauthorized, invalid_api_key, and invalid_token as three distinct auth-failure codes covering admin bearer, user API key, and Clerk session paths respectively. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a667aa2 commit 5886af4

10 files changed

Lines changed: 84 additions & 30 deletions

File tree

content/en/api-reference/account-keys.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ print(f"Deleted key: {result['key_id']}")
275275
```json
276276
{
277277
"error": {
278-
"code": "invalid_request",
278+
"code": "validation_error",
279279
"message": "Cannot delete the API key used to authenticate this request",
280280
"docs": "https://docs.sharpapi.io/en/api-reference/account-keys"
281281
}

content/en/api-reference/conventions.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ Every non-2xx response returns a single `error` object.
100100

101101
### Common error codes
102102

103-
`missing_api_key`, `invalid_api_key`, `validation_error`, `invalid_request`, `tier_restricted`, `rate_limited`, `too_many_streams`, `not_found`, `upstream_error`, `internal_error`.
103+
`missing_api_key`, `invalid_api_key`, `validation_error`, `tier_restricted`, `rate_limited`, `too_many_streams`, `not_found`, `upstream_error`, `internal_error`.
104+
105+
See the full list (19 HTTP codes + 6 WebSocket frame codes, with HTTP statuses) in [API Overview → Error Codes](/en/api-reference/overview#error-codes). `bad_request` and `invalid_request` are deprecated — both were collapsed into `validation_error`.
104106

105107
## Timestamps
106108

content/en/api-reference/deeplinks.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ To get the final sportsbook URL, either follow the redirect (`GET https://api.sh
145145
```json
146146
{
147147
"error": {
148-
"code": "bad_request",
148+
"code": "validation_error",
149149
"message": "ids array required"
150150
}
151151
}
@@ -155,7 +155,7 @@ To get the final sportsbook URL, either follow the redirect (`GET https://api.sh
155155
```json
156156
{
157157
"error": {
158-
"code": "bad_request",
158+
"code": "validation_error",
159159
"message": "Maximum 500 IDs per batch"
160160
}
161161
}

content/en/api-reference/events.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ data = response.json()
301301
```json
302302
{
303303
"error": {
304-
"code": "invalid_request",
304+
"code": "validation_error",
305305
"message": "Invalid date format. Use YYYY-MM-DD.",
306306
"docs": "https://docs.sharpapi.io/en/api-reference/events"
307307
}

content/en/api-reference/odds-batch.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ The maximum number of events per batch request depends on your tier:
3939
| **Enterprise** | 100 |
4040

4141
<Callout type="warning">
42-
Exceeding the batch limit for your tier will return a `400 invalid_request` error. Split large requests into multiple batches if needed.
42+
Exceeding the batch limit for your tier will return a `400 validation_error` error. Split large requests into multiple batches if needed.
4343
</Callout>
4444

4545
## Example Requests
@@ -207,7 +207,7 @@ X-Request-Id: req_batch_abc123
207207
```json
208208
{
209209
"error": {
210-
"code": "invalid_request",
210+
"code": "validation_error",
211211
"message": "Batch limit exceeded. Your tier (hobby) allows 10 events per batch, but 25 were requested.",
212212
"docs": "https://docs.sharpapi.io/en/api-reference/odds-batch"
213213
}
@@ -218,7 +218,7 @@ X-Request-Id: req_batch_abc123
218218
```json
219219
{
220220
"error": {
221-
"code": "invalid_request",
221+
"code": "validation_error",
222222
"message": "The 'event_ids' field is required and must be a non-empty array of event IDs.",
223223
"docs": "https://docs.sharpapi.io/en/api-reference/odds-batch"
224224
}

content/en/api-reference/odds-delta.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Use the `server_time` from each response as the `since` value for your next requ
4040
| `offset` | integer | 0 | Pagination offset |
4141

4242
<Callout type="warning">
43-
The `since` parameter is **required**. Omitting it returns a `400 invalid_request` error.
43+
The `since` parameter is **required**. Omitting it returns a `400 validation_error` error.
4444
</Callout>
4545

4646
## Example Requests
@@ -164,7 +164,7 @@ X-Request-Id: req_delta_abc123
164164
```json
165165
{
166166
"error": {
167-
"code": "invalid_request",
167+
"code": "validation_error",
168168
"message": "The 'since' parameter is required for the delta endpoint",
169169
"docs": "https://docs.sharpapi.io/en/api-reference/odds-delta"
170170
}

content/en/api-reference/overview.mdx

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,47 @@ All odds are returned as flat fields on each odds object:
313313

314314
## Error Codes
315315

316+
The canonical list of error codes emitted by the API. The string in `error.code` is the stable contract — check it rather than the prose `message`.
317+
318+
### HTTP error codes
319+
320+
Emitted in REST responses.
321+
316322
| Code | HTTP Status | Description |
317323
|------|-------------|-------------|
318-
| `unauthorized` | 401 | Missing or invalid API key |
319-
| `forbidden` | 403 | Feature requires higher tier |
320-
| `rate_limited` | 429 | Too many requests |
321-
| `tier_restricted` | 403 | Endpoint not available on your tier |
322-
| `invalid_request` | 400 | Malformed request parameters |
324+
| `missing_api_key` | 401 | No API key supplied via `X-API-Key`, `?api_key=`, or `Authorization: Bearer` |
325+
| `invalid_api_key` | 401 | API key was supplied but is not recognized |
326+
| `expired_api_key` | 401 | API key has expired — generate a new one in the dashboard |
327+
| `disabled_api_key` | 401 | API key is disabled, usually because the subscription lapsed |
328+
| `unauthorized` | 401 | Bearer-token auth failed on admin or `/api/v1/monitoring/*` endpoints (distinct from `invalid_api_key`) |
329+
| `invalid_token` | 401 | Clerk session token failed verification (dashboard-only endpoints) |
330+
| `tier_restricted` | 403 | Endpoint or feature is not available on your tier — response includes `tier` and `required_tier` |
323331
| `not_found` | 404 | Resource not found |
332+
| `method_not_allowed` | 405 | HTTP method is not supported on this route |
333+
| `gone` | 410 | Event has ended or expired — use `/api/v1/events` for current events |
324334
| `unknown_endpoint` | 410 | Wrong API path — response includes `correct_endpoint` with the right route (e.g. `/api/v1/arbitrage``/api/v1/opportunities/arbitrage`) |
325-
| `upstream_error` | 502 | Temporary data fetch issue |
326-
| `internal_error` | 500 | Server error |
335+
| `validation_error` | 400 | Request body or query parameters failed validation |
336+
| `rate_limited` | 429 | Per-minute request rate limit exceeded — response includes `retry_after` |
337+
| `concurrent_request_cap` | 429 | Too many in-flight requests for your tier — reduce parallelism or upgrade |
338+
| `too_many_streams` | 429 | Maximum concurrent SSE or WebSocket streams exceeded for this API key |
339+
| `backpressure` || Emitted as an SSE `event: error` (not an HTTP status) when the client cannot keep up; server then closes the stream |
340+
| `upstream_error` | 502 | Temporary issue reaching an upstream sportsbook or auth provider |
341+
| `service_unavailable` | 503 | A required service (e.g. key management) is not configured or is offline |
342+
| `internal_error` | 500 | Unexpected server error — retry with backoff and contact support with `X-Request-Id` if it persists |
343+
344+
<Callout type="info">
345+
`bad_request` and `invalid_request` are **deprecated** — both were collapsed into `validation_error`. Clients that match on the old strings should add `validation_error` to their error map.
346+
</Callout>
347+
348+
### WebSocket frame error codes
349+
350+
Emitted only inside `{"type": "error", "code": "..."}` frames on an open WebSocket connection. They describe client-protocol mistakes and do not correspond to an HTTP status.
351+
352+
| Code | Meaning |
353+
|------|---------|
354+
| `invalid_message` | Frame could not be parsed as JSON or did not match the expected shape |
355+
| `unknown_message_type` | `type` field is not one of the documented values (`auth`, `subscribe`, `filter`, `refresh_token`, `ping`) |
356+
| `missing_token` | `auth` or `refresh_token` frame did not include a `token` field |
357+
| `missing_channels` | `subscribe` frame did not include a non-empty `channels` array |
358+
| `not_authenticated` | Frame requires an authenticated session (sent `subscribe`, `filter`, or `refresh_token` before `auth`) |
359+
| `already_authenticated` | Client sent a second `auth` frame after the first one succeeded |

content/en/api-reference/stream.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ Each open SSE connection counts as one stream against your limit.
519519
| Enterprise | Custom |
520520

521521
<Callout type="warning">
522-
Exceeding your stream limit returns a `429` error with code `stream_limit_exceeded`. Close unused streams before opening new ones.
522+
Exceeding your stream limit returns a `429` error with code `too_many_streams`. Close unused streams before opening new ones.
523523
</Callout>
524524

525525
### Managing Streams
@@ -546,10 +546,10 @@ These close the connection. Handle them in `onerror`:
546546

547547
| Error Code | HTTP Status | Description | Resolution |
548548
|------------|-------------|-------------|------------|
549-
| `stream_limit_exceeded` | 429 | Too many concurrent streams | Close unused streams |
549+
| `too_many_streams` | 429 | Too many concurrent streams | Close unused streams |
550550
| `tier_restricted` | 403 | Streaming not available on your tier | Add WebSocket add-on |
551-
| `unauthorized` | 401 | Invalid API key | Check your API key |
552-
| `invalid_request` | 400 | Invalid filter parameters | Check query params |
551+
| `invalid_api_key` | 401 | API key missing or invalid | Check your API key |
552+
| `validation_error` | 400 | Invalid filter parameters | Check query params |
553553

554554
## Best Practices
555555

content/en/api-reference/websocket.mdx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,24 @@ Error notification. The connection may remain open (for non-fatal errors) or clo
567567
{
568568
"type": "error",
569569
"seq": 152,
570-
"code": "unknown_type",
570+
"code": "unknown_message_type",
571571
"message": "Unknown message type: foobar"
572572
}
573573
```
574574

575+
The WebSocket layer emits a small, fixed set of frame-level error codes for client-protocol mistakes. They are distinct from the HTTP error codes returned by REST endpoints.
576+
577+
| Code | Meaning |
578+
|------|---------|
579+
| `invalid_message` | Frame could not be parsed as JSON or did not match the expected shape |
580+
| `unknown_message_type` | `type` field is not one of `auth`, `subscribe`, `filter`, `refresh_token`, `ping` |
581+
| `missing_token` | `auth` or `refresh_token` frame did not include a `token` field |
582+
| `missing_channels` | `subscribe` frame did not include a non-empty `channels` array |
583+
| `not_authenticated` | Sent `subscribe`, `filter`, or `refresh_token` before `auth` succeeded |
584+
| `already_authenticated` | Client sent a second `auth` frame after the first one succeeded |
585+
586+
WebSocket frames may also carry the HTTP-style `invalid_api_key`, `tier_restricted`, and `too_many_streams` codes — these cause the server to close the connection after the frame is sent. See [API Overview → Error Codes](/en/api-reference/overview#error-codes) for the full list.
587+
575588
## Close Codes
576589

577590
| Code | Meaning | Resolution |

content/en/authentication.mdx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,22 @@ Authenticated requests receive higher rate limits based on your subscription tie
134134

135135
## Error Codes
136136

137+
Auth-related codes you'll see most often. For the full list of 19 HTTP codes plus the 6 WebSocket frame codes, see [API Overview → Error Codes](/en/api-reference/overview#error-codes).
138+
137139
| Code | HTTP Status | Description |
138140
|------|-------------|-------------|
139-
| `unauthorized` | 401 | API key missing or invalid |
140-
| `forbidden` | 403 | Feature requires higher tier |
141-
| `rate_limited` | 429 | Too many requests |
142-
| `tier_restricted` | 403 | Endpoint not available on your tier |
143-
| `invalid_request` | 400 | Malformed request parameters |
144-
| `not_found` | 404 | Resource not found |
145-
| `upstream_error` | 502 | Temporary issue fetching data |
146-
| `internal_error` | 500 | Server error |
141+
| `missing_api_key` | 401 | No API key was supplied |
142+
| `invalid_api_key` | 401 | API key was supplied but is not recognized |
143+
| `expired_api_key` | 401 | API key has expired |
144+
| `disabled_api_key` | 401 | API key is disabled, usually because the subscription lapsed |
145+
| `unauthorized` | 401 | Bearer-token auth failed on admin or monitoring endpoints (distinct from `invalid_api_key`) |
146+
| `invalid_token` | 401 | Clerk dashboard session token failed verification |
147+
| `tier_restricted` | 403 | Endpoint or feature not available on your tier |
148+
| `rate_limited` | 429 | Too many requests — see `retry_after` |
149+
| `too_many_streams` | 429 | Maximum concurrent SSE / WebSocket connections reached |
150+
| `validation_error` | 400 | Malformed request parameters (replaces the deprecated `bad_request` / `invalid_request`) |
151+
| `upstream_error` | 502 | Temporary issue reaching upstream |
152+
| `internal_error` | 500 | Unexpected server error |
147153

148154
### Error Response Format
149155

0 commit comments

Comments
 (0)