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

# Upload media

> Upload a file and get a file_uuid to send it in an action.

To send images, video, audio, or documents, you first upload the file and get a
`file_uuid`, which you then pass to a send action.

<Steps>
  <Step title="Request an upload URL">
    ```http theme={null}
    POST /files/request-upload
    ```

    With `{ filename, mime_type, size_bytes }`. It returns `201` with
    `file_uuid`, `upload_url`, `upload_token`, `storage_path`, and `expires_at`.
  </Step>

  <Step title="Upload the binary">
    ```http theme={null}
    PUT {upload_url}
    ```

    Upload the file to the `upload_url` you received, before it expires
    (`expires_at`).
  </Step>

  <Step title="Confirm">
    ```http theme={null}
    POST /files/confirm
    ```

    With `{ file_uuid }`. It returns `200` with `file_uuid`, `mime_type`,
    `size_bytes`, `download_url`, and `expires_at`. From here the `file_uuid` is
    sendable.
  </Step>
</Steps>

Once confirmed, pass the `file_uuid` to a send action — as direct media in
`send_message`, or as a template header:

```jsonc theme={null}
{
  "conversation": { "phone": "+5215512345678", "channel": "ch_7A9K2M4Q" },
  "actions": [
    {
      "type": "send_message",
      "template": {
        "name": "promo_verano",
        "language": "es_MX",
        "header": {
          "type": "image",
          "file_uuid": "7b8a1c2d-3e4f-5678-90ab-cdef12345678"
        },
        "body_variables": [{ "index": 1, "value": "Ana" }]
      }
    }
  ]
}
```

The `header.type` ∈ `image` | `video` | `document` carries `file_uuid`
(`document` accepts an optional `filename`). In `send_message` media mode, the
`file_uuid` goes at the action level with `body` as an optional caption (audio
doesn't accept a caption).

<Tip>
  If the preflight rejects the group, the response is a synchronous `4xx` and no
  action runs. See [Errors](/en/errors).
</Tip>

## Executable example

The full flow in three calls. The `file_uuid` confirmed in step 3 is the one you
then pass to a send action.

**1 · Request an upload URL**

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://app.1to1.ai/api/v1/public/{slug}/files/request-upload" \
    -H "Authorization: Bearer sk_1to1_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "filename": "receipt.pdf",
      "mime_type": "application/pdf",
      "size_bytes": 48213
    }'
  ```

  ```json 201 Response theme={null}
  {
    "file_uuid": "7b8a1c2d-3e4f-5678-90ab-cdef12345678",
    "upload_url": "https://storage.1to1.ai/uploads/7b8a1c2d?token=...",
    "upload_token": "ut_9f8e7d6c5b4a3210",
    "storage_path": "business/uploads/7b8a1c2d.pdf",
    "expires_at": "2026-07-22T15:30:00Z"
  }
  ```
</CodeGroup>

**2 · Upload the binary** to the `upload_url` before it expires

```bash theme={null}
curl -X PUT "{upload_url}" \
  -H "Content-Type: application/pdf" \
  --data-binary @receipt.pdf
```

**3 · Confirm**

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://app.1to1.ai/api/v1/public/{slug}/files/confirm" \
    -H "Authorization: Bearer sk_1to1_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "file_uuid": "7b8a1c2d-3e4f-5678-90ab-cdef12345678"
    }'
  ```

  ```json 200 Response theme={null}
  {
    "file_uuid": "7b8a1c2d-3e4f-5678-90ab-cdef12345678",
    "mime_type": "application/pdf",
    "size_bytes": 48213,
    "download_url": "https://storage.1to1.ai/download/7b8a1c2d?token=...",
    "expires_at": "2026-07-22T16:30:00Z"
  }
  ```
</CodeGroup>
