---
title: "Attachments"
description: "Base64 on the way out, bytes or a redirect on the way in."
canonical_url: "https://www.agent-identity.dev/docs/mail/attachments"
markdown_url: "https://www.agent-identity.dev/docs/mail/attachments.md"
last_updated: "2018-10-20"
x_farming_labs_generated_preamble: true
agent:
  tokenBudget: 700
  task: "Send a file with a message, and read a file off one that arrived."
  outcome: "Outbound attachments are accepted base64-encoded, and inbound ones are listed and downloadable for the receiving agent."
  appliesTo:
    package:
      - "@aid/api"
      - "@agentidentity/sdk"
  prerequisites:
    - "An agent with a provisioned mailbox."
    - "Object storage configured; the filesystem default keeps files on the API container's disk."
  files:
    - "apps/api/src/services/mail.ts"
    - "packages/storage/src/object-storage-factory.ts"
  sideEffects:
    - "Stored bytes persist with the message and count against whatever storage backend is configured."
  verification:
    - description: "List what arrived with a message."
      expect: "The attachments endpoint returns each file's id, filename, and content type."
  rollback:
    - "Deleting the message removes its attachments. There is no separate attachment delete."
  failureModes:
    - symptom: "Downloading an attachment returns 404."
      resolution: "The attachment belongs to another agent or organization, or the ids are mixed up. List attachments for the message first and use the id it returns."
---

# Attachments
URL: /docs/mail/attachments
LLM index: /llms.txt
Description: Base64 on the way out, bytes or a redirect on the way in.
Related: /docs/mail/sending, /docs/getting-started/quickstart

<!-- farming-labs:agent-contract:start -->
## Agent Contract

Task: Send a file with a message, and read a file off one that arrived.
Outcome: Outbound attachments are accepted base64-encoded, and inbound ones are listed and downloadable for the receiving agent.

### Applies To

- Package: `@aid/api`, `@agentidentity/sdk`

### Prerequisites

- An agent with a provisioned mailbox.
- Object storage configured; the filesystem default keeps files on the API container's disk.

### Files

- `apps/api/src/services/mail.ts`
- `packages/storage/src/object-storage-factory.ts`

### Side Effects

- Stored bytes persist with the message and count against whatever storage backend is configured.

### Verification

- List what arrived with a message.
  - Expected: The attachments endpoint returns each file's id, filename, and content type.

### Rollback

- Deleting the message removes its attachments. There is no separate attachment delete.

### Failure Modes

- Downloading an attachment returns 404. — Recovery: The attachment belongs to another agent or organization, or the ids are mixed up. List attachments for the message first and use the id it returns.
<!-- farming-labs:agent-contract:end -->

# Attachments

## Sending

Attachments go inline in the send body, base64-encoded:

```json
{
  "to": ["customer@example.com"],
  "subject": "Invoice",
  "text": "Attached.",
  "attachments": [
    {
      "filename": "invoice.pdf",
      "content_type": "application/pdf",
      "content_base64": "JVBERi0xLjQK…"
    }
  ]
}
```

`filename` and `content_type` are required. `content_id` is optional and makes the
attachment referenceable from the HTML body as `cid:<content_id>` — that is how you embed
an image rather than appending it.

Because the payload is inline and base64 inflates by about a third, this is not the path
for very large files. Send a link for those.

## Receiving

Inbound attachments are extracted at ingest and written to the configured object storage.

```bash title="terminal"
curl -sS "https://api.agent-identity.dev/v1/identities/$AID_AGENT/mail/messages/$MSG/attachments" \
  -H "authorization: Bearer $AID_KEY"
```

Then download one:

```bash title="terminal"
curl -sSL -o invoice.pdf \
  "https://api.agent-identity.dev/v1/identities/$AID_AGENT/mail/messages/$MSG/attachments/$ATT/download" \
  -H "authorization: Bearer $AID_KEY"
```

The download endpoint behaves differently depending on your storage backend: with
filesystem storage it streams the bytes with a `content-disposition` header; with S3-style
storage it issues a redirect to a presigned URL. Follow redirects — `-L` in curl, and the
default in most HTTP clients. The SDK's `downloadAttachment` handles both and always
returns bytes.

## Storage

Attachment bytes are stored by the service and returned through the download endpoint
(`client.mail.downloadAttachment`). You never handle a storage URL or credentials.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
