Skip to content
Search Documentation
Search across all documentation pages
Quick Start

Quickstart

One request turns a video URL into an adaptive HLS ladder, hosted on our CDN with a playable URL. No storage bucket, no origin, nothing to configure in the dashboard first.

Transcode a video

Copy this as-is — it points at a public sample clip, so it runs before you own any storage. managed: true means “deliver the output to Transcodely hosting”: the outputs land in managed storage and a hosted video record is created alongside the job.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Create 
  -H "Authorization: Bearer {{API_KEY}}" 
  -H "Content-Type: application/json" 
  -d '{
    "input_url": "https://www.transcodely.com/samples/transcodely-sample-30s.mp4",
    "managed": true,
    "outputs": [
      {
        "type": "hls",
        "video": [
          { "codec": "h264", "resolution": "1080p", "quality": "standard" },
          { "codec": "h264", "resolution": "720p", "quality": "standard" },
          { "codec": "h264", "resolution": "480p", "quality": "standard" }
        ]
      }
    ]
  }'
const job = await client.jobs.create({
  inputUrl: "https://www.transcodely.com/samples/transcodely-sample-30s.mp4",
  managed: true,
  outputs: [
    {
      type: OutputFormat.HLS,
      video: [
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_1080P, quality: QualityTier.STANDARD },
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_720P, quality: QualityTier.STANDARD },
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_480P, quality: QualityTier.STANDARD },
      ],
    },
  ],
});
job = client.jobs.create(
    input_url="https://www.transcodely.com/samples/transcodely-sample-30s.mp4",
    managed=True,
    outputs=[{
        "type": "hls",
        "video": [
            {"codec": "h264", "resolution": "1080p", "quality": "standard"},
            {"codec": "h264", "resolution": "720p", "quality": "standard"},
            {"codec": "h264", "resolution": "480p", "quality": "standard"},
        ],
    }],
)
// Managed is an optional field, so it takes a pointer:
// import "google.golang.org/protobuf/proto"

job, err := client.Jobs.Create(ctx, &transcodely.JobCreateParams{
	InputUrl: "https://www.transcodely.com/samples/transcodely-sample-30s.mp4",
	Managed:  proto.Bool(true),
	Outputs: []*transcodely.OutputSpec{{
		Type: transcodely.OutputFormatHLS,
		Video: []*transcodely.VideoVariant{
			{Codec: transcodely.VideoCodecH264, Resolution: transcodely.Resolution1080P, Quality: transcodely.QualityTierStandard},
			{Codec: transcodely.VideoCodecH264, Resolution: transcodely.Resolution720P, Quality: transcodely.QualityTierStandard},
			{Codec: transcodely.VideoCodecH264, Resolution: transcodely.Resolution480P, Quality: transcodely.QualityTierStandard},
		},
	}},
})

The response carries the job with an initial status of pending, one outputs entry per output you asked for, and — because this is a managed job — a top-level video_id for the hosted video that will hold the result:

{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "status": "pending",
    "progress": 0,
    "priority": "standard",
    "video_id": "vid_a1b2c3d4e5f6g7",
    "outputs": [
      {
        "id": "out_a1b2c3d4e5f6g7",
        "status": "pending",
        "progress": 0
      }
    ],
    "created_at": "2026-02-28T10:30:00Z"
  },
  "video_id": "vid_a1b2c3d4e5f6g7"
}

The first managed request on an app can take a few seconds longer than the rest: hosting is provisioned on first use, which creates the app’s managed storage and its CDN zone. Every later request skips that step. If provisioning fails, the call returns Connect code unavailable with error code hosting_provisioning_failed and creates nothing — retry in a moment.

Get an API key

The request above needs a key in the Authorization header. Create one in the dashboard under Settings > API Keys, or with ApiKeyService.Create. A key is scoped to a single app and looks like this:

ak_AbCdEf1234567890GhIjKlMn

The full secret is shown once, at creation. Store it somewhere safe — afterwards only the prefix and last four characters are ever returned. See Authentication for the details.

Watch it finish

Poll the job with its ID. A 30-second clip like the sample is usually done in well under a minute:

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Get 
  -H "Authorization: Bearer {{API_KEY}}" 
  -H "Content-Type: application/json" 
  -d '{"id": "job_a1b2c3d4e5f6"}'
const job = await client.jobs.get("job_a1b2c3d4e5f6");
job = client.jobs.get(id="job_a1b2c3d4e5f6")
job, err := client.Jobs.Get(ctx, "job_a1b2c3d4e5f6")

The job moves through pending > probing > processing > completed. Once it reads completed, each output on a managed job carries a signed_url — a ready-to-play HLS manifest served over the CDN, signed and time-limited:

{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "status": "completed",
    "progress": 100,
    "video_id": "vid_a1b2c3d4e5f6g7",
    "outputs": [
      {
        "id": "out_a1b2c3d4e5f6g7",
        "status": "completed",
        "progress": 100,
        "signed_url": "https://cdn.example.com/vid_a1b2c3d4e5f6g7/hls/master.m3u8?token=...&expires=...",
        "output_size_bytes": "15728640",
        "duration_seconds": "30",
        "actual_cost": 0.012
      }
    ],
    "total_actual_cost": 0.012,
    "currency": "EUR"
  }
}

Open that URL in any HLS-capable player — Safari plays it natively, and hls.js, Vidstack, Video.js or the Transcodely embed play it everywhere else. The token expires, so read a fresh URL from the latest response rather than caching it.

The same result is a hosted Video under the video_id in the response, with its own playback_url, poster and embed code. Polling is the simplest thing to start with; for production, take the job.succeeded webhook or the Watch stream instead.

Your own bucket instead

Managed hosting is one destination, not the only one. Point outputs at your own storage — GCS, S3, Cloudflare R2, or any S3-compatible bucket — by creating an Origin once and sending output_origin_id instead of managed:

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Create 
  -H "Authorization: Bearer {{API_KEY}}" 
  -H "Content-Type: application/json" 
  -d '{
    "input_url": "https://www.transcodely.com/samples/transcodely-sample-30s.mp4",
    "output_origin_id": "ori_x9y8z7w6v5",
    "outputs": [
      {
        "type": "hls",
        "video": [
          { "codec": "h264", "resolution": "1080p", "quality": "standard" }
        ]
      }
    ]
  }'

Your credentials stay encrypted at rest, the files land in your bucket under paths you control, and nothing about the encode changes. Storage setup walks through creating an origin for each provider, and output paths covers the path templates.

What’s Next

Run this against your own file

A free account includes 30-second test encodes, so the request on this page can be tried before anything is configured.