---
title: "Get a VOD"
description: "Fetches a single VOD entry (movie or series episode) by its numeric id. Returns the same shape as one item in the /vods listing."
---

# Get a VOD

Fetches one VOD entry by its numeric id. The response has the same shape as an item in [List VODs](/docs/?page=xai-ref-catalog-vods), so any code that already renders entries from the list endpoint can render the single item response without changes.

Both admin and reseller keys can call this endpoint on any VOD id. Series episodes and movies share the same id space; use the `is_serie` flag on the response to route the row to the right UI treatment. The metadata subset (`year`, `rating`, `icon`) comes from the panel's local TMDB cache.

## Endpoint

`GET https://<your-panel-domain>/panel-api/v1/vods/{id}`

## Authentication

Bearer token in the `Authorization` header. See [Authentication](/docs/?page=panel-api-authentication).

## Required scope

`vods:read`.

## Path parameters

| Name | Type | Description |
| ---- | ---- | ----------- |
| `id` | int | Numeric VOD id. |

## Response

| Field | Type | Description |
| ----- | ---- | ----------- |
| `id` | int | Numeric VOD id. |
| `name` | string | Entry display name. |
| `icon` | string | Poster URL (`cover_big` from TMDB). Empty string when the entry has no poster. |
| `year` | int or null | Release year, derived from the release date in the TMDB cache. `null` when the panel has no release date for the entry. |
| `rating` | float or null | TMDB rating on a 0.0 to 10.0 scale. `null` when not available. |
| `is_serie` | bool | `true` for series episodes, `false` for movies. |
| `categories` | array | List of `{id, name}` objects. An entry can belong to more than one category. |

Example response for a movie with categories.

```json
{
  "id": 109898,
  "name": "Movie 42 (1999)",
  "icon": "https://cdn.example.com/posters/movie-42.jpg",
  "year": 1999,
  "rating": 8,
  "is_serie": false,
  "categories": [
    {"id": 44, "name": "Franchise Films"}
  ]
}
```

If the entry does not exist, the server returns `404 not_found`.

```json
{
  "error": "not_found",
  "message": "VOD not found",
  "request_id": "6afd09a9-3128-40e9-99d6-bd8ea03f6154"
}
```

## Examples

### cURL

```bash
curl -H "Authorization: Bearer <your-api-key>" \
     https://<your-panel-domain>/panel-api/v1/vods/109898
```

### PHP SDK

```php
require __DIR__ . '/api-panel-php-sdk-1.0.0/autoload.php';
use XtreamAI\PanelApi\PanelApiClient;
use XtreamAI\PanelApi\Exceptions\NotFoundException;

$client = new PanelApiClient(baseUrl: 'https://<your-panel-domain>', token: '<your-api-key>');

try {
    $vod = $client->catalog->vod(109898);
    echo $vod->name, ' (', ($vod->year ?? 'unknown'), ")\n";
} catch (NotFoundException $e) {
    echo "vod not found\n";
}
```

### Python SDK

```python
from xtream_ai_panel_api import PanelApiClient
from xtream_ai_panel_api.exceptions import NotFoundException

client = PanelApiClient(base_url="https://<your-panel-domain>", token="<your-api-key>")

try:
    vod = client.catalog.vod(109898)
    print(vod.name, vod.year)
except NotFoundException:
    print("vod not found")
```

> [!NOTE]
> VOD metadata is enriched automatically from the panel's local TMDB cache. It is read-only over the Panel API. There is no endpoint to trigger a metadata refresh; that is a panel admin action performed from the CMS. If the metadata looks stale, ask the panel operator.

## Errors

| HTTP | Error slug | When it happens | How to fix |
| ---- | ---------- | --------------- | ---------- |
| 401 | `invalid_key` | The `Authorization` header is missing, malformed, or names a key that does not exist. | Check the header. See [Authentication](/docs/?page=panel-api-authentication). |
| 403 | `insufficient_scope` | The key does not carry `vods:read`. | Regenerate the key with `vods:read` in its scope list, or use a key that has it. |
| 404 | `not_found` | No VOD exists with the given `id`. | Verify the id. Ids are stable, so a persistent 404 means the entry was deleted from the panel. |
| 429 | `rate_limited` | The per key rate limit has been exceeded. Response carries `Retry-After: 60` and `X-RateLimit-*` headers. | Back off for the number of seconds in `Retry-After` and retry. |

## See also

- [List VODs](/docs/?page=xai-ref-catalog-vods)
- [Get a live stream](/docs/?page=xai-ref-catalog-stream)
- [Catalog overview](/docs/?page=xai-ref-overview)
