---
title: "Create a media-library asset"
method: POST
path: "/v1/assets"
tags: ["assets"]
---

# Create a media-library asset

`POST /v1/assets`

## Request

- Base URL: `https://us1.platform.bird.com`
- URL: `https://us1.platform.bird.com/v1/assets`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `bird_session`

Uploads a file to the workspace's media library and returns its permanent public
URL. Send a `multipart/form-data` body with the bytes in the `file` part.

The file's contents determine its type, and the type determines its `kind`:

| Kind | Accepted formats | Maximum size |
| --- | --- | --- |
| `image` | PNG, JPEG, GIF, WebP | 5 MB |
| `video` | MP4, WebM, QuickTime | 25 MB |
| `audio` | MP3, M4A, Ogg, WAV | 25 MB |
| `document` | PDF | 25 MB |

Images are re-encoded to remove embedded metadata and apply recorded rotation.
Animated GIFs keep their animation, and WebP images become JPEG or PNG. Other
files are stored byte-for-byte. Documents are downloads; other media displays
inline. Asset bytes and URLs do not change. Upload new content as a new asset.
A duplicate file returns the existing asset with `200 OK`.
An organization can retain at most 100,000 assets per region, including removed library
entries whose URLs still serve. Reusing an existing asset does not use another slot.

Include each multipart field at most once. `file` is required. Optional `name`
is a display name of up to 255 characters and defaults to the filename when
omitted or empty after trimming;
`alt_text` allows up to 1,000 characters; `folder_id` places a new asset in an
existing folder. Omit `folder_id` for the library root. Each text part is
limited to 8 KiB before trimming surrounding whitespace. Duplicate uploads
retain the existing asset's metadata and folder.

See [Manage media-library files](/docs/guides/media-library) for CLI and MCP use.

## Headers

- `Idempotency-Key` string
- `X-Workspace-Id` string
- `X-Organization-Id` string

## Response `200`

An asset with identical contents already existed and was returned unchanged.

- Asset: A file in the workspace's media library, hosted at a permanent public URL. Embed or link `url` anywhere hosted media is needed, including in email that has already been sent: an asset's bytes and URL never change.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `id` string, required
  - `url` string, uri, required: The asset's permanent public URL. Safe to embed or link in sent messages; for a document the usable form is a link.
  - `thumbnail_url` string, uri, nullable, required: A small preview of the asset, for rendering a picker or a grid. Intended for your own interfaces rather than for embedding in messages. Null for every kind but `image`: generating a preview of a video, an audio file, or a document would mean rendering its contents, which the library does not do. Show an icon for the `kind` instead.
  - `name` string, required: The asset's display name. Defaults to the uploaded file's name.
  - `content_type` string, required: The stored file's media type, determined from its contents.
  - `kind` string, required: The category a media-library asset's type falls into. Use it to group or filter a mixed library. - `image`: covers PNG, JPEG, and GIF. - `video`: covers MP4, WebM, and QuickTime. - `audio`: covers MP3, M4A, Ogg, and WAV. - `document`: covers PDF.
  - `size_bytes` integer, required: The stored file's size in bytes. Images are re-encoded on upload, so for those this can differ from the size of the file you sent. Every other kind is stored byte-for-byte.
  - `width` integer, nullable, required: The stored image's width in pixels. Null for every kind but `image`.
  - `height` integer, nullable, required: The stored image's height in pixels. Null for every kind but `image`.
  - `alt_text` string, nullable, required: Default alternative text describing the asset, carried along whenever it is placed. Most mail clients block images by default, so for an image this is often the only thing a recipient reads.
  - `folder_id` string, required
  - `deleted_at` string, date-time, nullable, required: When the asset was removed from the library, or null if it is still listed. A removed asset keeps serving at its original URL.

## Other responses

- `201`: The uploaded asset.
- `400`: Bad request
- `401`: Authentication required
- `403`: Insufficient permissions
- `404`: Resource not found
- `413`: Request body or message size exceeds the allowed limit
- `422`: The request has invalid field values, violates a business rule, or carries a query parameter the endpoint does not declare. Field validation errors use `type: validation_error` and include the affected fields in `details`. Business-rule errors identify the failed rule in `type`.
- `429`: Rate limit exceeded
- `500`: Internal server error
- `501`: The operation is not supported
- `503`: The service is temporarily unavailable. If `Retry-After` is present, wait for that delay before retrying; otherwise, retry with exponential backoff. Reuse the same idempotency key and request when retrying a mutation.

---

[API](https://skmtc.dev/messagebird/apis/bird-api.md) · [All operations](https://skmtc.dev/messagebird/apis/bird-api/llms.txt) · [OpenAPI document](https://skmtc.dev/messagebird/apis/bird-api/revisions/6dfce1179799?raw)
