# Upload message images

Upload up to 10 image files and get a public URL for each, ready to attach to a message.

- Endpoint: `POST https://api.returning.ai/v1/messages/upload-image`
- Section: Community / Messaging
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `sendMessage` (Shown in the dashboard as "Send Messages")
- Retries: Not idempotent; each retry uploads new copies
- Guide: hand-written
- Verified: code, 2026-09-27
- Last updated: 26 Sep 2026
- Web page: https://docs.returning.ai/api-reference/messaging/upload-message-images

## When to use this

- Your system draws a chart as an image file and wants to post it in a channel.
- Your images aren't online yet, so Send message can't fetch them from a URL.

**Instead:** Use [Send message](https://docs.returning.ai/api-reference/messaging/send-message.md) instead with `images` when your pictures already have public URLs.

**Public files:** Every uploaded file gets a public URL that anyone with the link can open, and there is no call to delete it. Upload only images you are happy to publish.

## Authentication

- Header: `Authorization: Bearer <API_KEY>`
- Permission: `sendMessage`

Use a Community API key with `sendMessage`, the same permission as Send message, and keep it on your server. A personal user API key with its own send permission also works.

## Behaviour

This call only stores the files; it doesn't post anything. Post them with Send message, passing the returned URLs in `images`.

The file type isn't checked, so send only images, and set each file part's content type, such as `image/png`. Uploaded files can't be deleted through the API.

## Request

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with `sendMessage`. (`Bearer <API_KEY>`) |

### Body

Send the body as `multipart/form-data` with one `images` part per file, up to 10 files of up to 30 MB each.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `images` | `file` | Yes | The image files. Repeat the `images` field once per file. (Up to 10 files, 30 MB each) |

Send the body as `multipart/form-data`.

### Example request

```bash
curl --request POST \
  --url https://api.returning.ai/v1/messages/upload-image \
  --header 'Authorization: Bearer <API_KEY>' \
  --form 'images=@xauusd-chart.png'
```

## Response

A `200` returns a JSON array with one entry per file, in the order you sent them, and no `status` or `message`. Keep each `url` for Send message.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `id` | `string` | - | An ID for this upload. It isn't used by other endpoints. |
| `name` | `string` | - | The file name you sent, or `chart.png` when the file part has no name. |
| `url` | `string` | - | The file's public URL. Pass it in `images` to Send message. |
| `type` | `string` | - | The content type you sent for the file, or `image/png` when none was given. |
| `size` | `integer` | - | The file size in bytes. |

### Example response (200)

```json
[
  {
    "id": "1b4e28ba-2fa1-11d2-883f-0016d3cca427",
    "name": "xauusd-chart.png",
    "url": "https://cdn.example.com/uploads/xauusd-chart.png",
    "type": "image/png",
    "size": 48213
  }
]
```

## Errors

Errors have `message`, and sometimes `status` or `detail`. None has a machine-readable code, so branch on the HTTP status and read `message`.

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | - | `No image buffers provided`: the request had no files. Send them as `multipart/form-data` in the `images` field. `Failed to upload 1 of 2 image(s)`: some files couldn't be stored; `detail` lists them, and none of the URLs is returned, so upload again. |
| 401 | - | The key is missing (`Invalid token`), unknown (`Invalid API key`) or expired, or it lacks `sendMessage` (`Your API key does not have permission to access this action`). Add the permission in Settings > Integration > API Keys. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 500 | - | The upload failed, or the key could not be checked (`Authentication failed`). Retry the same request with backoff. |

**Retries:** This endpoint doesn't accept an `Idempotency-Key`. A retry uploads new copies with new URLs, and earlier copies stay online. After a timeout, retry once, and use only the URLs from the response you receive. Over the [rate limit](https://docs.returning.ai/how-it-works.md#rate-limits), requests return `429`; wait for the window to reset, then retry.

## Next step

- [Send message](https://docs.returning.ai/api-reference/messaging/send-message.md): `POST /v1/messages/send`. Post the image in a channel by passing the returned `url` values in `images`.
