The Origin object
Origins are storage locations for video inputs and transcoded outputs. Transcodely supports Google Cloud Storage, Amazon S3, Cloudflare R2, and HTTP/HTTPS endpoints. Credentials are validated at creation and stored encrypted.
Base path: transcodely.v1.OriginService Requires: X-Organization-ID header on all endpoints.
Attributes
| Attribute | Type | Description |
|---|---|---|
id | string | Unique identifier with ori_ prefix (e.g., "ori_x9y8z7w6v5"). |
app_id | string | ID of the parent app that owns this origin (e.g., "app_k1l2m3n4o5"). Server-set. |
name | string | Human-readable name. |
description | string | Optional description. |
provider | string | Storage provider. One of "gcs", "s3", "r2", "http", or "transcodely" (system-managed, read-only). |
permissions | string[] | Declared permissions: "read" and/or "write". |
status | string | Current status. One of "active", "failed", "archived". |
base_path | string | Base path prefix within the bucket (e.g., "videos/uploads/"). |
path_template | string | Output path template with {variable} tokens (e.g., "{date}/{job_id}/{codec}_{resolution}"). Supported tokens — core: {job_id}, {video_id}, {timestamp}, {date}, {uuid}; output: {output_id}, {output_index}, {preset_id}, {codec}, {resolution}, {bitrate}, {format} (alias {type}), {framerate}, {quality}; segment (HLS/DASH): {segment_index}, {segment_number}, {segment_time}; thumbnail: {thumb_index}, {thumb_time}, {thumb_time_ms}. Must include at least one of {job_id}, {output_id}, {video_id}, or {uuid} so concurrent jobs sharing the origin can’t collide. |
gcs | object | GCS configuration, present when provider is "gcs". Contains bucket. Credentials are never included. |
s3 | object | S3 configuration, present when provider is "s3". Contains bucket, region, and optional endpoint. Credentials are never included. |
http | object | HTTP configuration, present when provider is "http". Contains base_url. Credentials are never included. |
r2 | object | Cloudflare R2 configuration, present when provider is "r2". Contains bucket, account_id or endpoint, and jurisdiction. Credentials are never included. |
last_validated_at | string | ISO 8601 timestamp of last successful validation. Omitted if never validated. |
validation_error | string | Error from last failed validation. Omitted if status is not "failed". |
created_at | string | ISO 8601 timestamp. |
updated_at | string | ISO 8601 timestamp. |
archived_at | string | ISO 8601 timestamp. Omitted if not archived. |
is_managed | boolean | true for Transcodely-managed origins (auto-created during hosting provisioning). Managed origins cannot be modified or archived. |
{
"id": "ori_x9y8z7w6v5",
"name": "Production GCS Bucket",
"description": "Main storage for video assets",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "active",
"base_path": "videos/",
"path_template": "{date}/{job_id}/{codec}_{resolution}",
"gcs": { "bucket": "acme-video-assets" },
"last_validated_at": "2025-01-15T10:30:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}Providers
| Provider | Read | Write | Authentication |
|---|---|---|---|
gcs | Yes | Yes | Service account JSON key. |
s3 | Yes | Yes | Access key ID and secret. AWS S3 or any S3-compatible service (Hetzner Object Storage, Wasabi, DigitalOcean Spaces, MinIO, Backblaze B2) via a custom endpoint. |
r2 | Yes | Yes | R2 access key ID and secret. Account ID derives the endpoint, or supply a custom endpoint. |
http | Yes | No | Optional custom headers. |
transcodely | — | — | System-managed. Auto-created for hosting-enabled apps and returned by Get/List; read-only — cannot be created, modified, or archived via the API. |
The ValidationResult object
Returned when credentials are validated, either at creation, after credential rotation, or via the Validate endpoint.
| Attribute | Type | Description |
|---|---|---|
success | boolean | Whether all declared permissions were validated. |
can_read | boolean | Whether read permission was validated. |
can_write | boolean | Whether write permission was validated. |
read_error | string | Error message if read validation failed. |
write_error | string | Error message if write validation failed. |
validated_at | string | ISO 8601 timestamp. |
Create an origin
Create a new storage origin. Credentials are validated at creation time and must pass before the origin is stored.
POST /transcodely.v1.OriginService/CreateParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable name (1-255 chars). |
description | string | No | Description (max 1000 chars). |
permissions | string[] | Yes | Declared permissions: "read" and/or "write". At least one required. HTTP origins only support "read". |
base_path | string | No | Base path prefix within the bucket (max 1024 chars). |
path_template | string | No | Output path template (max 1024 chars). Supports the same {variable} tokens as the path_template attribute above. |
gcs | object | One of | GCS provider configuration. Exactly one of gcs, s3, or http must be provided. |
gcs.bucket | string | Yes | GCS bucket name (e.g., "my-video-bucket"). |
gcs.credentials | object | Yes | GCS credentials. |
gcs.credentials.service_account_json | string | Yes | Full JSON content of the service account key file. |
s3 | object | One of | S3 provider configuration. |
s3.bucket | string | Yes | S3 bucket name. |
s3.region | string | Yes | Region (e.g., "us-east-1", or "fsn1" for Hetzner). Required even with a custom endpoint — the AWS SDK needs it for request signing. |
s3.credentials | object | Yes | S3 credentials. |
s3.credentials.access_key_id | string | Yes | Access key ID. |
s3.credentials.secret_access_key | string | Yes | Secret access key. |
s3.endpoint | string | No | Optional S3-compatible endpoint (e.g., "https://fsn1.your-objectstorage.com"). When set, Transcodely uses path-style addressing against this host instead of AWS. Omit for AWS S3. Must be a valid URI, max 256 chars. |
r2 | object | One of | Cloudflare R2 provider configuration. |
r2.bucket | string | Yes | R2 bucket name (3-63 chars, must match ^[a-z0-9][a-z0-9.-]*[a-z0-9]$). |
r2.account_id | string | One of | Cloudflare account ID (must match ^[a-f0-9]{32}$). Exactly one of account_id or endpoint must be set. |
r2.jurisdiction | string | No | Data residency. One of "default", "eu", "fedramp". Only valid when account_id is set; ignored when endpoint is supplied. |
r2.endpoint | string | One of | Explicit endpoint URL for custom domains or jurisdictions not enumerated above. Must be a valid URI, max 256 chars. Mutually exclusive with account_id. |
r2.credentials | object | Yes | R2 credentials (S3-compatible). |
r2.credentials.access_key_id | string | Yes | R2 access key ID. |
r2.credentials.secret_access_key | string | Yes | R2 secret access key. |
http | object | One of | HTTP provider configuration (read-only). |
http.base_url | string | Yes | Base URL (e.g., "https://cdn.example.com/videos/"). |
http.credentials | object | No | Optional authentication headers. |
http.credentials.headers | object | No | Key-value map of custom headers (max 20 pairs). |
app_id | string | No | Target app (app_...). Portal/JWT callers pass it to create the origin in a specific app in their org (omit to use the org’s first active app); API-key callers may omit it (the key’s app is used) or pass their own app — a different app is rejected. |
Returns
The Origin object and a ValidationResult confirming the credential check.
The
originandvalidationfields are both returned only on the raw Connect/JSON (curl) response. The JS, Python, and Go SDKcreate()methods return just the Origin — inspect itsstatus/validation_error, or call Validate separately for the fullcan_read/can_writebreakdown.
Example: GCS origin
Creates a read/write GCS origin from a bucket name and an inline service account JSON key, with base_path and path_template shaping where outputs land.
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Create
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{
"name": "Production GCS Bucket",
"description": "Main storage for video assets",
"permissions": ["read", "write"],
"base_path": "videos/",
"path_template": "{date}/{job_id}/{codec}_{resolution}",
"gcs": {
"bucket": "acme-video-assets",
"credentials": {
"service_account_json": "{...}"
}
}
}'const origin = await client.origins.create({
name: "Production GCS Bucket",
description: "Main storage for video assets",
permissions: [OriginPermission.READ, OriginPermission.WRITE],
basePath: "videos/",
pathTemplate: "{date}/{job_id}/{codec}_{resolution}",
gcs: {
bucket: "acme-video-assets",
credentials: {
serviceAccountJson: "{...}",
},
},
});origin = client.origins.create(
name="Production GCS Bucket",
description="Main storage for video assets",
permissions=["read", "write"],
base_path="videos/",
path_template="{date}/{job_id}/{codec}_{resolution}",
gcs={
"bucket": "acme-video-assets",
"credentials": {
"service_account_json": "{...}",
},
},
)origin, err := client.Origins.Create(ctx, &transcodely.OriginCreateParams{
Name: "Production GCS Bucket",
Description: "Main storage for video assets",
Permissions: []transcodely.OriginPermission{transcodely.OriginPermissionRead, transcodely.OriginPermissionWrite},
BasePath: "videos/",
PathTemplate: "{date}/{job_id}/{codec}_{resolution}",
Gcs: &transcodely.GcsOriginConfig{
Bucket: "acme-video-assets",
Credentials: &transcodely.GcsCredentials{
ServiceAccountJson: "{...}",
},
},
}){
"origin": {
"id": "ori_x9y8z7w6v5",
"name": "Production GCS Bucket",
"description": "Main storage for video assets",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "active",
"base_path": "videos/",
"path_template": "{date}/{job_id}/{codec}_{resolution}",
"gcs": { "bucket": "acme-video-assets" },
"last_validated_at": "2025-01-15T10:30:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
"validation": {
"success": true,
"can_read": true,
"can_write": true,
"read_error": "",
"write_error": "",
"validated_at": "2025-01-15T10:30:00Z"
}
}Example: S3 origin
A write-only AWS S3 origin authenticated with an access key ID and secret. region is required even when no custom endpoint is set, since the AWS SDK needs it for request signing.
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Create
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{
"name": "AWS S3 Output Bucket",
"permissions": ["write"],
"s3": {
"bucket": "acme-transcoded-output",
"region": "us-east-1",
"credentials": {
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}
}'const origin = await client.origins.create({
name: "AWS S3 Output Bucket",
permissions: [OriginPermission.WRITE],
s3: {
bucket: "acme-transcoded-output",
region: "us-east-1",
credentials: {
accessKeyId: "AKIAIOSFODNN7EXAMPLE",
secretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
},
},
});origin = client.origins.create(
name="AWS S3 Output Bucket",
permissions=["write"],
s3={
"bucket": "acme-transcoded-output",
"region": "us-east-1",
"credentials": {
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
},
},
)origin, err := client.Origins.Create(ctx, &transcodely.OriginCreateParams{
Name: "AWS S3 Output Bucket",
Permissions: []transcodely.OriginPermission{transcodely.OriginPermissionWrite},
S3: &transcodely.S3OriginConfig{
Bucket: "acme-transcoded-output",
Region: "us-east-1",
Credentials: &transcodely.S3Credentials{
AccessKeyId: "AKIAIOSFODNN7EXAMPLE",
SecretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
},
},
})Example: Cloudflare R2 origin
The recommended form supplies an account_id and lets us derive the endpoint.
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Create
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{
"name": "Cloudflare R2 Outputs",
"permissions": ["read", "write"],
"r2": {
"bucket": "acme-transcoded-outputs",
"account_id": "f037e1abcd0987654321fedcba012345",
"credentials": {
"access_key_id": "...",
"secret_access_key": "..."
}
}
}'const origin = await client.origins.create({
name: "Cloudflare R2 Outputs",
permissions: [OriginPermission.READ, OriginPermission.WRITE],
r2: {
bucket: "acme-transcoded-outputs",
accountId: "f037e1abcd0987654321fedcba012345",
jurisdiction: R2Jurisdiction.DEFAULT, // or EU, FEDRAMP
credentials: {
accessKeyId: "...",
secretAccessKey: "...",
},
},
});origin = client.origins.create(
name="Cloudflare R2 Outputs",
permissions=["read", "write"],
r2={
"bucket": "acme-transcoded-outputs",
"account_id": "f037e1abcd0987654321fedcba012345",
"jurisdiction": "default", # or "eu", "fedramp"
"credentials": {
"access_key_id": "...",
"secret_access_key": "...",
},
},
)origin, err := client.Origins.Create(ctx, &transcodely.OriginCreateParams{
Name: "Cloudflare R2 Outputs",
Permissions: []transcodely.OriginPermission{transcodely.OriginPermissionRead, transcodely.OriginPermissionWrite},
R2: &transcodely.R2OriginConfig{
Bucket: "acme-transcoded-outputs",
AccountId: "f037e1abcd0987654321fedcba012345",
Jurisdiction: transcodely.R2JurisdictionDefault, // or EU, FedRAMP
Credentials: &transcodely.S3Credentials{
AccessKeyId: "...",
SecretAccessKey: "...",
},
},
})For custom domains or non-standard regions, supply an explicit endpoint (e.g. https://media.example.com) in place of account_id — see r2.endpoint above. Exactly one of the two must be set.
Retrieve an origin
Retrieve an origin by ID. Credentials are never included in responses.
POST /transcodely.v1.OriginService/GetParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Origin ID (e.g., "ori_x9y8z7w6v5"). |
Returns
The Origin object.
Example
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Get
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{"id": "ori_x9y8z7w6v5"}'const origin = await client.origins.get("ori_x9y8z7w6v5");origin = client.origins.get("ori_x9y8z7w6v5")origin, err := client.Origins.Get(ctx, "ori_x9y8z7w6v5"){
"origin": {
"id": "ori_x9y8z7w6v5",
"name": "Production GCS Bucket",
"description": "Main storage for video assets",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "active",
"base_path": "videos/",
"path_template": "{date}/{job_id}/{codec}_{resolution}",
"gcs": { "bucket": "acme-video-assets" },
"last_validated_at": "2025-01-15T10:30:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}List origins
List origins with optional filtering by provider, status, and permission.
POST /transcodely.v1.OriginService/ListParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
provider | string | No | Filter by provider: "gcs", "s3", "r2", "http", or "transcodely". |
status | string | No | Filter by status: "active", "failed", or "archived". |
permission | string | No | Filter by permission: "read" or "write". |
include_archived | boolean | No | Include archived origins. Default: false. |
pagination | object | No | Pagination parameters. See Pagination. |
app_id | string | No | Filter to a single app (app_...). Portal/JWT callers pass it to scope the list to one app (omit to return origins across all apps in the org); API-key callers may omit it (the key’s app is used) or pass their own app. |
Returns
A list of Origin objects and pagination metadata.
Example
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/List
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{
"provider": "gcs",
"permission": "write",
"pagination": {"limit": 20}
}'for await (const origin of client.origins.list({
provider: OriginProvider.GCS,
permission: OriginPermission.WRITE,
pagination: { limit: 20 },
}).autoPage()) {
console.log(origin.id, origin.provider);
}for origin in client.origins.list(limit=20).auto_paging_iter():
print(origin.id, origin.provider)iter := client.Origins.List(ctx, &transcodely.OriginListParams{
Provider: transcodely.OriginProviderGCS.Enum(),
Permission: transcodely.OriginPermissionWrite.Enum(),
Pagination: &transcodely.PaginationRequest{Limit: 20},
})
for iter.Next() {
origin := iter.Current()
fmt.Println(origin.GetId(), origin.GetProvider())
}
if err := iter.Err(); err != nil {
log.Fatal(err)
}{
"origins": [
{
"id": "ori_x9y8z7w6v5",
"name": "Production GCS Bucket",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "active",
"base_path": "videos/",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
],
"pagination": {
"next_cursor": "",
"total_count": 1
}
}Python SDK:
client.origins.list()currently accepts onlylimit(pagination) and does not support theprovider,status,permission,include_archived, orapp_idfilters. Filter client-side, or use the Go/JS SDKs or the raw API for server-side filtering.
Update an origin
Update an origin’s metadata and optionally rotate credentials. If credentials are provided, validation runs automatically. Transcodely-managed origins (is_managed: true) cannot be updated.
POST /transcodely.v1.OriginService/UpdateParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Origin ID. |
name | string | No | New name (1-255 chars). |
description | string | No | New description (max 1000 chars). |
base_path | string | No | New base path (max 1024 chars). |
path_template | string | No | New path template (max 1024 chars). |
gcs_credentials | object | No | Updated GCS credentials. Triggers validation. |
s3_credentials | object | No | Updated S3 credentials. Triggers validation. |
r2_credentials | object | No | Updated R2 credentials (same shape as S3). Triggers validation. |
http_credentials | object | No | Updated HTTP credentials. Triggers validation. |
Returns
The updated Origin object. The raw Connect/JSON (curl) response also includes a ValidationResult when credentials were rotated. The JS, Python, and Go SDK update() methods return only the Origin — call Validate separately for the can_read/can_write breakdown.
Example
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Update
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{
"id": "ori_x9y8z7w6v5",
"name": "Production GCS (Updated)",
"path_template": "{job_id}/{output_id}"
}'const origin = await client.origins.update({
id: "ori_x9y8z7w6v5",
name: "Production GCS (Updated)",
pathTemplate: "{job_id}/{output_id}",
});origin = client.origins.update(
id="ori_x9y8z7w6v5",
name="Production GCS (Updated)",
path_template="{job_id}/{output_id}",
)origin, err := client.Origins.Update(ctx, &transcodely.OriginUpdateParams{
Id: "ori_x9y8z7w6v5",
Name: proto.String("Production GCS (Updated)"),
PathTemplate: proto.String("{job_id}/{output_id}"),
}){
"origin": {
"id": "ori_x9y8z7w6v5",
"name": "Production GCS (Updated)",
"description": "Main storage for video assets",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "active",
"base_path": "videos/",
"path_template": "{job_id}/{output_id}",
"gcs": { "bucket": "acme-video-assets" },
"last_validated_at": "2025-01-15T10:30:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-02-28T15:00:00Z"
}
}Validate an origin
Re-validate an origin’s credentials and permissions. Use this to check for permission drift after IAM policy changes.
POST /transcodely.v1.OriginService/ValidateParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Origin ID. |
Returns
The Origin object (status may change to "active" or "failed") and a ValidationResult.
Example
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Validate
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{"id": "ori_x9y8z7w6v5"}'const result = await client.origins.validate({ id: "ori_x9y8z7w6v5" });
console.log(result.validation?.success, result.validation?.canWrite);result = client.origins.validate(id="ori_x9y8z7w6v5")
print(result.validation.success, result.validation.can_write)validation, err := client.Origins.Validate(ctx, "ori_x9y8z7w6v5")
fmt.Println(validation.GetSuccess(), validation.GetCanWrite()){
"origin": {
"id": "ori_x9y8z7w6v5",
"name": "Production GCS Bucket",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "active",
"last_validated_at": "2025-02-28T15:00:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-02-28T15:00:00Z"
},
"validation": {
"success": true,
"can_read": true,
"can_write": true,
"read_error": "",
"write_error": "",
"validated_at": "2025-02-28T15:00:00Z"
}
}Archive an origin
Soft-delete an origin. Archived origins cannot be used for new jobs, but existing job data is preserved. Transcodely-managed origins (is_managed: true) cannot be archived.
POST /transcodely.v1.OriginService/ArchiveParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Origin ID. |
Returns
The archived Origin object with status: "archived".
Example
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Archive
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-H "Content-Type: application/json"
-d '{"id": "ori_x9y8z7w6v5"}'const origin = await client.origins.archive("ori_x9y8z7w6v5");origin = client.origins.archive("ori_x9y8z7w6v5")err := client.Origins.Archive(ctx, "ori_x9y8z7w6v5"){
"origin": {
"id": "ori_x9y8z7w6v5",
"name": "Production GCS Bucket",
"provider": "gcs",
"permissions": ["read", "write"],
"status": "archived",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-02-28T15:00:00Z",
"archived_at": "2025-02-28T15:00:00Z"
}
}