Sign inGet Started

Manage media-library files

Upload media once and reuse its public URL in your content. The API, bird assets commands, and MCP tools manage the same workspace library as the dashboard.

Before you start

Use a workspace API key with assets:write for uploads and changes, and assets:read for reads. To see email-template references, also grant email_management:read. See API authentication and CLI setup.

Uploaded URLs are accessible without authentication. Only upload files intended for public access. Images are re-encoded to remove embedded metadata. PDF, audio, and video retain their bytes; file-type recognition is not a malware scan.

Upload a file

Code example
bird assets upload --file ./banner.png --name "Summer banner" --alt-text "Summer collection"

The response includes the asset's id and url. --file - reads stdin. Images accept PNG, JPEG, GIF, and WebP up to 5 MiB; video, audio, and PDF accept the formats and 25 MB limit listed in the upload reference.

For HTTP, send multipart/form-data with one required file part. Optional parts are name, alt_text, and folder_id. Include each part at most once and retain the same Idempotency-Key when retrying an upload.

Identical file bytes return the existing asset unchanged, including its name and folder. To change metadata, update that asset. To replace file contents, upload a new file and use its new URL.

Find and organize assets

Code example
bird assets list --kind image
bird assets folders create --name "Campaign images"

Use the returned IDs to retrieve an asset or move it:

Code example
bird assets get ast_01krdgeqcxet5s7t44vh8rt9mg
bird assets update ast_01krdgeqcxet5s7t44vh8rt9mg --folder-id asf_01krdgeqcxet5s7t44vh8rt9mg

Moving files or folders preserves asset URLs. Folder lists are flat and paginated; read every page before assembling a complete tree from parent_id. A folder filter matches only files directly inside that folder.

Each workspace supports 1,000 active folders and 10,000 retained folders, including deleted folders. Deletion frees an active slot but does not release retained capacity. At the retained limit, reuse existing folders or the library root; this limit is fixed, but you can contact support to discuss your use case.

To move an asset back to the root, send {"folder_id":null} to the update endpoint, or provide that JSON with the CLI's --body-file. {"alt_text":null} clears alternative text. Omitted fields remain unchanged.

Inspect usage and remove entries

Code example
bird assets references list ast_01krdgeqcxet5s7t44vh8rt9mg

References include saved content you have permission to read. They exclude unsaved edits and older published versions. A response with truncated: true is incomplete; an empty response does not prove the URL is unused outside Bird.

Code example
bird assets delete ast_01krdgeqcxet5s7t44vh8rt9mg --yes

Deleting an asset removes its library entry. Its public URL continues to serve the file, including in content you already sent. Deleting a folder moves its contents to the parent. If a child folder name conflicts at the destination, deletion is refused; rename or move the conflicting child folder, then retry. Neither operation is an emergency takedown.

Use MCP or an SDK

Local MCP exposes assets_upload for file uploads. Use a local file path for files larger than the inline limit. Hosted MCP supports the ten metadata, folder, and reference tools; it does not expose file upload. See MCP setup.

The Go, TypeScript, Python, and PHP SDKs expose assets, nested folders, and references resources for the ten JSON operations. Upload through HTTP or the CLI, then use the returned asset ID with your SDK.

Resolve upload errors

A size error requires a smaller file; changing its extension does not change the recognized type. A byte-quota error requires available organization storage. The organization also has a 100,000 retained-asset limit per region; removed library entries still count, so reuse existing assets where possible. A duplicate multipart field is rejected: send each field once. For a temporary busy response, retry with the same idempotency key. Error responses link to code-specific recovery instructions.

Next steps

Continue with the documentation, guides and examples for this topic.