Layers
Partner APIAPI referenceContent

GET /v1/content/:containerId

Read one content container - status, approval, hook, and generated assets.

View as Markdown
GET/v1/content/:containerId
Phase 1stable
Auth
Bearer
Scope
content:read

Returns the full container record: generation status, approval status, hook, caption, and the rendered media assets. Safe to call while a generation job is in-flight - fields that aren't populated yet are present as null or empty arrays. For live progress, prefer GET /v1/content/:containerId/progress or GET /v1/jobs/:jobId.

Path parameters

  • containerId
    string (cnt_uuid)required
    The container id β€” the `cnt_`-prefixed id returned by create/list (the bare uuid is also accepted).

Request

terminal
curl https://api.layers.com/v1/content/{containerId} \
  -H "Authorization: Bearer $LAYERS_API_KEY"
get-container.ts
const res = await fetch(
  `https://api.layers.com/v1/content/${containerId}`,
  { headers: { 'Authorization': `Bearer ${process.env.LAYERS_API_KEY}` } },
);
const container = await res.json();
get_container.py
import os, httpx

r = httpx.get(
    f"https://api.layers.com/v1/content/{container_id}",
    headers={"Authorization": f"Bearer {os.environ[\'LAYERS_API_KEY\']}"},
)
container = r.json()

Responses

200Full container record.
{
  "id": "cnt_7d18b9a1...",
  "projectId": "prj_01HX...",
  "status": "completed",
  "format": "ugc-remix",
  "hook": "wait for it...\nthis simple habit changed everything about my mindset 🧠",
  "influencerId": "inf_4a8e1bc2...",
  "sourceTiktokId": null,
  "mediaId": "med_01HZ...",
  "caption": "Thirty days, one run at a time…",
  "firstComment": null,
  "preview": {
    "kind": "video",
    "primaryUrl": "https://media.layers.com/.../ast_01HXZ9/video.mp4",
    "videoUrl": "https://media.layers.com/.../ast_01HXZ9/video.mp4",
    "thumbnailUrl": "https://media.layers.com/.../ast_01HXZ9/thumb.jpg",
    "hlsUrl": null,
    "durationMs": 9200,
    "aspectRatio": "9:16"
  },
  "assets": [
    {
      "assetId": "ast_01HXZ9...",
      "kind": "video",
      "url": "https://media.layers.com/.../ast_01HXZ9/video.mp4",
      "thumbnailUrl": "https://media.layers.com/.../ast_01HXZ9/thumb.jpg"
    }
  ],
  "approvalStatus": "approved",
  "creativeType": "generated",
  "adsEnrollment": "auto",
  "createdAt": "2026-04-17T13:10:00Z",
  "completedAt": "2026-04-17T13:14:22Z",
  "failedAt": null,
  "lastError": null
}
404Container not in this org.
{ "error": { "code": "NOT_FOUND", "message": "Container not found.", "requestId": "req_..." } }

Echo fields

The partner's creative inputs are echoed back on read so you can drive your own UI off a single GET without keeping a side-table.

FieldPopulates forNotes
hookslideshow-builder, ugc-remixThe literal string you sent on POST β€” line breaks and emoji round-trip exactly. null on remix formats (they adapt source overlays internally).
influencerIdevery format that took an influencerId or resolved one via a wired social accountPrefixed inf_<uuid>.
sourceTiktokIdvideo-remix, slideshow-remixThe raw TikTok id you sent. null on builder / ugc formats.
mediaIdugc-remix onlyPartner-uploaded app-demo source clip, prefixed med_<uuid>. null on every other format.

Origin fields

Every container carries two origin fields:

FieldValuesNotes
creativeTypegenerated | uploadedHow the container was filled. Uploaded content is partner- or user-supplied finished media; everything else is generated.
adsEnrollmentauto | opted_in | opted_outGenerated content is auto (legacy enrollment). Uploads are born opted_out and are not used in paid campaigns.

Uploaded containers additionally carry platformFit β€” computed per-platform fit from the probed media:

"platformFit": [
  { "platform": "tiktok", "ok": false, "issues": ["800x800 image resolution too low (min 1080px on the short edge)"] },
  { "platform": "instagram", "ok": false, "issues": ["800x800 image resolution too low (min 1080px on the short edge)"] }
]

platformFit is advisory; scheduling or publishing to an unfit platform returns 422 with the same issues. It is absent on generated containers (no probe metadata). On uploaded containers, format is null and hook is always null β€” hook is a generation-only field and never applies to uploaded media. See Upload finished content for the full semantics.

Container status

Container status
  • queued
    statusoptional
    Created, awaiting the generator.
  • processing
    statusoptional
    Generation in-flight. Assets populate on completion.
  • completed
    statusoptional
    Ready to approve and schedule.
  • failed
    statusoptional
    See `lastError.code` and `lastError.message`. Call generate again with a fresh `hook` to retry.
  • canceled
    statusoptional
    Workflow was canceled. Call generate again to try again.

Approval status

Approval status
  • not_required
    statusoptional
    Project policy does not require approval - content can be scheduled immediately.
  • pending
    statusoptional
    Default when the project requires approval. Blocks scheduling.
  • approved
    statusoptional
    Cleared for scheduling and publishing.
  • rejected
    statusoptional
    Blocked from scheduling. Call generate again with a fresh `hook` to try again.

Errors

CodeWhen
NOT_FOUNDContainer id not in this org.
FORBIDDEN_SCOPEKey lacks content:read.

The preview object

Every completed container carries a normalized preview object β€” the canonical "render this in my UI" surface. Render off preview, not off assets[] (which is the underlying file inventory). See Preview object for the per-kind field-population matrix.

FieldTypeNotes
kind"slideshow" | "video" | "image"Discriminator. Pick rendering mode off this.
primaryUrlstringThe first/hero URL β€” fine to drop directly into <img> or <video> based on kind.
thumbnailUrlstring | nullFirst slide for slideshows. For video kinds the poster-frame extraction is best-effort and may be null on a freshly completed container β€” render the videoUrl directly and let the browser produce a frame.
imageUrlsstring[]Populated when kind = "slideshow". Ordered.
videoUrlstringPopulated when kind = "video". Direct MP4 URL.
hlsUrlstring | nullAdaptive-bitrate HLS manifest. Returns null until the HLS pipeline ships.
durationMsinteger | nullVideo duration in milliseconds. null for slideshow/image kinds and on video kinds when probing didn't run (treat as informational; the asset is still playable).
aspectRatiostring"9:16" for verticals, "1:1" for squares, etc.

See also

On this page