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

# Errors, idempotency, and retries

> Recover interrupted work without submitting a duplicate job.

Request failures return an HTTP error. After a job is admitted, processing failures appear on its receipt. Fetching a failed job returns HTTP `200`.

API errors use this envelope:

```json theme={null}
{"error":{"code":"insufficient_credit","message":"insufficient credit"}}
```

Handle errors by `error.code`. Log the message and optional `details` for diagnosis. Gateways can return non-JSON errors.

| Response | Action |
| - | - |
| `400` | Correct the request or unsupported options. |
| `401`, `403` | Check credentials, expiry/revocation, and account status. |
| `402` | Add account credit. Retrying does not help. |
| `413`, `415` | Reduce input size or correct Content-Type. |
| `422` | Narrow a usage report that exceeds its row limit. |
| `404`, `410` | Check the ID and whether content expired or was deleted. |
| `409` | Check the code. Idempotency conflicts, claimed inputs, and pinned content each need a different fix. |
| `429`, `502`, `503`, `504` | Retry with bounded backoff if the operation is safe to replay. Honor `Retry-After`. |

Common codes are `ephemeral_file_already_claimed` (upload again or use a persistent template), `request_content_in_use` (wait for dependent work), and `model_unavailable` (check the model and operation). For recovery details, see [files](/developer/docs/developer/docs/revise-api/files), [models](/developer/docs/developer/docs/revise-api/models), and [job lifecycle](/developer/docs/developer/docs/revise-api/jobs).

## Idempotency

Send `Idempotency-Key` on uploads, prompt/conversion creation, webhook creation, and manual webhook-delivery retry. Repeating an operation with the same key and body replays it. Changing the body returns a conflict. Upload and job-creation replays include `Idempotent-Replayed: true`; webhook registration and delivery retries do not expose that header.

Use nonempty printable ASCII keys without spaces. Ordinary creation keys allow up to 200 characters; webhook creation/retry keys allow 128. Use distinct keys for each operation. Prompt and conversion creation share one key namespace within the account, across API keys; uploads have a separate namespace. Upload identity includes filename, bytes, and lifetime. New encryption public keys change the request body and therefore need a new operation key. Replays return the current receipt, including any expiry or content deletion, and never rerun a completed job.

Don't retry cancel or resume actions without checking the job, and don't generate a new key after an ambiguous submission failure. If you know the job ID, retrieve that job. If the submission response was lost, replay the identical request with its original key. A failed download is not a reason to create another paid job.

## TypeScript recovery

```ts theme={null}
import { ReviseClient, Source, ReviseWorkflowError } from "@reviseio/api";

const revise = new ReviseClient({ apiKey: process.env.REVISE_API_KEY! });
try {
  const pdf = await revise.convert(
    Source.fromText("# Report", { filename: "report.md" }),
    "pdf",
    { idempotencyKey: "report-42", timeoutMs: 120_000 },
  );
  const bytes = await pdf.bytes({ signal: AbortSignal.timeout(60_000) });
} catch (error) {
  if (error instanceof ReviseWorkflowError) {
    console.error(error.recovery.jobId, error.recovery.stage);
    // Persist recovery securely to resume this operation.
  }
  throw error;
}
```

Helpers derive `:upload` and `:prompt`/`:convert` keys from a base of at most 192 characters. `onProgress` provides keys, IDs, and the latest receipt synchronously; it cannot await durable storage. Use low-level methods when persistence must complete between network steps.

The client retries HTTP `429/502/503/504` on GET, DELETE, and supported keyed POST calls, with two additional attempts by default. It honors `Retry-After`; if the advised wait exceeds the configured `maxRetryDelayMs` (60 seconds by default), it returns the error instead of retrying early. Set `maxRetries: 0` to disable retries. Transport exceptions and body-read failures are not automatically retried.

`ReviseJobError` extends `ReviseWorkflowError` and exposes the unsuccessful or paused receipt as `.result`. `ReviseWorkflowError` preserves recovery plus its cause. `ReviseApiError` exposes status, code, body, and headers; `ReviseArtifactError` describes integrity failures; `SourceError` describes source resolution failures. Lazy output reads happen after the workflow: retain the returned Source and its receipt to retry reading without resubmitting.


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