Search Documentation
Search across all documentation pages
TypeScript SDK

TypeScript SDK

transcodely is the official TypeScript / JavaScript SDK for the Transcodely API. It runs on Node.js 20+, ships with full type definitions for every request and response, and bundles a hand-rolled Connect-RPC transport so you don’t need to install Connect-ES separately. The SDK is alpha (0.1.0) — breaking changes are possible on minor bumps until 1.0.0.

Install

npm install transcodely
# or
pnpm add transcodely
# or
yarn add transcodely

The SDK has one peer dependency, @bufbuild/protobuf ^1.10.0, used for generated message types. Most package managers will install it automatically.

Authenticate

The SDK takes the API key as an explicit constructor argument. The conventional environment variable is TRANSCODELY_API_KEY.

import { Transcodely } from "transcodely";

const client = new Transcodely({
  apiKey: process.env.TRANSCODELY_API_KEY!,
});

Test (ak_test_*) and live (ak_live_*) keys hit the same base URL — the environment is encoded in the prefix. Never embed an API key in browser code; the SDK is server-side only.

Create your first job

Resource methods live under lazy namespaces (client.jobs, client.videos, etc.). Method arguments are typed PartialMessage<T> shapes that auto-complete from the proto schema.

import {
  Transcodely,
  OutputFormat,
  VideoCodec,
  Resolution,
} from "transcodely";

const client = new Transcodely({ apiKey: process.env.TRANSCODELY_API_KEY! });

const job = await client.jobs.create({
  inputUrl: "https://storage.example.com/source.mp4",
  outputOriginId: "ori_x9y8z7w6v5",
  outputs: [
    {
      type: OutputFormat.HLS,
      video: [
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_1080P },
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_720P },
      ],
    },
  ],
});

console.log(job.id, job.status);

Method args use camelCase (inputUrl, outputOriginId); the SDK serializes them to snake_case (input_url, output_origin_id) on the wire automatically.

Watch a job to completion

client.jobs.watch(id) returns an AsyncIterable that emits one event per job-state change, auto-reconnecting on transient failures. Heartbeats are filtered by default. Pass an AbortSignal to cancel from your side:

import { JobStatus } from "transcodely";

const ac = new AbortController();
setTimeout(() => ac.abort(), 10 * 60 * 1000); // 10-minute ceiling

for await (const event of client.jobs.watch(job.id, { signal: ac.signal })) {
  console.log(event.event, event.job?.status, event.job?.progress);

  if (
    event.job?.status === JobStatus.COMPLETED ||
    event.job?.status === JobStatus.FAILED ||
    event.job?.status === JobStatus.CANCELED
  ) {
    break;
  }
}

The SDK retries the underlying server-side stream on APIConnectionError with exponential backoff and re-emits a SNAPSHOT event on every reconnect, so resuming is idempotent on the consumer side.

List with auto-pagination

Every list method returns a Page<T> that you can either await for a single page or .autoPage() over to walk every result.

// Single page
const page = await client.jobs.list({ pagination: { limit: 50 } });
console.log(page.items, page.nextCursor);

// All items, automatically across pages
for await (const job of client.jobs.list({ pagination: { limit: 50 } }).autoPage()) {
  console.log(job.id, job.status);
}

autoPage() stops when the API returns an empty next_cursor. See Pagination for the cursor model.

Handle typed errors

Every error inherits from TranscodelyError. Match concrete classes with instanceof:

import {
  Transcodely,
  TranscodelyError,
  AuthenticationError,
  NotFoundError,
  RateLimitError,
  InvalidRequestError,
} from "transcodely";

try {
  await client.jobs.create({ inputUrl: "...", outputs: [] });
} catch (err) {
  if (err instanceof InvalidRequestError) {
    for (const v of err.errors) {
      console.error(`${v.field}: ${v.description}`);
    }
  } else if (err instanceof RateLimitError) {
    await new Promise((r) => setTimeout(r, err.retryAfterMs ?? 1000));
  } else if (err instanceof NotFoundError) {
    console.error("not found:", err.message);
  } else if (err instanceof AuthenticationError) {
    console.error("bad API key");
  } else if (err instanceof TranscodelyError) {
    console.error(`[${err.requestId}] ${err.code}: ${err.message}`);
  } else {
    throw err;
  }
}

Every error carries code, httpStatus, requestId, and raw (the original response body). See Errors for the full hierarchy.

Override idempotency

client.jobs.create automatically generates a UUID v4 Idempotency-Key so retrying within the same process is safe. For cross-process safety (queue workers, cron jobs), pass your own:

const job = await client.jobs.create({
  inputUrl: "...",
  outputOriginId: "ori_x9y8z7w6v5",
  outputs: [/* ... */],
  idempotencyKey: `transcode_asset_${assetId}_v1`,
});

All other write methods also ship an Idempotency-Key automatically. See Idempotency for replay semantics and key-format guidance.

Request IDs

The most recent request ID is exposed for log correlation:

const job = await client.jobs.get("job_a1b2c3d4e5f6");
console.log(client.lastRequestId); // "req_..."

Errors also carry err.requestId directly.

Configuration

Pass any of these to the constructor:

OptionDefaultNotes
apiKey— required —Test or live API key
baseUrlhttps://api.transcodely.comOverride for staging or self-hosted
timeoutMs30000Request timeout in milliseconds
maxRetries3Retries on network errors, 5xx, 429, 503 with jittered backoff
apiVersioncalendar version baked at SDK build timeSent as Transcodely-Version
defaultHeadersRecord<string, string> — sent on every request
fetchImplglobalThis.fetchInject a custom fetch (testing, browser shims)
logger(event: LogEvent) => void — structured request log hook
const client = new Transcodely({
  apiKey: process.env.TRANSCODELY_API_KEY!,
  timeoutMs: 60_000,
  maxRetries: 5,
  defaultHeaders: { "X-Caller": "ingest-worker" },
  logger: (event) => console.log(event.kind, event.requestId, event.durationMs),
});

Where to go next

  • API Reference — the full RPC surface, with request and response shapes.
  • Webhook Integration — verify signed deliveries and handle events with client.webhooks.constructEvent.
  • Errors — the typed error hierarchy in one place.
  • Pagination — cursor model and auto-paging idioms.
  • Idempotency — when and how to set your own key.
  • SDK source on GitHub — full source, runnable examples in examples/, and changelog.