# Overview

Upload files to Nairi via the REST API and read back any files the agent returns. Two-step flow: upload to get an attachment_id, then reference it in messages.





Attachments are a two-step flow: upload bytes to get an ID, then reference that ID by including it in a `conversations/start` or `conversations/{job_id}/continue` request. The agent receives the files alongside the prompt. Any files the agent produces in reply are surfaced the same way — as IDs on the assistant message, which you fetch back via the GET endpoint.

## Endpoints [#endpoints]

| Method | Path                              | Purpose                                                  |
| ------ | --------------------------------- | -------------------------------------------------------- |
| `POST` | `/api/public/v1/attachments`      | Upload a file (multipart). Returns an `attachment_id`.   |
| `GET`  | `/api/public/v1/attachments/{id}` | Fetch an attachment's metadata + bytes (base64-encoded). |

## Limits [#limits]

* **Max file size:** 50 MB per attachment.
* **Max attachments per message:** 10 referenced IDs.
* **Org-scoped:** an attachment can only be referenced or fetched by the org that uploaded it.

## Sending attachments with a prompt [#sending-attachments-with-a-prompt]

1. `POST /api/public/v1/attachments` for each file → record the returned `attachment_id` values.
2. Include them as `attachment_ids: [...]` in your `conversations/start` or `conversations/{job_id}/continue` request body.

The IDs must be valid ULIDs (`att_...`). Invalid IDs or IDs belonging to a different org are rejected with `400` before the message is created.

## Reading attachments from an agent reply [#reading-attachments-from-an-agent-reply]

When you fetch a message via `GET /api/public/v1/messages/{message_id}` or `GET /api/public/v1/conversations/{job_id}/messages`, any attachments the agent emitted appear as an `attachment_ids` array on the message. Call `GET /api/public/v1/attachments/{id}` on each one to download the bytes.

<Callout type="info">
  The download response embeds the file as a base64-encoded `data` field on the JSON body, so you don't need a separate streaming endpoint. Decode it once and write to disk.
</Callout>
