Search Documentation
Search across all documentation pages
Metadata

Metadata

Metadata lets you attach custom key-value pairs to jobs. This is useful for linking Transcodely jobs to your internal systems — tracking which user uploaded a video, tagging jobs by campaign, or storing any other context you need.

Overview

Metadata is a flat map of string keys to string values, set at job creation time:

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Create 
  -H "Authorization: Bearer {{API_KEY}}" 
  -H "X-Organization-ID: org_a1b2c3d4e5" 
  -H "Content-Type: application/json" 
  -d '{
    "input_url": "gs://my-bucket/video.mp4",
    "output_origin_id": "ori_x9y8z7w6v5",
    "outputs": [
      {
        "type": "mp4",
        "video": [
          { "codec": "h264", "resolution": "1080p", "quality": "standard" }
        ]
      }
    ],
    "metadata": {
      "user_id": "usr_12345",
      "campaign": "summer-2026",
      "source": "upload-api",
      "content_id": "vid_abc123"
    }
  }'
const job = await client.jobs.create({
  inputUrl: "gs://my-bucket/video.mp4",
  outputOriginId: "ori_x9y8z7w6v5",
  outputs: [
    {
      type: OutputFormat.MP4,
      video: [
        {
          codec: VideoCodec.H264,
          resolution: Resolution.RESOLUTION_1080P,
          quality: QualityTier.STANDARD,
        },
      ],
    },
  ],
  metadata: {
    user_id: "usr_12345",
    campaign: "summer-2026",
    source: "upload-api",
    content_id: "vid_abc123",
  },
});
job = client.jobs.create(
    input_url="gs://my-bucket/video.mp4",
    output_origin_id="ori_x9y8z7w6v5",
    outputs=[{
        "type": "mp4",
        "video": [{"codec": "h264", "resolution": "1080p", "quality": "standard"}],
    }],
    metadata={
        "user_id": "usr_12345",
        "campaign": "summer-2026",
        "source": "upload-api",
        "content_id": "vid_abc123",
    },
)
job, err := client.Jobs.Create(ctx, &transcodely.JobCreateParams{
    InputUrl:       "gs://my-bucket/video.mp4",
    OutputOriginId: proto.String("ori_x9y8z7w6v5"),
    Outputs: []*transcodely.OutputSpec{{
        Type: transcodely.OutputFormatMP4,
        Video: []*transcodely.VideoVariant{{
            Codec:      transcodely.VideoCodecH264,
            Resolution: transcodely.Resolution1080P,
            Quality:    transcodely.QualityTierStandard,
        }},
    }},
    Metadata: map[string]string{
        "user_id":    "usr_12345",
        "campaign":   "summer-2026",
        "source":     "upload-api",
        "content_id": "vid_abc123",
    },
})

Metadata is returned in every job response, and inside the data of the corresponding webhook events:

{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "status": "completed",
    "metadata": {
      "user_id": "usr_12345",
      "campaign": "summer-2026",
      "source": "upload-api",
      "content_id": "vid_abc123"
    }
  }
}

Constraints

ConstraintLimit
Maximum entries20 key-value pairs per job
Key length1-64 characters
Value lengthUp to 1,024 characters
Key formatFree-form string
Value formatFree-form string

Metadata is immutable after job creation. You cannot add, update, or remove metadata entries after the job has been created.

Common Use Cases

Map Transcodely jobs back to your own database entities:

{
  "metadata": {
    "user_id": "usr_12345",
    "video_id": "vid_abc123",
    "upload_session": "sess_x9y8z7w6"
  }
}

When a webhook fires, you can use these values to update the correct records in your system.

Categorization and Reporting

Tag jobs for analytics and cost reporting:

{
  "metadata": {
    "team": "content-team",
    "campaign": "summer-2026",
    "content_type": "ugc",
    "tier": "free"
  }
}

Export metadata alongside job costs to build per-team or per-campaign cost reports.

Debugging and Tracing

Include request tracing information for debugging:

{
  "metadata": {
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "request_id": "req_n3o4p5q6r7s8",
    "environment": "staging",
    "git_sha": "a1b2c3d"
  }
}

Batch Processing

Track batch position and source:

{
  "metadata": {
    "batch_id": "batch_2026-01-15",
    "batch_index": "42",
    "total_in_batch": "100",
    "source_queue": "transcode-queue"
  }
}

Metadata in Webhooks

All metadata is included in webhook payloads, making it easy to correlate events with your internal state:

{
  "type": "job.succeeded",
  "data": {
    "id": "job_a1b2c3d4e5f6",
    "object": "job",
    "status": "completed",
    "metadata": {
      "user_id": "usr_12345",
      "video_id": "vid_abc123"
    }
  }
}

In your webhook handler, use the metadata to route the event to the right processing logic:

app.post('/webhooks/transcodely', async (req, res) => {
  // Verify the signature over the raw body first — see the Webhook Integration guide.
  // The envelope's `data` field is the resource snapshot (here, a job).
  const job = req.body.data;
  const userId = job.metadata.user_id;
  const videoId = job.metadata.video_id;

  // Update your database
  await db.videos.update({
    where: { id: videoId },
    data: {
      transcode_status: job.status,
      output_url: job.outputs[0].output_url,
    },
  });

  // Notify the user
  await notifications.send(userId, {
    type: 'video_ready',
    videoId,
  });

  res.status(200).send('OK');
});
def handle_event(event: Event) -> None:
    # construct_event has already verified the signature — see the Webhook
    # Integration guide. event.data is the resource snapshot (here, a job).
    job = event.data
    user_id = job.metadata["user_id"]
    video_id = job.metadata["video_id"]

    # Update your database, then notify the user.
    db.videos.update(
        video_id,
        transcode_status=job.status,
        output_url=job.outputs[0].output_url,
    )
    notifications.send(user_id, type="video_ready", video_id=video_id)
// ConstructEvent has already verified the signature — see the Webhook
// Integration guide. event.Job() unwraps the resource snapshot.
job, ok := event.Job()
if !ok {
    return
}
userID := job.GetMetadata()["user_id"]
videoID := job.GetMetadata()["video_id"]

// Update your database, then notify the user.
db.Videos.Update(videoID, job.GetStatus(), job.GetOutputs()[0].GetOutputUrl())
notifications.Send(userID, "video_ready", videoID)

Best Practices

  1. Use consistent key naming across your application — decide on a convention (e.g., snake_case) and stick with it.
  2. Do not store sensitive data in metadata. Values are stored as-is and are visible in API responses and webhook payloads.
  3. Keep values short when possible. While values can be up to 1,024 characters, shorter values are easier to work with.
  4. Use metadata for correlation, not configuration. Metadata does not affect how a job is processed — use output specs and presets for encoding configuration.
  5. Plan your keys upfront. Since metadata is immutable after creation, decide what you need to track before submitting jobs.