Promote an upload, or ingest from a URL
const url = 'http://localhost:3000/api/v1/assets';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"token":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","filename":"example","mime":"example","fields":{"additionalProperty":"example"},"collections":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"],"tags":["example"],"rights":{"license":"example","territories":["example"],"channels":["example"],"embargo":"2026-04-15","expires":"2026-04-15","modelRelease":"released","downloadable":true},"origin":"shot","parentAssetId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","generator":"example","prompt":"example","versionOf":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","status":"draft","private":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://localhost:3000/api/v1/assets \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "token": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "filename": "example", "mime": "example", "fields": { "additionalProperty": "example" }, "collections": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "tags": [ "example" ], "rights": { "license": "example", "territories": [ "example" ], "channels": [ "example" ], "embargo": "2026-04-15", "expires": "2026-04-15", "modelRelease": "released", "downloadable": true }, "origin": "shot", "parentAssetId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "generator": "example", "prompt": "example", "versionOf": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "status": "draft", "private": true }'With token: promote a staged upload. With url: the server fetches it (public addresses only). Identical bytes dedupe to the existing asset (200). Without the write scope the new asset is proposed, and required fields may be left for the person who approves it. C2PA Content Credentials in the file are read into c2pa, and set origin and generator unless given. With versionOf, it is a new version of that asset: filed where it is, with its tags and fields, and current once approved; public when the version it takes over from is, if whoever uploads or approves it may share it.
Scope: propose.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
From POST /api/v1/uploads, after the PUT
Custom field values, keyed by field key
object
object
Countries it may run in (ISO 3166-1 alpha-2); empty: anywhere
What it may be used for, e.g. web, print, paid-social; empty: anything
Whether people outside the project may download the file itself; null follows its license (isDownloadable). Either way they see it.
A new version of this asset: it joins its version stack, collections, tags and fields, and with write on it becomes current
Draft keeps it out of the library until it is submitted and approved. Without write it is proposed whatever this says
Only people added to it, or to a collection it is in, and admins see it. A new version keeps the one before’s
object
Public http(s) URL the server fetches. A Figma or Google Docs, Sheets, Slides or Drive link is kept as the link and shows as its embed
Defaults to the URL’s last path segment, or a linked file’s title
Custom field values, keyed by field key
object
object
Countries it may run in (ISO 3166-1 alpha-2); empty: anywhere
What it may be used for, e.g. web, print, paid-social; empty: anything
Whether people outside the project may download the file itself; null follows its license (isDownloadable). Either way they see it.
A new version of this asset: it joins its version stack, collections, tags and fields, and with write on it becomes current
Draft keeps it out of the library until it is submitted and approved. Without write it is proposed whatever this says
Only people added to it, or to a collection it is in, and admins see it. A new version keeps the one before’s
Responses
Section titled “Responses”Deduped to an existing asset
object
object
The asset’s own values
object
Values inherited from its collections; own values win
object
Draft, proposed (in review), active (approved), archived or rejected
The status; expired for an approved asset past its last day of use; deleted, until restored or purged
Its stack’s current approved version: the others are superseded by it
For a proposal: who made it, a person’s or an API key’s name
Why a person rejected it
Custom field values an agent suggested, waiting for a person to accept or dismiss
object
object
ISO 3166-1 alpha-2; empty: anywhere
Empty: any use
Set by a person; null or missing follows the license (see downloadable on its description)
object
The app that signed it
The signing certificate’s organization, as the file claims it; not verified
IPTC: digitalCapture, trainedAlgorithmicMedia…
The tool the actions name, often the model
Its own flag; it is private too when every collection it is in is
Served at /a/{id} to anyone while it may be used; otherwise to people who can see it, and signed URLs
Example
{ "data": { "status": "draft", "state": "draft", "rights": { "modelRelease": "released" }, "origin": "shot", "via": "agent" }}Created
object
object
The asset’s own values
object
Values inherited from its collections; own values win
object
Draft, proposed (in review), active (approved), archived or rejected
The status; expired for an approved asset past its last day of use; deleted, until restored or purged
Its stack’s current approved version: the others are superseded by it
For a proposal: who made it, a person’s or an API key’s name
Why a person rejected it
Custom field values an agent suggested, waiting for a person to accept or dismiss
object
object
ISO 3166-1 alpha-2; empty: anywhere
Empty: any use
Set by a person; null or missing follows the license (see downloadable on its description)
object
The app that signed it
The signing certificate’s organization, as the file claims it; not verified
IPTC: digitalCapture, trainedAlgorithmicMedia…
The tool the actions name, often the model
Its own flag; it is private too when every collection it is in is
Served at /a/{id} to anyone while it may be used; otherwise to people who can see it, and signed URLs
Example
{ "data": { "status": "draft", "state": "draft", "rights": { "modelRelease": "released" }, "origin": "shot", "via": "agent" }}default
Section titled “default”An error
object
object
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": "example" }}