# GET /v1/content/:containerId/assets/:assetId (/docs/api/reference/content/get-asset)



<Endpoint method="GET" path="/v1/content/:containerId/assets/:assetId" scope="content:read" phase="1" />

Returns the asset descriptor for a single media file on the container: the public CDN URL, kind, and any per-asset metadata (`width`, `height`, `durationMs`, `mimeType`, `sizeBytes`).

URLs are durable, not short-lived signatures, so it's safe to embed them in your own UI for the lifetime of the container. They do go away when the container is deleted, so always serve from the current container state rather than caching the URL itself.

The `assets` array on [`GET /v1/content/:containerId`](/docs/api/reference/content/get-container) carries the same shape as the body below. This endpoint exists for direct asset addressing (e.g. you have an `assetId` from `primaryAsset` and don't want to re-pull the whole container).

## Path parameters [#path-parameters]

<Parameters
  rows="[
  { name: 'containerId', type: 'string', required: true, description: 'The container id (UUID; both raw and `cnt_<id>` accepted).' },
  { name: 'assetId', type: 'string', required: true, description: 'The asset id, taken from `container.assets[].assetId` or `primaryAsset.assetId`. Treat it as opaque.' },
]"
/>

## Request [#request]

<Tabs items="['curl', 'TypeScript', 'Python']">
  <Tab value="curl">
    ```sh title="terminal"
    curl https://api.layers.com/v1/content/{containerId}/assets/{assetId} \
      -H "Authorization: Bearer $LAYERS_API_KEY"
    ```
  </Tab>

  <Tab value="TypeScript">
    ```ts title="get-asset.ts"
    const res = await fetch(
      `https://api.layers.com/v1/content/${containerId}/assets/${assetId}`,
      { headers: { 'Authorization': `Bearer ${process.env.LAYERS_API_KEY}` } },
    );
    const { url, mimeType, expiresAt } = await res.json();
    ```
  </Tab>

  <Tab value="Python">
    ```py title="get_asset.py"
    import os, httpx

    r = httpx.get(
        f"https://api.layers.com/v1/content/{container_id}/assets/{asset_id}",
        headers={"Authorization": f"Bearer {os.environ[\'LAYERS_API_KEY\']}"},
    )
    asset = r.json()
    ```
  </Tab>
</Tabs>

## Responses [#responses]

<Response status="200" description="Asset descriptor with public CDN URL.">
  ```json
  {
    "containerId": "cnt_7d18b9a1...",
    "assetId": "video-9c855048-b470-42e7-8f1b-032324d48555",
    "kind": "video",
    "url": "https://media.layers.com/public-media/content-container/.../media/video-9c855048-b470-42e7-8f1b-032324d48555.mp4",
    "thumbnailUrl": null
  }
  ```

  Optional fields are typically present on newer containers and may be absent on legacy data:

  ```json
  {
    "mimeType": "video/mp4",
    "sizeBytes": 1843200,
    "durationMs": 9200,
    "width": 1080,
    "height": 1920,
    "checksumSha256": "e3b0c44298fc1c...",
    "expiresAt": "2026-04-18T10:45:00Z"
  }
  ```
</Response>

<Response status="404" description="Asset not found on this container.">
  ```json
  {
    "error": {
      "code": "NOT_FOUND",
      "message": "Asset not on this container.",
      "requestId": "req_..."
    }
  }
  ```
</Response>

## Notes [#notes]

<Callout type="info">
  URLs are durable, not pre-signed. They're stable CDN paths - fine to
  embed in your UI or pass to a video player without `expiresAt` bookkeeping.
  When `expiresAt` is included, honor it. Otherwise treat the URL as valid
  until the asset is replaced or the container is deleted.
</Callout>

* **`checksumSha256` is stable across re-fetches when present.** Use it to dedupe downloads or verify integrity after upload to a third-party CDN. Not all rows carry it - older containers may omit the field.

## Errors [#errors]

| Code              | When                                                          |
| ----------------- | ------------------------------------------------------------- |
| `NOT_FOUND`       | Asset id not on this container, or container not in this org. |
| `FORBIDDEN_SCOPE` | Key lacks `content:read`.                                     |

## See also [#see-also]

* [Read the container](/docs/api/reference/content/get-container)
* [Generate a new container](/docs/api/reference/content/slideshow-builder)
