CDN Endpoints

API endpoints for uploading, managing, and transforming assets.

POST/cdn/upload

Generate a presigned URL for uploading a file.

After upload, the file's actual content is verified against the declared mimeType. If the bytes contradict the declaration (e.g. a JPEG uploaded as video/mp4), the asset's type is corrected automatically. Files declared as video or audio that cannot be decoded are marked failed.

REQUEST BODY

FieldTypeRequiredDescription
filenamestringrequiredOriginal filename
mimeTypestringrequiredMIME type (e.g., image/jpeg)
sizenumberrequiredFile size in bytes (max 100MB)
folderstringoptionalFolder path for organization
metadataobjectoptionalCustom metadata

RESPONSE

FieldTypeDescription
uploadUrlstringPresigned S3 URL for upload
assetIdstringAsset ID for confirmation
cdnUrlstringCDN URL for the file
expiresAtISO 8601URL expiration time
Example Request
curl -X POST "https://api.stack0.dev/v1/cdn/upload" \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"filename": "profile.jpg",
"mimeType": "image/jpeg",
"size": 102400,
"folder": "avatars"
}'
POST/cdn/upload/{assetId}/confirm

Confirm that a file upload has completed successfully.

Example Request
curl -X POST "https://api.stack0.dev/v1/cdn/upload/asset_xxx/confirm" \
-H "Authorization: Bearer sk_live_your_api_key"
GET/cdn/assets/{id}

Get a single asset by ID.

GET/cdn/assets

List assets with optional filters and pagination.

QUERY PARAMETERS

ParameterTypeDescription
limitnumberMax results (default 50, max 100)
offsetnumberOffset for pagination
folderstringFilter by folder
typestringFilter by type (image, video, audio, document, other)
searchstringSearch by filename
sortBystringSort by: createdAt, filename, size
sortOrderstringSort order: asc, desc
PATCH/cdn/assets/{id}

Update asset metadata.

DELETE/cdn/assets/{id}

Delete a single asset.

POST/cdn/assets/delete

Delete multiple assets by their IDs.

POST/cdn/assets/move

Move one or more assets to a different folder.

POST/cdn/transform

Get a URL for a transformed image with resize, crop, and effects options.

TRANSFORM OPTIONS

OptionTypeDescription
widthnumberTarget width (max 4096)
heightnumberTarget height (max 4096)
fitstringcover | contain | fill | inside | outside
formatstringauto | jpeg | webp | avif | png
qualitynumber1-100
blurnumber0.3-1000
grayscalebooleanConvert to grayscale
Example Request
curl -X POST "https://api.stack0.dev/v1/cdn/transform" \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"assetId": "asset_xxx",
"options": {
"width": 400,
"height": 300,
"fit": "cover",
"format": "webp",
"quality": 80
}
}'

Video Merge Endpoints

Endpoints for merging multiple videos and images into a single video.

POST/cdn/video/merge

Create a merge job to combine multiple videos and images into a single video.

Input content is verified before processing: a video input whose bytes are actually a still image or audio-only file fails the job with a descriptive error instead of producing a broken clip, and the audio track must contain an audio stream.

REQUEST BODY

FieldTypeRequiredDescription
projectSlugstringrequiredProject identifier
inputsarrayrequiredArray of assets to merge (1-100 items)
inputs[].assetIduuidrequiredAsset ID of video or image
inputs[].durationnumberoptionalDuration in seconds (required for images, max 3600)
inputs[].startTimenumberoptionalTrim start time in seconds (videos only)
inputs[].endTimenumberoptionalTrim end time in seconds (videos only)
audioTrackobjectoptionalAudio track overlay configuration
audioTrack.assetIduuidrequiredAsset ID of the audio file
audioTrack.loopbooleanoptionalLoop audio if shorter than video (default: false)
audioTrack.fadeInnumberoptionalFade in duration (0-10 seconds)
audioTrack.fadeOutnumberoptionalFade out duration (0-10 seconds)
outputobjectoptionalOutput configuration
output.formatstringoptionalOutput format: mp4, webm (default: mp4)
output.qualitystringoptionalQuality: 360p, 480p, 720p, 1080p, 1440p, 2160p (default: 720p)
output.aspectRatiostringoptionalOutput canvas: auto, 16:9, 9:16, 1:1 (default: auto). auto matches the orientation of the first visual input — portrait inputs produce portrait output (1080x1920 at 1080p). Explicit values force the canvas; quality sets the short edge.
output.filenamestringoptionalCustom filename (max 255 chars)
webhookUrlstringoptionalURL for completion notification
Example Request
curl -X POST "https://api.stack0.dev/v1/cdn/video/merge" \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"projectSlug": "my-project",
"inputs": [
{ "assetId": "uuid-1" },
{ "assetId": "uuid-2", "duration": 5 },
{ "assetId": "uuid-3", "startTime": 10, "endTime": 60 }
],
"audioTrack": {
"assetId": "audio-uuid",
"loop": true,
"fadeIn": 2,
"fadeOut": 3
},
"output": {
"format": "mp4",
"quality": "1080p",
"aspectRatio": "auto"
}
}'
GET/cdn/video/merge/{jobId}

Get details of a merge job including status and output asset.

RESPONSE

FieldTypeDescription
iduuidMerge job ID
statusstringpending, queued, processing, completed, failed, cancelled
progressnumberProgress percentage (0-100)
outputAssetobjectOutput asset details (when completed)
outputAsset.cdnUrlstringCDN URL of the merged video
outputAsset.durationnumberTotal duration in seconds
outputAsset.sizenumberFile size in bytes
GET/cdn/video/merge

List merge jobs with optional status filter.

QUERY PARAMETERS

ParameterTypeDescription
projectSlugstringProject identifier (required)
statusstringFilter by status
limitnumberMax results (default 20, max 100)
offsetnumberOffset for pagination
POST/cdn/video/merge/{jobId}/cancel

Cancel a pending or processing merge job.

Example Request
curl -X POST "https://api.stack0.dev/v1/cdn/video/merge/job-uuid/cancel" \
-H "Authorization: Bearer sk_live_your_api_key"