tscaps.docs
Documentation

API reference

Endpoints, request fields, job states, and failure codes for the Automation API.

The tscaps automation API is organized around RESTful JSON endpoints. Send your secret API key as a bearer token in the Authorization header with every request:

Authorization: Bearer TSCAPS_API_KEY
Content-Type: application/json

Base URL:

https://api.tscaps.io

Endpoints

Method Path Purpose
POST /v1/automation-jobs Create a job
GET /v1/automation-jobs/:id Get job status
POST /v1/automation-jobs/:id/cancel Cancel a job
POST /v1/automation-jobs/uploads Create an upload URL
GET /v1/automation-jobs List jobs

Create a job

POST /v1/automation-jobs

Queues a new video processing job with caption styling and subtitle burn-in.

Request parameters

Field Type Required Description
videoUrl string One source Publicly accessible HTTPS URL of the video file to process. Specify either videoUrl or uploadId, never both.
uploadId string One source ID of a file uploaded via POST /v1/automation-jobs/uploads. Specify either videoUrl or uploadId, never both.
templateId string Yes ID of the caption template to apply. Use built-in templates (such as mira or noor) or custom templates saved to your account. View all available templates in your Templates catalog.
format string No Output video container: mp4 or webm. Defaults to mp4.
quality string No Encoding bitrate quality: low, medium, or high. Defaults to high. Selecting higher quality does not change minute consumption.
resolution object No Output dimensions in pixels as { "width": number, "height": number }. Must not exceed your plan’s frame budget. Omit to preserve the source resolution (automatically downscaled if over budget).
language string No Language spoken in the video as a 2-letter ISO/BCP-47 code (e.g., en, es, fr). Automatically detected if omitted.
webhookUrl string No Public HTTPS URL where an event notification will be sent when the job reaches a terminal state (succeeded, failed, or cancelled).

Request example

{
  "videoUrl": "https://example.com/reel.mp4",
  "templateId": "mira",
  "format": "mp4",
  "quality": "high",
  "resolution": { "width": 1080, "height": 1920 },
  "language": "en",
  "webhookUrl": "https://api.yourdomain.com/webhooks/tscaps"
}

Code example

curl -X POST https://api.tscaps.io/v1/automation-jobs \
  -H "Authorization: Bearer $TSCAPS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "videoUrl": "https://example.com/reel.mp4",
    "templateId": "mira",
    "quality": "high"
  }'
const response = await fetch("https://api.tscaps.io/v1/automation-jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TSCAPS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    videoUrl: "https://example.com/reel.mp4",
    templateId: "mira",
    quality: "high",
  }),
});

const job = await response.json();
import os
import requests

response = requests.post(
    "https://api.tscaps.io/v1/automation-jobs",
    headers={"Authorization": f"Bearer {os.environ['TSCAPS_API_KEY']}"},
    json={
        "videoUrl": "https://example.com/reel.mp4",
        "templateId": "mira",
        "quality": "high",
    },
)

job = response.json()

Response

Returns 202 Accepted with the initial job record.

{
  "id": "9f2c48e1-5b7a-4a29-8874-9dfc8227b610",
  "status": "queued",
  "phase": "queued",
  "templateId": "mira",
  "quotedSeconds": null,
  "format": "mp4",
  "quality": "high",
  "resolution": null,
  "percent": null,
  "downloadUrl": null,
  "outputExpiresAt": null,
  "failureReason": null,
  "failureCode": null,
  "settledAt": null,
  "createdAt": "2026-09-12T10:11:38.000Z"
}

Get job status

GET /v1/automation-jobs/:id

Retrieves the current status and rendering progress of a specific job.

Path parameters

Parameter Type Description
id string The unique UUID of the automation job.

Code example

curl https://api.tscaps.io/v1/automation-jobs/9f2c48e1-5b7a-4a29-8874-9dfc8227b610 \
  -H "Authorization: Bearer $TSCAPS_API_KEY"
const response = await fetch("https://api.tscaps.io/v1/automation-jobs/9f2c48e1-5b7a-4a29-8874-9dfc8227b610", {
  headers: { Authorization: `Bearer ${process.env.TSCAPS_API_KEY}` },
});

const job = await response.json();
import os
import requests

response = requests.get(
    "https://api.tscaps.io/v1/automation-jobs/9f2c48e1-5b7a-4a29-8874-9dfc8227b610",
    headers={"Authorization": f"Bearer {os.environ['TSCAPS_API_KEY']}"},
)

job = response.json()

Response

Returns 200 OK with the complete job record.

{
  "id": "9f2c48e1-5b7a-4a29-8874-9dfc8227b610",
  "status": "succeeded",
  "phase": "succeeded",
  "templateId": "mira",
  "quotedSeconds": 74,
  "format": "mp4",
  "quality": "high",
  "resolution": { "width": 1080, "height": 1920 },
  "percent": null,
  "downloadUrl": "https://storage.tscaps.io/outputs/9f2c48e1-...?token=...",
  "outputExpiresAt": "2026-09-19T10:14:00.000Z",
  "failureReason": null,
  "failureCode": null,
  "settledAt": "2026-09-12T10:12:52.000Z",
  "createdAt": "2026-09-12T10:11:38.000Z"
}

Job lifecycle properties

  • status: High-level execution state. One of:
    • queued: Waiting in queue for processing capacity.
    • running: Actively processing.
    • succeeded: Video rendered and available for download.
    • failed: Job encountered an unrecoverable error.
    • cancelled: Job was cancelled by user request.
  • phase: Detailed operation currently in progress: queued, ingesting, transcribing, rendering, succeeded, failed, or cancelled.
  • percent: Integer between 0 and 100 indicating rendering progress during the rendering phase. null in other phases.
  • quotedSeconds: Measured duration of the input video in seconds (populated after ingest).
  • downloadUrl: Presigned HTTPS download link to the final video (populated upon succeeded).
  • outputExpiresAt: ISO timestamp when downloadUrl expires (rendered files remain available for 7 days).

Cancel a job

POST /v1/automation-jobs/:id/cancel

Cancels a queued or currently executing job. If the job is active, rendering stops immediately. All minutes reserved for the job are refunded back to your account balance.

This endpoint is idempotent: repeating the cancel call on an already cancelled job returns 200 OK.

Path parameters

Parameter Type Description
id string The unique UUID of the job to cancel.

Code example

curl -X POST https://api.tscaps.io/v1/automation-jobs/9f2c48e1-5b7a-4a29-8874-9dfc8227b610/cancel \
  -H "Authorization: Bearer $TSCAPS_API_KEY"
const response = await fetch("https://api.tscaps.io/v1/automation-jobs/9f2c48e1-5b7a-4a29-8874-9dfc8227b610/cancel", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.TSCAPS_API_KEY}` },
});

const job = await response.json();
import os
import requests

response = requests.post(
    "https://api.tscaps.io/v1/automation-jobs/9f2c48e1-5b7a-4a29-8874-9dfc8227b610/cancel",
    headers={"Authorization": f"Bearer {os.environ['TSCAPS_API_KEY']}"},
)

job = response.json()

Response

Returns 200 OK with the cancelled job record (status: "cancelled").


Create an upload URL

POST /v1/automation-jobs/uploads

Requests a signed URL to upload a video file directly to tscaps cloud storage when the video cannot be exposed over a public URL.

Request parameters

Field Type Required Description
fileName string Yes Original file name (e.g., reel.mp4). Used to determine media content type.
sizeBytes integer Yes Exact file size in bytes. This value is cryptographically signed into the presigned URL.

Request example

{
  "fileName": "reel.mp4",
  "sizeBytes": 14205000
}

Code example

curl -X POST https://api.tscaps.io/v1/automation-jobs/uploads \
  -H "Authorization: Bearer $TSCAPS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "fileName": "reel.mp4", "sizeBytes": 14205000 }'
const response = await fetch("https://api.tscaps.io/v1/automation-jobs/uploads", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TSCAPS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ fileName: "reel.mp4", sizeBytes: 14205000 }),
});

const upload = await response.json();
import os
import requests

response = requests.post(
    "https://api.tscaps.io/v1/automation-jobs/uploads",
    headers={"Authorization": f"Bearer {os.environ['TSCAPS_API_KEY']}"},
    json={"fileName": "reel.mp4", "sizeBytes": 14205000},
)

upload = response.json()

Response

Returns 201 Created with upload instructions:

{
  "uploadId": "3b71d39a-7c22-48a3-92f1-47fae3223019",
  "uploadUrl": "https://storage.tscaps.io/uploads/3b71d39a-...?signature=...",
  "contentType": "video/mp4",
  "sizeBytes": 14205000,
  "expiresAt": "2026-09-12T10:26:38.000Z"
}

Upload the file binary to uploadUrl via HTTP PUT with the returned Content-Length and Content-Type. Once uploaded, pass uploadId to POST /v1/automation-jobs. Read the Direct file uploads guide for complete examples.


List jobs

GET /v1/automation-jobs

Retrieves a paginated list of recent automation jobs for your account, ordered newest first.

Query parameters

Parameter Type Description
cursor string Opaque pagination cursor. Pass nextCursor from the previous response to retrieve the next page.

Code example

curl "https://api.tscaps.io/v1/automation-jobs?cursor=eyJjcmVhdGVkQXQiOi..." \
  -H "Authorization: Bearer $TSCAPS_API_KEY"
const response = await fetch("https://api.tscaps.io/v1/automation-jobs", {
  headers: { Authorization: `Bearer ${process.env.TSCAPS_API_KEY}` },
});

const { jobs, nextCursor } = await response.json();
import os
import requests

response = requests.get(
    "https://api.tscaps.io/v1/automation-jobs",
    headers={"Authorization": f"Bearer {os.environ['TSCAPS_API_KEY']}"},
)

data = response.json()
jobs = data["jobs"]
next_cursor = data["nextCursor"]

Response

Returns 200 OK:

{
  "jobs": [
    {
      "id": "9f2c48e1-5b7a-4a29-8874-9dfc8227b610",
      "status": "succeeded",
      "phase": "succeeded",
      "templateId": "mira",
      "quotedSeconds": 74,
      "format": "mp4",
      "quality": "high",
      "resolution": { "width": 1080, "height": 1920 },
      "percent": null,
      "downloadUrl": "https://...",
      "outputExpiresAt": "2026-09-19T10:14:00.000Z",
      "failureReason": null,
      "failureCode": null,
      "settledAt": "2026-09-12T10:12:52.000Z",
      "createdAt": "2026-09-12T10:11:38.000Z"
    }
  ],
  "nextCursor": null
}

Failure codes

When a job fails, the response includes:

  • failureCode: A machine-readable identifier for program logic.
  • failureReason: A human-readable description for debugging or logging.

Always branch on failureCode in your application and include a generic fallback for any future codes:

Failure Code Meaning Retryable Resolution
source-unreachable The video URL could not be reached or returned HTTP 4xx/5xx. Yes Check that the URL is public, unauthenticated, and online.
source-unreadable The file was downloaded but could not be parsed as a valid video container. No Ensure the file is an encoded MP4, WebM, MOV, or supported container.
source-too-long The video exceeds your plan’s maximum duration limit (3 min Free, 5 min Starter, 10 min Pro). No Shorten the video or upgrade your subscription plan.
output-larger-than-source The requested resolution is larger than the input video dimensions. No Tscaps does not upscale. Omit resolution or specify equal or smaller dimensions.
automation-minutes-exhausted The account has insufficient automation minutes to process the video. No Buy more minutes or wait for monthly renewal.
ingest-failed Audio extraction or preliminary video probing failed. Yes Check video codec compatibility or retry the request.
transcription-failed Speech-to-text recognition encountered an error. Yes Retry the job. If speech is in a specific language, pass the language code explicitly.
render-failed The rendering engine could not composite the subtitle frames. Yes Transient rendering error; retry the job.
timed-out Processing exceeded the maximum execution deadline. Yes Retry the job. If the problem persists, reduce video duration.
internal An unexpected server error occurred. Yes Transient error; safe to retry.

Billing guarantee

Failed and cancelled jobs never consume automation minutes. Reserved minutes are refunded to your balance immediately.