API Documentation

Run transcode.pro programmatically. Every request runs a fixed preset or an admin-published tool with documented options — there's no raw/custom-filter mode, so cost and behavior are always predictable.

Quickstart

  1. Create an account and verify your email.
  2. Go to API & Credits in your dashboard, create a key, and claim your free trial credits.
  3. Top up if you need more than the trial amount.
  4. Verify the key works before building against it — GET /api/v1/account with your key should return your credit balance:
curl --request GET \
  --url "https://transcode.pro/api/v1/account" \
  --header "Authorization: Bearer dsk_live_your_key_here"
  1. Make your first job request:
curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"thumbnail"}'

Response:

{
  "id": "d7291197-0050-4cdb-a731-ebbc656ca765",
  "status": "PROCESSING",
  "creditsCharged": 1,
  "balanceAfter": 19
}

One request, or two?

Add "wait": 25 to the body above (max 25 seconds) and this becomes one request: we hold the connection open, keep checking the job for you, and the same response comes back with outputUrlalready in it once it's done — image, audio, or video, same mechanism. This covers the large majority of jobs, which finish in well under 25 seconds.

Skip wait(or the job is still running when it runs out — rare, usually a large file) and it's two requests: this one only returns an id and status: "PROCESSING", no download link yet — you then call GET /api/v1/jobs/:id (optionally with its own ?wait=25) to get outputUrlonce it's ready.

How to test this: the cURL tab above runs as-is in any terminal (Mac/Linux/WSL, or Windows via curl.exe or Git Bash) — just swap in your real key and file URL. No terminal? Paste the same URL, headers, and body into Postman or Insomnia as a raw JSON POST request. For an actual integration, copy the Node.js, Python, or Go tab instead — every example on this page runs unmodified once you swap in your key.

Authentication

Every request (except the two marked “No auth” below) needs an Authorization header with a Bearer key from your dashboard:

Authorization: Bearer dsk_live_...

Keys are shown once, at creation — we only store a hash, so if you lose one, revoke it and create a new key. Revoking takes effect immediately on the very next request made with that key.

Endpoints

Every endpoint includes production-ready examples for cURL, Node.js, Python, and Go. Replace the sample API key, input URL, and resource IDs with your own values. Keep secret API keys in trusted server-side environments. Never expose them in browser or mobile client code.

GET/api/v1/account200 OKRequires API key

Check your current credit balance.

curl --request GET \
  --url "https://transcode.pro/api/v1/account" \
  --header "Authorization: Bearer dsk_live_your_key_here"
Example response200 OKapplication/json
{ "balanceCredits": 19 }
GET/api/v1/tools200 OKNo auth

The live, complete list of everything you can run right now: all presets (with options) plus any admin-published tools.

curl --request GET \
  --url "https://transcode.pro/api/v1/tools"
Example response200 OKapplication/json
{
  "presets": [ { "preset": "thumbnail", "creditsPerJob": 1, "options": [...] }, ... ],
  "dynamicTools": [ { "toolId": "catalog:video-filter:hqdn3d", "name": "hqdn3d", "creditsPerJob": 10 }, ... ]
}
GET/api/v1/pricing200 OKNo auth

Current credit cost per preset.

curl --request GET \
  --url "https://transcode.pro/api/v1/pricing"
Example response200 OKapplication/json
{
  "model": {
    "creditsPerInr": 5,
    "durationUnitSeconds": 60,
    "minimumDurationUnits": 1,
    "formula": "ceil(baseCredits * resolutionMultiplier * max(1, durationSeconds / durationUnitSeconds) * durationTierMultiplier)"
  },
  "pricing": [
    { "preset": "probe", "creditsPerJob": 2, "billingBasis": "flat_job", "description": "..." },
    { "preset": "transcode", "creditsPerJob": 13, "billingBasis": "per_minute_base", "description": "..." }
  ]
}
POST/api/v1/uploads201 CreatedRequires API key

Get a presigned URL to upload a local file.

Free — credits are only charged when you create a job, not for uploading. Skip this entirely if your input is already reachable at a public URL.

curl --request POST \
  --url "https://transcode.pro/api/v1/uploads" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"filename":"video.mp4","contentType":"video/mp4","sizeBytes":887988}'
Example response201 Createdapplication/json
{
  "mode": "single",
  "key": "uploads/...",
  "input": "https://...",
  "url": "https://...presigned..."
}

Upload the file bytes with PUT to the returned presigned url, then pass the returned input to a job.

POST/api/v1/jobs201 CreatedRequires API key

Create a job. Provide either preset (+ options) or toolId — never both, never raw filters.

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"transcode","options":{"width":1280,"crf":23},"output":{"filename":"out.mp4"}}'
Example response201 Createdapplication/json
{
  "id": "d7291197-0050-4cdb-a731-ebbc656ca765",
  "status": "PROCESSING",
  "creditsCharged": 13,
  "balanceAfter": 87
}

Returns 402immediately if your balance can't cover the job's cost — nothing is charged or queued in that case. If the job already finished by the time we respond (most presets do), this response also includes outputUrl (or error) directly — check status before falling back to polling GET /api/v1/jobs/:id. Pass "wait": <seconds, max 25> in the body to have us block and retry internally instead — you only get a response once the job is done (or the wait runs out).

GET/api/v1/jobs/:id200 OKRequires API key

Fetch a job's status and result.

Add ?wait=<seconds, max 25> to block on this specific job instead of polling it yourself.

curl --request GET \
  --url "https://transcode.pro/api/v1/jobs/d7291197-0050-4cdb-a731-ebbc656ca765" \
  --header "Authorization: Bearer dsk_live_your_key_here"
Example response200 OKapplication/json
{
  "id": "...",
  "status": "COMPLETED",       // QUEUED | PROCESSING | COMPLETED | FAILED | CANCELLED
  "progress": 100,
  "outputUrl": "https://...",
  "usage": { "creditsCharged": 10 }  // present once status is terminal
}

frame-sample jobs return a ZIP of individual numbered frame images as outputUrl, plus a frames: [{ "index": 1, "timeSec": 0 }, ...]manifest of each frame's timestamp.

GET/api/v1/jobs200 OKRequires API key

List jobs created by this key.

curl --request GET \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here"
Example response200 OKapplication/json
{ "jobs": [ { "id": "...", "status": "COMPLETED", ... } ] }

Presets

The fixed set of operations available to every account. Pass any of these as optionsin a preset job — anything not listed isn't configurable.

probe30 base credits

Reads metadata only — no options, no output file.

Create a probe job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"probe"}'

Poll GET /api/v1/jobs/:id — once COMPLETED, the source's metadata is in the usage/probe fields; there's no downloadable output for this preset.

thumbnail30 base credits

Extracts a single frame as an image.

OptionTypeDetails
timeSecnumberdefault 1 · 0–∞ — Timestamp to capture, in seconds.
widthinteger16–7680 — Output width in pixels (height scales automatically).
formatstringdefault jpg · jpg / png / webp

Create a thumbnail job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"thumbnail","options":{"timeSec":5,"width":640,"format":"jpg"}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, download the result from outputUrl.

audio-extract30 base credits

Extracts (and optionally re-encodes) the audio track.

OptionTypeDetails
formatstringdefault mp3 · mp3 / aac / opus / flac / wav
bitratestring — e.g. "128k", "2500k", "5M".

Create a audio-extract job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"audio-extract","options":{"format":"mp3","bitrate":"192k"}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, download the result from outputUrl.

transcode30 base credits

Full re-encode — change codec, resolution, bitrate, frame rate, or container.

OptionTypeDetails
videoCodecstringdefault libx264 · libx264 / libx265 / libsvtav1 / h264_nvenc — Or any other codec name supported by the processing backend.
audioCodecstringdefault aac · aac / libopus / libfdk_aac / copy
crfinteger0–63 — Quality — lower is higher quality and larger file size.
videoBitratestring — e.g. "2500k", "5M".
audioBitratestring — e.g. "128k".
widthinteger16–7680
heightinteger16–4320
fpsnumber1–240
speedPresetstringultrafast / superfast / veryfast / faster / fast / medium / slow / slower / veryslow
formatstringdefault mp4 · mp4 / mkv / webm / mov / ts

Create a transcode job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"transcode","options":{"width":1280,"height":720,"crf":23,"videoCodec":"libx264","format":"mp4"},"output":{"filename":"out.mp4"}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, download the result from outputUrl.

watermark30 base credits

Overlays an image on every frame.

OptionTypeDetails
overlayUrlstringrequired — URL of the png/jpg/webp image to overlay.
positionstringdefault bottom-right · top-left / top-right / bottom-left / bottom-right / center
marginintegerdefault 10 · 0–500
formatstringdefault mp4 · mp4 / mkv / webm / mov

Create a watermark job input is the video, options.overlayUrl is a separate image URL to overlay:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"watermark","options":{"overlayUrl":"https://example.com/logo.png","position":"bottom-right","margin":20},"output":{"filename":"watermarked.mp4"}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, download the result from outputUrl.

aspect-ratio30 base credits

Reframes video to a target aspect ratio by padding (letterbox/pillarbox), cropping, or stretching.

OptionTypeDetails
targetstringdefault 16:9 · 16:9 / 9:16 / 1:1 / 4:3 / 21:9
fitstringdefault pad · pad / crop / stretch — pad = letterbox/pillarbox (no distortion), crop = fills the frame by cropping excess, stretch = forces the ratio (may distort).

Create a aspect-ratio job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"aspect-ratio","options":{"target":"9:16","fit":"pad"}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, download the result from outputUrl.

fade30 base credits

Fades audio in at the start and/or out at the end.

OptionTypeDetails
fadeInnumberdefault 2 · 0–30 — Fade-in duration in seconds.
fadeOutnumberdefault 3 · 0–30 — Fade-out duration in seconds.

Create a fade job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"fade","options":{"fadeIn":2,"fadeOut":3}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, download the result from outputUrl.

frame-sample56 base credits

Samples individual still frames at a low, configurable rate (e.g. 1 frame/second) and returns them bundled as a ZIP — built for feeding a bounded set of frames to an AI/vision pipeline instead of every native frame.

OptionTypeDetails
fpsnumberdefault 1 · 0.1–10 — Sampling rate — 1 = one frame/second, 0.5 = one frame every 2 seconds.
maxFramesintegerdefault 24 · 1–60 — Hard cap of 60 frames per request.
formatstringdefault jpg · jpg / png / webp

Create a frame-sample job:

curl --request POST \
  --url "https://transcode.pro/api/v1/jobs" \
  --header "Authorization: Bearer dsk_live_your_key_here" \
  --header "Content-Type: application/json" \
  --data '{"input":"https://example.com/video.mp4","preset":"frame-sample","options":{"fps":1,"maxFrames":10,"format":"jpg"}}'

Poll GET /api/v1/jobs/:id — once COMPLETED, outputUrl is a .zip of the sampled frames, and frames lists each one's timestamp.

Published tools

Beyond the fixed presets, we occasionally publish additional single-purpose tools — a specific filter or codec verified and enabled by our team. These run at fixed, pre-verified settings (no configurable options) — pass the toolId shown below instead of preset. This list is always current — fetch GET /api/v1/tools to check programmatically.

None published right now — only the fixed presets above are available.

Response codes

Successful responses use JSON unless noted otherwise. Errors use { "error": "message" } with a matching HTTP status code.

StatusMeaning
200Request completed successfully.
201Upload ticket or processing job created.
400Invalid request body (see the error message for which field).
401Missing, invalid, or revoked API key.
402Insufficient credits for this job. Nothing was charged.
422We checked your input first and it's missing what this tool needs (e.g. no audio track for audio-extract/fade, or no video track for a video tool). Nothing was charged or sent to processing.
404Job or tool not found, or it belongs to a different key.
429Rate limit exceeded. Follow the Retry-After response header.
500Unexpected platform error. Retry or contact support if it persists.
502The processing service is temporarily unavailable. Retry.

Rate limits

Independent per key, in two buckets so polling a job doesn't compete with creating new ones:

BucketApplies toLimit
createPOST /api/v1/jobs, POST /api/v1/uploads30 / minute
readGET /api/v1/jobs, GET /api/v1/jobs/:id, GET /api/v1/account120 / minute

Every authenticated response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds) headers. Exceeding a limit returns 429 with a Retry-After header.

Pricing

Base rates come directly from the admin credit system. Full-timeline work bills exact media seconds in 60-second units with a one-unit minimum, then applies the configured resolution and duration-tier modifiers. Probe and thumbnail are flat jobs because they do not process the complete timeline. These values are live and apply equally to the API and platform tools.

PresetWhat it doesBase credits
customRaw ffmpeg args (crop, rotate, trim, loop, speed, etc.)30/min
probeInspect media metadata30/job
thumbnailExtract a single frame30/job
audio-extractExtract/convert audio track30/min
fadeFade audio in and/or out30/min
aspect-ratioPad, crop, or stretch to a target aspect ratio30/min
watermarkOverlay image/text on video30/min
transcodeRe-encode video (codec/resolution/bitrate)30/min
frame-sampleSample frames at a configurable rate, bundled as a ZIP56/min

Formula: ceil(base × resolution multiplier × billable minutes × duration-tier multiplier). $1 = 100 credits.