Assets
An Asset is the API’s handle for an uploaded input image or a generated result image. You create input Assets by uploading; the service creates result Assets when a job succeeds. Product requests refer to Asset ids, so an image is uploaded once and can be used by more than one request while it remains available.
Assets do not make an image public. Every call requires a valid API key, and an Asset belongs to the environment (live or test) whose key created it. Keep the key on your server. Do not expose Asset ids or content paths to a public client unless your own application checks that user’s access before returning them.
Upload
Send the image bytes as the whole request body, with the matching Content-Type. No
multipart, no JSON wrapper, no base64. The SDKs do this in assets.upload.
The answer is 201 with Location: /v1/assets/{asset_id}.
- Accepted types are
image/jpeg,image/pngandimage/webp. AnotherContent-Type, bytes that are not a recognised image, or bytes of a different type than declared are415 UNSUPPORTED_MEDIA_TYPE. A recognised image that cannot be used — over the dimension or pixel limit, or undecodable — is422 UNPROCESSABLE_IMAGE. - Too large is
413 PAYLOAD_TOO_LARGE, and it is checked before your key is: an oversized body answers 413 even with no valid key. - Metadata is removed. EXIF, XMP and IPTC are stripped and the pixels are rotated to
their displayed orientation before the asset is stored, so
widthandheightare what a viewer shows.
Hair Color Try-On needs one input Asset, the source image; the API finds the hair itself. A same-size grayscale hair mask from your application is an optional second Asset that replaces the API’s own segmentation. It does not create a hairstyle.
Uploads are not deduplicated
POST /v1/assets takes no Idempotency-Key. Uploading the same bytes twice creates two
assets. That is deliberate: a retried upload after a timeout can leave an unreferenced
asset behind, which costs nothing and expires on its own. Deduplicate at the submit,
where the key is required, not at the upload.
Reading an asset
GET /v1/assets/{asset_id} returns the metadata above for any asset in your
environment. An id that is not yours is 404 ASSET_NOT_FOUND, whether or not it exists
elsewhere.
GET /v1/assets/{asset_id}/content returns the bytes of a result asset; the SDKs
call it assets.getContent and assets.get_content. An input asset answers
404 ASSET_CONTENT_UNAVAILABLE: you already have its bytes. The bytes come from the API
itself; the response is never a redirect to object storage, so your X-API-Key is the
only credential involved.
Listing assets
GET /v1/assets returns your readable Assets, newest first, one page at a time. Filter
by purpose (input or result), job_id, or a created_gte / created_lt window,
and follow next_cursor for the next page. Listing is enabled per environment.
Deleting an asset
DELETE /v1/assets/{asset_id} deletes one of your input Assets and erases its
bytes; it answers 204. A job already submitted from it keeps its own copy until that
job is deleted or expires. A result Asset is deleted with its job, so deleting one
directly is 409 ASSET_OWNED_BY_JOB: delete the job instead
(Jobs). Deletion is enabled per environment.
Expiry
Every asset carries expires_at. Treat it as the last moment you may rely on the asset:
fetch what you need before then, and store the bytes yourself if you need them longer. A
submit that names an expired asset answers 410 ASSET_EXPIRED; upload again. Result
Assets expire with their Job.
Keep image handling inside your retention policy
Face images and generated results can identify a person. Tell people how your application uses them, limit copies to what your product needs, and delete what you no longer need. Read Privacy and retention before storing inputs or outputs. For Job output shapes, see Job outputs.