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

# Errors

> The error format, every error code and the order in which the API checks a request.

## Error format

Every error has the same shape:

```json theme={null}
{
  "error": {
    "code": "invalid_request",
    "message": "Invalid value for query parameter \"limit\".",
    "param": "limit"
  }
}
```

<ResponseField name="error.code" type="string">
  A stable, machine-readable code. Rely on this.
</ResponseField>

<ResponseField name="error.message" type="string">
  A human-readable message in English. It can change, so do not parse it.
</ResponseField>

<ResponseField name="error.param" type="string">
  The query parameter that was rejected. Only present on some `invalid_request` errors.
</ResponseField>

## Error codes

| HTTP status | `code` | When it occurs |
| - | - | - |
| 400 | `invalid_request` | A query parameter has the wrong form (`param` names it), or the query string is longer than 1024 characters including the leading `?` (no `param`). |
| 401 | `unauthorized` | The `Authorization` header is missing, uses another scheme or is longer than 256 characters, or the key has the wrong form, is unknown, revoked or expired. The body is the same in every case. The response carries `WWW-Authenticate: Bearer`. |
| 404 | `not_found` | The ID does not exist in your workspace, the ID belongs to another workspace, the ID has the wrong form, or the path does not exist. The body is the same in every case. |
| 405 | `method_not_allowed` | The method is `POST`, `PUT`, `PATCH` or `DELETE` on one of the four endpoints. The API is read-only. The response carries `Allow: GET, HEAD, OPTIONS`. |
| 429 | `rate_limited` | A rate limit was reached. The response carries `Retry-After`. See [Rate limits](/api/rate-limits). |
| 500 | `internal_error` | An error on the HocDoc side. |

Messages of the fixed errors:

| `code` | `message` |
| - | - |
| `unauthorized` | `Missing or invalid API key.` |
| `not_found` | `Resource not found.` |
| `method_not_allowed` | `Method not allowed. This API is read-only.` |
| `rate_limited` | `Too many requests.` |
| `internal_error` | `Internal server error.` |

The API never answers `403`. An ID of another workspace looks the same as an unknown ID.

## Order of checks

The API checks a `GET` request to one of the four endpoints in this order:

1. The limit per IP address. If it is reached: `429`.
2. The length of the query string. If it is longer than 1024 characters: `400`.
3. The `Authorization` header. If it is missing or the key has the wrong form: `401`. The API does not look up the key yet.
4. The limit per key. If it is reached: `429`.
5. The query parameters of the endpoint. If one is invalid: `400`.
6. The key itself. If it is unknown, revoked or expired: `401`.
7. The resource. If the ID is unknown: `404`.

This has these effects:

* A `400` for an invalid query parameter says nothing about whether your key is valid.
* A `401` comes before a `404`. A request with an invalid key never learns whether an ID exists.
* An ID with the wrong form is treated like an unknown ID. With a valid key it returns `404`, with an invalid key it returns `401`.
* A path that does not exist returns `404` without any of these checks. It needs no key.
* A `405` and the answer to `OPTIONS` are also sent without any of these checks.

## Methods

These rules apply to the four endpoints:

| Method | Behavior |
| - | - |
| `GET` | Reads data. |
| `HEAD` | Is handled like `GET`, with the same checks, status and headers. The response has no body. A `HEAD` request counts against the [rate limits](/api/rate-limits). |
| `OPTIONS` | Returns `204` without a body and with `Allow: GET, HEAD, OPTIONS`. It needs no key. |
| `POST`, `PUT`, `PATCH`, `DELETE` | Return `405` with `Allow: GET, HEAD, OPTIONS`. They need no key. |

The API sets no CORS headers, also not on the answer to `OPTIONS`. A browser blocks calls from another origin, so call the API from a server.

A path that does not exist returns `404` with `not_found` for every one of these methods.

## Server errors

A `500` with `internal_error` means the request failed on the HocDoc side. The response contains no details. Retry the request after a short wait.

A `500` carries the `RateLimit-*` headers of the key.

## Handling errors in code

```bash theme={null}
curl -s -o /dev/null -w "%{http_code}\n" \
  "https://app.hocdoc.com/api/v1/offers?limit=0" \
  -H "Authorization: Bearer $HOCDOC_API_KEY"
```

With a key of the right form this prints `400`. Read `error.code` from the body to decide what to do:

| `code` | Suggested handling |
| - | - |
| `invalid_request` | Fix the request. Check `error.param`. |
| `unauthorized` | Check the key. It can be missing, malformed, expired or revoked. |
| `not_found` | Check the ID and the path. |
| `method_not_allowed` | Use `GET`. |
| `rate_limited` | Wait for the number of seconds in `Retry-After`, then retry. |
| `internal_error` | Retry after a short wait. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.