Uploading assets
Upload files into the library through presigned URLs, in one PUT or in parts, then manage them.
Assets uploaded through the API are ordinary library assets: they count towards the organisation's storage, follow the same format rules and limits as the Assets page, get the same previews and duplicate detection, and are what you hand to a flow's API Trigger.
The upload flow
An upload has three steps. The bytes travel straight to storage, so a 100 GB file works exactly as it does from the browser.
1. Begin
curl -X POST https://app.nubu.app/api/v1/assets/uploads \
-H "Authorization: Bearer nubu_api_..." \
-H "Content-Type: application/json" \
-d '{ "filename": "hero.jpg", "size_bytes": 348211, "content_type": "image/jpeg", "folder_id": null }'
The answer (201) carries the new asset_id and an upload plan:
"mode": "single": oneurlto PUT the whole file to, valid forexpires_in_seconds(an hour)."mode": "multipart"(files over 100 MiB): anupload_id, thepart_size_bytes(64 MiB), thepart_count, andparts, the first hundred presigned part URLs.
The kind of asset follows the filename's extension. When an extension fits more than one kind (a .pdf can be an image or a document), pass "kind": "image" or "kind": "document". Pass "name" to give the asset a library name other than the filename.
Pass "folder_id" (a folder's id from Folders) to upload straight into a folder; omit it or pass null for the library's root. A folder that is not the organisation's answers 422 validation_failed.
2. PUT the bytes
Single mode: PUT the file to url with the same Content-Type you declared.
curl -X PUT "<url>" -H "Content-Type: image/jpeg" --data-binary @hero.jpg
Multipart mode: split the file into part_size_bytes pieces (the last one takes the remainder) and PUT each piece to its part URL with no Content-Type. Parts may go up in any order and in parallel. A part URL is valid for an hour; for the parts you have not sent yet, or for a retry, ask for fresh URLs:
curl -X POST https://app.nubu.app/api/v1/assets/uploads/<asset_id>/parts \
-H "Authorization: Bearer nubu_api_..." \
-H "Content-Type: application/json" \
-d '{ "upload_id": "<upload_id>", "part_numbers": [101, 102, 103] }'
3. Complete
curl -X POST https://app.nubu.app/api/v1/assets/uploads/<asset_id>/complete \
-H "Authorization: Bearer nubu_api_..." \
-H "Content-Type: application/json" \
-d '{ "upload_id": "<upload_id>", "width": 1920, "height": 1080, "sha256": "<hex>" }'
Send upload_id only for a multipart upload. width, height, duration_seconds and frame_rate are optional and improve how the asset shows in the library; sha256 (the hex digest of the bytes) lets Nubu tell you about an identical file already in the library (duplicate_of). The answer carries the ready asset. Completing an asset that is already complete answers it again, so a retry is safe.
If the bytes have not arrived yet the complete answers 409 conflict; to abandon an upload, POST /assets/uploads/<asset_id>/abort (with the upload_id for a multipart one) removes the pending asset and anything stored for it.
Several files at once
POST /assets/uploads/batch takes { "files": [ ... ] } (up to 50 entries shaped like a single begin) and answers one entry per file, in order, with either its asset_id and upload plan or an error. Complete each file on its own afterwards.
Storage is checked at the begin, before any URL is handed out: a file that would not fit the organisation's remaining allowance answers 409 conflict with details.reason storage_full and a message saying how much is free (in a batch, that file's entry carries the error and the others proceed; a replacement is checked the same way, with the old file's size credited). Deleting assets frees the space at once. See Rate limits and errors.
Reading the library
GET /assetslists assets, newest first. Filters:folder_id(a folder's id; see Folders),kind(image, video, audio, document),status(pending, ready, failed),q(a name search) andtag.GET /assets/<id>answers the asset with adownload_urlfor the file, valid for 15 minutes.
Editing, replacing and deleting
PATCH /assets/<id>with any ofname,tags(an array) andfolder_id(null for the root).- Replacing a file keeps the asset id and everything that references it.
POST /assets/<id>/replacewithfilename,size_bytesandcontent_type(the extension must match the asset's) answers anuploadplan and afile_key; PUT the bytes, thenPOST /assets/<id>/replace/completewith thatfile_key(and theupload_idfor a multipart one). Until the complete succeeds the original stays in place.POST /assets/<id>/replace/partsre-mints part URLs andPOST /assets/<id>/replace/abortdiscards the attempt. DELETE /assets/<id>removes the asset and its files. An asset used by a creative that is queued or rendering answers409 conflictuntil that render finishes.