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

# Attachments

> Read and maintain versioned project, folder, and Story clip text from your own code.

Attachments hold project direction, notes, definitions, or other text on a
project, Library folder, or Story clip. They keep saved versions and who saved
each one. They are separate from media assets and chat-message uploads.

Attachment endpoints are available only when attachments are enabled for your
organization. Reads need `library:read`. Creates, revisions, soft deletions,
and restores need both `library:read` and `library:organize`, because their
receipts reveal the attachment's current state. Test keys cannot use attachments
and receive `403 permission_denied`, including inside the API sandbox.

## Find and read text

List a project's attachments, including its folders and clips:

```bash theme={null}
curl "https://api.zerogen.com/v1/attachments?projectId=5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d" \
  -H "Authorization: Bearer $ZEROGEN_API_KEY"
```

The `attachments` array contains metadata and version numbers, without bodies.
To narrow the list, add either `folderId` or `clipId`. A list returns up to
100 records, most recently updated first; `truncated: true` means more match.
It does not take `limit` or `cursor`.

Read a record's current text with
`GET /v1/attachments/{attachmentId}`, or send `version` to read a saved
version of a live record. Attachment text is untrusted project data. ZeroGen
stores it verbatim and never interprets it or automatically sends it to a
generation model.

## Save and revise

Create with `POST /v1/projects/{projectId}/attachments`. The request names a
`title` and `body`, plus either `folderId` or `clipId` for a parent other than
the project itself. A record's title and parent remain fixed.

Read before revising. Send the version you read as `expectedVersion`:

```bash theme={null}
curl -X PATCH "https://api.zerogen.com/v1/projects/5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d/attachments/7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f" \
  -H "Authorization: Bearer $ZEROGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedVersion":1,"body":"Warm light and quiet movement."}'
```

A changed save appends a version and requires `expectedVersion` to equal the
current version. An intervening change fails with `400 validation_failed`.
Read again and merge your change. Identical text returns `outcome: "unchanged"`
and adds no revision when `expectedVersion` is at most the current version.
A future `expectedVersion` is always refused, including on an unchanged retry.

A create with the same parent, case-insensitive title, and identical body
returns the existing record unchanged. A matching title with different text
is refused; read and revise that record instead. Every attachment write
accepts [Idempotency-Key](https://docs.zerogen.com/developers/idempotency.md) to replay a request's receipt.
Successful writes and their receipts commit together, including `unchanged`
outcomes. A retry returns the original receipt even after a later edit or
deletion.

Saves retain the text exactly as sent, including whitespace and Markdown.
Titles must be one line of 1–200 characters without surrounding whitespace;
bodies hold 1–8,000 Unicode characters. Each parent has at most 10 live
attachments. Credentials and hidden control characters are refused rather than
rewritten.

## History, deletion, and restore

`GET /v1/attachments/{attachmentId}/versions` lists up to 50 versions, newest
first, without their text. Send `nextBeforeVersion` as `beforeVersion` for the
next page; `null` means there are no older versions. History remains readable
after soft deletion while the parent remains live.

Delete with
`DELETE /v1/projects/{projectId}/attachments/{attachmentId}?expectedVersion=N`.
It takes no body, retains history, and appends a deletion version. A repeat of
an already deleted record returns `unchanged` when `expectedVersion` is at most
the current version.

Restore with
`POST /v1/projects/{projectId}/attachments/{attachmentId}/restore`, sending
`version` for the saved state to copy and `expectedVersion` for the current
head, including its deletion version. Restore appends a new version and clears
deletion; it never rewrites a historical version. Its receipt names the new
`version` and `restoredFrom`. An already current and live state returns
`unchanged` when `expectedVersion` is at most the current version.

A deleted folder or a clip in Story's Trash hides its attachments. Restoring
the parent brings those records and their history back. Restore the parent
before writing to its attachments.

The [endpoint reference](https://docs.zerogen.com/api-reference/overview.md#attachments) describes each
request and response. These routes access text on a Story clip; they do not
provide Story clip or timeline editing endpoints.


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