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

# Files, artifacts, and retention

> Upload inputs and retrieve verified output bytes.

Files are uploaded inputs. Artifacts are request outputs. Their IDs and endpoints are separate.

## Upload a file

Use multipart form field `file`, with an optional `lifetime` of `ephemeral` or `persistent`. The filename determines the input format; Content-Type is advisory. Uploads are currently limited to **18 MiB**.

```bash theme={null}
curl --fail-with-body 'https://revise.io/api/v1/files' \
  -H "Authorization: Bearer $REVISE_API_KEY" \
  -H 'Idempotency-Key: template-42-upload' \
  -F 'file=@template.docx' \
  -F 'lifetime=persistent'
```

Use persistent files for templates you intend to submit to multiple jobs. [`GET /v1/files/{id}`](/revise-api/reference/get-file) returns metadata. There is no REST endpoint for downloading an uploaded file's original bytes; retain your original if you need them later.

## Download an artifact

Read metadata from a completed receipt or [`GET /v1/artifacts/{id}`](/revise-api/reference/get-artifact). Metadata includes `filename`, `content_type`, `bytes`, `sha256`, `variant`, `input_eligible`, expiry/deletion fields, and optional encryption information.

Fetch bytes from [`GET /v1/artifacts/{id}/content`](/revise-api/reference/download-artifact) with bearer authentication. Construct the URL from your configured API base and the artifact ID. Do not forward your API key to arbitrary response URLs or follow redirects to other hosts.

Before consuming the result, compare its length and SHA-256 with metadata. For encrypted output these describe the **ciphertext**. The HTTP headers then report `application/jose` and a `.jwe` filename; artifact metadata still describes the original plaintext format.

## Retention

* Ephemeral uploads can be claimed by one job. Unclaimed uploads normally expire after 24 hours. Successful work deletes claimed ephemeral input data; failed/cancelled work follows the server's failure-retention policy.
* Persistent files remain until explicitly deleted. Active work can pin a file and prevent deletion.
* Completed request content normally expires after 24 hours. Download and store results your application needs to retain.
* Deleting prompt or conversion content removes retained content and output bytes but preserves billing and operational receipts. It does not cancel work. Repeated content deletion succeeds; active/pinned content can return `409`.
* Expired or deleted bytes cannot be restored by replaying an idempotency key. A retained metadata record does not prove the content remains downloadable.

<Warning>
  With `retention.delete_after_webhook_id`, a successful completion-webhook acknowledgement can trigger deletion. Download and durably store results before returning 2xx from that webhook.
</Warning>

## TypeScript

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

const revise = new ReviseClient({ apiKey: process.env.REVISE_API_KEY! });
const artifact = await revise.artifacts.download("art_REPLACE_ME");
const bytes = artifact.bytes; // length and SHA-256 already checked
```

For large outputs, `artifacts.content(id)` exposes a raw Response. Your code then owns stream cleanup and verification. `Source.stream()` buffers before returning a fresh stream; it is not a streaming passthrough.
