assets:read; uploading, editing and deleting them assets:write. In the web app, every role but viewers can upload and delete. Published-only keys can’t list assets: a site reaches the ones it shows through its records, with expand.
Upload
Files are at most 10 MB each on Free and 100 MB on paid plans, and count toward the organization’s storage. On Free, storage is a hard limit: an upload that would go over it is refused. In the web app, choose Upload on the Assets page, or drop files anywhere on it. An asset field in a record’s editor takes uploads too. With an SDK or the CLI, upload takes a file and returns the ready asset, whoseid goes into an asset field:
Over HTTP
Without an SDK or the CLI, an upload takes three requests. The file goes straight to storage, not through the API.1
Start the upload
Send the file’s name, type and exact size in bytes. The response is the asset,
$PROJECT_ID is your key’s project (prj_…): GET /v1/me returns it as api_key.project_id.pending, with an upload: the method, url and headers to send the file with, and when it expires_at.2
Send the file
Send the file’s bytes to
upload.url with upload.method, and every header in upload.headers, before upload.expires_at. No Authorization header: the URL carries its own.3
Complete it
The API checks the file has the declared size and type, reads an image’s dimensions and marks the asset
ready. Only ready assets can be used in records.422 upload_missing means the file hasn’t arrived yet; 422 upload_mismatch means it differs from what you declared, and the asset is marked failed, so start a new upload. A project can have 100 uploads in progress at a time (409 too_many_uploads), and uploads never completed are removed after a day.
Agents connected to the MCP server upload in the same steps, with its start_upload and complete_upload tools.
Alt text and filenames
An asset’salt text says what an image shows, for screen readers and search engines. It is the default wherever the asset is used. An image in rich text can have its own alt, which it keeps once set. The filename is the name the file downloads under.
In the web app, open an asset on the Assets page, change its Filename or Alt text and choose Save. Through the API:
null alt clears it. The file itself can’t change: to replace it, upload a new asset and point the records at it.
Find assets
The Assets page searches filenames and alt text, filters by type (Images, Documents, Video, Audio or Other), and lists deleted assets under Deleted.GET /v1/projects/{project_id}/assets lists them newest first, a page at a time, like records:
q: words that must each appear in the filename or alt text, ignoring case.q=hero jpgfindsHero-banner.jpg.filter[kind]:image,video,audio,document(PDFs, text, Office and OpenDocument files) orother, or several withfilter[kind][in]=image,video.filter[content_type]: a MIME type or atype/*wildcard, or several withfilter[content_type][in]=image/*,application/pdf, such as the types an asset field accepts.filter[deleted]=true: deleted assets instead.
Where an asset is used
Before you delete or replace an image or file, check which records use it:records: how many records use it.published: how many of them are published with it in their content, which is what your sites show.uses: the 10 most recently updated of them, each with itsrecordand the keys of thefieldsthat use the asset.
records:read as well as assets:read, and published-only keys get 403. In the SDKs, it is assets.usage.
In the web app, open an asset on the Assets page: Used in lists the records that use it. Deleting an asset that records use asks first.
Delete, restore and purge
Deleting an asset (Delete, orDELETE /v1/assets/{asset_id}) keeps it for 30 days, until its purge_after, and then removes it for good. Records that use it keep its ID. Until then, Restore on the Deleted tab (POST /v1/assets/{asset_id}/restore) brings it back.
To remove a file sooner, delete it and then choose Delete permanently (POST /v1/assets/{asset_id}/purge). That can’t be undone. Its file, media and every rendition leave the CDN within a minute or so, though browsers keep what they cached, and records that used it keep an ID that no longer resolves. Purging frees the file’s storage.
Webhooks
Asset changes sendasset.created (when an upload completes), asset.updated, asset.deleted, asset.restored and asset.purged: see Webhooks.