Outbound

API Documentation

Upload files, generate signed download links and manage sharing programmatically. All endpoints live under https://outbound-api.inurhuda00-526.workers.dev/api/v1.

Quickstart

Upload a file in three calls. Issue an API key, open an upload session, PUT the parts, then complete it — videos start encoding automatically.

# 1. Create an upload session
curl -X POST https://outbound-api.inurhuda00-526.workers.dev/api/v1/uploads \
  -H "x-api-key: $KEY" \
  -H "content-type: application/json" \
  -d '{"filename":"video.mp4","contentType":"video/mp4","fileSize":1048576}'

# 2. PUT the file to the presigned URL, then complete the upload
curl -X POST https://outbound-api.inurhuda00-526.workers.dev/api/v1/uploads/complete \
  -H "x-api-key: $KEY" -H "content-type: application/json" \
  -d '{"key":"…","uploadId":"…","assetId":"…","parts":[…],"title":"My video","contentType":"video/mp4"}'

Authentication

Create an API key on your account's API keys page and send it with every request — either header works:

headers
x-api-key: <your-key>
Authorization: Bearer <your-key>

Keys inherit your account's plan (an active subscription is required) and are rate limited per key. Exceeding the limit returns 429.

Uploading a file

Uploads are resumable multipart uploads, straight to storage — your file bytes never proxy through the API. Three steps:

1Create an upload session

terminal
curl -X POST https://outbound-api.inurhuda00-526.workers.dev/api/v1/uploads \
  -H "x-api-key: $KEY" \
  -H "content-type: application/json" \
  -d '{"filename":"video.mp4","contentType":"video/mp4","fileSize":1048576}'

The response contains key, uploadId, partSize and one presigned partUrls[] entry per part. Videos up to 10 GB; images 50 MB; audio 500 MB.

2PUT each part to its presigned URL

terminal
# slice the file into partSize chunks; part N goes to partUrls[N-1]
curl -X PUT "<partUrls[0]>" --data-binary @part-1.bin
# → keep the ETag response header of every part

Parts can upload in parallel and in any order. Each response carries an ETag header — collect them for the final step.

3Complete the upload

terminal
curl -X POST https://outbound-api.inurhuda00-526.workers.dev/api/v1/uploads/complete \
  -H "x-api-key: $KEY" \
  -H "content-type: application/json" \
  -d '{
    "key": "<key>", "uploadId": "<uploadId>", "assetId": "<assetId>",
    "parts": [{"partNumber": 1, "etag": "<etag>"}],
    "title": "My video", "contentType": "video/mp4"
  }'

The asset is registered and returned. Videos encode to adaptive HLS (480p / 720p / 1080p) automatically — poll the asset until metadata.encodingStatus === "ready". Abandoned sessions can be cancelled with POST /uploads/abort.

Signed download links

Mint an expiring, HMAC-signed URL to the original file — shareable with anyone, no auth needed to download:

terminal
curl -X POST "https://outbound-api.inurhuda00-526.workers.dev/api/v1/assets/<id>/download-link?expiresIn=3600" \
  -H "x-api-key: $KEY"

# → { "url": "https://…/api/share/download/<id>?exp=…&sig=…",
#     "expiresAt": "2026-06-12T01:00:00.000Z" }

expiresIn is in seconds — 60 up to 604800 (7 days), default 86400 (24 h).

Sharing

Publishing makes an asset publicly streamable and gives it a share page, an HLS URL and an embed snippet. Unpublishing revokes all of them.

terminal
curl -X POST https://outbound-api.inurhuda00-526.workers.dev/api/v1/assets/<id>/publish -H "x-api-key: $KEY"

# → {
#   "status": "published", "slug": "my-video-x7k2na",
#   "pageUrl":      "https://…/embed/my-video-x7k2na",
#   "hlsUrl":       "https://outbound-api.inurhuda00-526.workers.dev/api/share/my-video-x7k2na/hls/master.m3u8",
#   "fileUrl":      "https://outbound-api.inurhuda00-526.workers.dev/api/share/my-video-x7k2na/file",
#   "thumbnailUrl": "https://outbound-api.inurhuda00-526.workers.dev/api/share/my-video-x7k2na/thumbnail",
#   "embedHtml":    "<iframe src=…></iframe>"
# }

URLs are null while the asset is a draft (and hlsUrl until encoding is ready). Check state any time with GET /assets/:id/share.

Endpoint reference

POST/uploads

Create an upload session — returns presigned part URLs.

POST/uploads/complete

Register the uploaded file as an asset; videos start encoding.

POST/uploads/abort

Cancel an in-progress upload session.

GET/assets

List your assets — ?page, ?limit, ?type, ?status, ?q.

GET/assets/:id

Asset detail, including its sharing state and URLs.

DELETE/assets/:id

Delete the asset and every stored file that belongs to it.

POST/assets/:id/download-link

Mint an expiring signed download URL — ?expiresIn seconds.

GET/assets/:id/share

Current sharing status + public URLs.

POST/assets/:id/publish

Publish — enables the share page, HLS stream and embed.

POST/assets/:id/unpublish

Back to draft — revokes all public URLs.

Responses & errors

Every endpoint returns the same envelope — { success, message, statusCode, data }. Errors use it too, with success: false and an optional code:

401Missing, invalid or expired API key.
403Plan does not allow this action (e.g. no active subscription).
404Asset not found — or owned by another account.
400Validation failed; the message says which field.
429API key rate limit exceeded — back off and retry.
Built withTanship