# Errors

The problem+json error format, what each status code means, and how to handle a failed request in code. Every failure parses the same way, per RFC 7807.

When a request fails, PDF Blocks returns a standard HTTP status code and a
machine-readable body describing what went wrong. Errors follow
[RFC 7807](https://www.rfc-editor.org/rfc/rfc7807) problem details, so you parse
every failure the same way regardless of which action produced it.

## The problem+json model

Error responses have `Content-Type: application/problem+json` and this shape:

| Attribute | Type    | Description                                     |
| --------- | ------- | ----------------------------------------------- |
| `type`    | string  | A URL to documentation about the problem.       |
| `title`   | string  | A human-readable summary of the problem.        |
| `status`  | integer | The HTTP status code, mirrored in the body.     |
| `errors`  | object  | Field names mapped to arrays of error messages. |

The `type` URL always ends in the status code (for example
`https://www.pdfblocks.com/docs/api/v1/error/400`), so you can branch on it or
on `status`. The `errors` object is present when a failure is tied to specific
request fields (validation); for request-level failures such as a bad API key it
may be omitted.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/400",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "file": [
      "Could not parse the PDF document. The file may be invalid or corrupt."
    ]
  }
}
```

## Status codes

| Status | Meaning                        | What to do                          |
| ------ | ------------------------------ | ----------------------------------- |
| `400`  | Validation error               | Fix the named fields and resend.    |
| `401`  | Unauthorized                   | Send a valid `X-API-Key`.           |
| `404`  | Not found                      | Check the action route and host.    |
| `406`  | Unacceptable `Accept`          | Request a supported format.         |
| `402`  | Payment required *(reserved)*  | Resolve billing or quota.           |
| `403`  | Forbidden *(reserved)*         | Key isn't permitted for this call.  |
| `413`  | Payload too large              | Send a smaller file.                |
| `429`  | Too many requests *(reserved)* | Back off and retry.                 |
| `5xx`  | Server error (rare)            | Retry with backoff.                 |

### 400: Validation error

A parameter is invalid, or `file` is not a readable PDF. The `errors` object
names each offending field.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/400",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "line_1": ["The field line_1 must be a string with a maximum length of 32."]
  }
}
```

Read `errors` field by field, correct the input, and resend. A `400` will not
succeed on retry without changes.

### 401: Unauthorized

The `X-API-Key` header is missing, malformed, or not a valid key.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/401",
  "title": "The request is missing a valid API key.",
  "status": 401
}
```

Set the `X-API-Key` header to a valid key from your
[dashboard](https://dashboard.pdfblocks.com) and send the request over HTTPS. See
[Authentication](/docs/api/authentication).

### 404: Not found

The path does not resolve to an action, usually a typo in the action name or a
missing version segment.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/404",
  "title": "The requested resource was not found.",
  "status": 404
}
```

Verify the route (for example `/v1/add_text_watermark`) and that you are calling
a valid [base URL](/docs/api/regions-and-data-residency).

### 406: Unacceptable `Accept`

A multi-document action received an `Accept` header it can't satisfy.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/406",
  "title": "The requested Accept header cannot be satisfied.",
  "status": 406
}
```

Request one of the supported formats (`application/zip`, `application/json`, or
`multipart/mixed`) or omit `Accept` to get the default ZIP. See
[Response formats](/docs/api/response-formats).

### 413: Payload too large

Your plan caps how large a single input document may be: 5 MB on Free, 10 MB
on every other plan (see [Pricing](/pricing)). A request whose body exceeds
that limit is rejected before processing. Unlike a `429`, a `413` will not
succeed on retry: send a smaller file, or ask us to raise the limit for your
account if you regularly need more.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/413",
  "title": "This request exceeds your plan's maximum document size of 10 MB.",
  "status": 413
}
```

### Reserved status codes

<Note>
  **Forward-looking.** The `402`, `403`, and `429` responses are part of
  the API contract but are **not enforced yet**. Handle them now so your client
  is ready when they go live. Usage and rate-limit specifics live in
  [Rate limits and usage](/docs/api/rate-limits-and-usage).
</Note>

**`402`: Payment required.** A billing or quota condition on your plan.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/402",
  "title": "Payment is required to complete this request.",
  "status": 402
}
```

**`403`: Forbidden.** The key is valid but not permitted to use this resource.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/403",
  "title": "You do not have permission to access this resource.",
  "status": 403
}
```

**`429`: Too many requests.** You have exceeded your plan's rate allowance.

```json
{
  "type": "https://www.pdfblocks.com/docs/api/v1/error/429",
  "title": "Too many requests. Please retry later.",
  "status": 429
}
```

### 5xx: Server errors

A `5xx` status signals a problem on our side and is rare. It is transient: retry
the same request with [exponential backoff](/docs/api/rate-limits-and-usage).

## Handling errors in code

Parse the body once and branch on `status` (or the trailing status in `type`):

- **`400`**: read the `errors` object, map each message back to its field, and
  fix the input. Do not blind-retry; the same request will fail again.
- **`401`, `403`, `404`, `406`**: the request itself is wrong. Correct the
  header, route, or `Accept` and resend; retrying unchanged won't help.
- **`402`, `413`**: an account or size condition. Resolve billing, or send a
  smaller file; these won't succeed on retry as-is.
- **`429` and `5xx`**: transient. Retry with exponential backoff, respect a
  `Retry-After` header when present, and cap your attempts. See
  [Rate limits and usage](/docs/api/rate-limits-and-usage).

Always read the `errors` object when it's present; it names exactly what to fix.
