---
title: Content API and Fields
menu_group: REST API
menu_order: 10
tab: Content
tab_order: 10
summary: List, create, update, and delete MediaBlaster content with clean JSON field names.
---

# Content API and Fields

The content API manages Movies, Videos, Episodes, and Series using normalized JSON. Internal storage still uses `rovidx_smarttv_*` and `rovidx_smart_tv_*` meta keys; the REST layer maps those automatically.

## Endpoints

### Unified routes

| Method | Route | Description |
|--------|-------|-------------|
| GET | `/content` | Paginated collection |
| POST | `/content` | Create (requires `type` in body) |
| GET | `/content/{id}` | Single item |
| PATCH | `/content/{id}` | Partial update |
| DELETE | `/content/{id}` | Trash (or permanent with `?force=true`) |

### Type-specific aliases

Same behavior as `/content`, with `type` fixed by the URL:

| Type | List/create | Item |
|------|-------------|------|
| movies | `GET`, `POST` `/movies` | `GET`, `PATCH`, `DELETE` `/movies/{id}` |
| videos | `/videos` | `/videos/{id}` |
| episodes | `/episodes` | `/episodes/{id}` |
| series | `/series` | `/series/{id}` |

`POST /movies` creates a movie even if `type` is omitted from the JSON body.

If `{id}` exists but belongs to another post type, the API returns **404** `mediablaster_not_found`.

## List collection — query parameters

`GET /content` (or `GET /movies`, etc.)

| Parameter | Description |
|-----------|-------------|
| `type` | Filter: `movies`, `videos`, `episodes`, `series` |
| `status` | `publish`, `draft`, `pending`, `private`, or `any` (editors only) |
| `search` | WordPress search (`s`) |
| `genre` | Filter by genre meta |
| `tag` | Post tag slug or name |
| `series_id` | Episodes in a series playlist (`rovidx_smarttv_playlist`) |
| `page` | Page number (default `1`) |
| `per_page` | Items per page (default `20`, max `100`) |
| `orderby` | `date`, `modified`, `title`, `menu_order`, `rand` |
| `order` | `ASC` or `DESC` |
| `include_locked` | `true` to include items hidden with “hide completely” access |

**Public default:** only `publish` status. Logged-in users with `edit_posts` may request drafts or `status=any`.

### Collection response

```json
{
  "items": [ { "...content object..." } ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total": 124,
    "total_pages": 7
  }
}
```

## Create and update

### Defaults

- New content defaults to **`draft`**.
- Sending `"status": "publish"` requires `publish_posts` (or equivalent); otherwise **403**.
- **PATCH** only updates fields present in the body; omitted nested keys are not cleared.

### Minimal create example

`POST /wp-json/mediablaster/v3/movies`

```json
{
  "title": "REST Test Movie",
  "description": "Long description.",
  "excerpt": "Short description.",
  "media": {
    "url": "https://cdn.example.com/video.m3u8",
    "duration": 3600,
    "format": "HLS",
    "quality": "FHD"
  },
  "taxonomy": {
    "genres": ["documentary"],
    "rating": "PG",
    "tags": ["History", "Featured"]
  },
  "vimeo": {
    "source_url": "https://vimeo.com/123456789"
  }
}
```

### Partial update example

`PATCH /wp-json/mediablaster/v3/movies/123`

```json
{
  "title": "Updated Title",
  "media": {
    "quality": "UHD"
  }
}
```

Only `title` and `media.quality` change; existing URL and duration remain.

## Delete

`DELETE /content/{id}`

- Default: move to **trash** (`trashed: true`).
- `DELETE /content/{id}?force=true` — permanent delete (requires elevated delete capability).

Response includes `deleted`, `trashed`, and `previous` (serialized snapshot).

## Content object (response shape)

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | WordPress post ID |
| `type` | string | Post type slug |
| `status` | string | `draft`, `publish`, `pending`, `private` |
| `slug` | string | Post name |
| `title` | string | Post title |
| `description` | string | `post_content` |
| `excerpt` | string | `post_excerpt` |
| `created_at` | string | ISO 8601 (GMT) |
| `updated_at` | string | ISO 8601 (GMT) |
| `thumbnail` | object | `{ "id", "url" }` |
| `media` | object | See below |
| `taxonomy` | object | `tags`, `genres`, `rating` |
| `series` | object | Series linkage (episodes) or series meta |
| `captions` | array | Caption tracks |
| `trickplay` | array | Trickplay/BIF files |
| `ads` | object | Ad breaks |
| `availability` | object | Start/end dates |
| `access` | object | Subscription lock state |
| `vimeo` | object | `source_url` |
| `links` | object | `self`, `edit` (if allowed) |

### `media`

| Field | Allowed values | Notes |
|-------|----------------|-------|
| `url` | URI | Playback URL; `null` if user lacks access |
| `duration` | integer (seconds) | Accepts `hh:mm:ss` on write |
| `format` | `MP4`, `MOV`, `M4V`, `HLS`, `SMOOTH`, `DASH` | |
| `quality` | `SD`, `HD`, `FHD`, `UHD` | |

### `taxonomy`

| Field | Description |
|-------|-------------|
| `tags` | Post tag names |
| `genres` | Genre keys (multicheck values) |
| `rating` | Parental rating string |

### `series` (episodes)

| Field | Description |
|-------|-------------|
| `series_id` | Parent series post ID (derived from playlist membership) |
| `season_number` | Season number |
| `episode_number` | Episode number |

### `series` (series post type)

Additional fields on `type: series` responses: `type`, `release_date`, `playlist`, `thumbnail`, `thumbnail_id`, `genres`.

### `captions[]`

| Field | Description |
|-------|-------------|
| `url` | Caption file URL |
| `language` | Language code |
| `type` | e.g. `CLOSED_CAPTION`, `SUBTITLE` |

### `trickplay[]`

| Field | Description |
|-------|-------------|
| `url` | BIF or trickplay file URL |
| `quality` | Quality label |

### `ads`

| Field | Description |
|-------|-------------|
| `ad_breaks` | Array of break positions (seconds) |
| `custom_midroll_timer` | Custom midroll offset or `null` |

### `availability`

| Field | Description |
|-------|-------------|
| `start_date` | Availability start or `null` |
| `end_date` | Availability end or `null` |

### `access`

Present when subscriptions are enabled:

| Field | Description |
|-------|-------------|
| `is_locked` | Premium/locked for current user |
| `user_can_access` | Whether playback URL may be shown |
| `required_tier` | Tier object or `null` |
| `required_access_group` | Access group object or `null` |

### `vimeo`

| Field | Description |
|-------|-------------|
| `source_url` | Vimeo page URL (`rovidx_smart_tv_vm_pro_url`) |

### `links`

| Field | Description |
|-------|-------------|
| `self` | REST URL for this item |
| `edit` | wp-admin edit link (only if user can edit) |

## Request body field reference

Use these keys in **POST** and **PATCH** bodies (not raw meta names).

### Top-level

| API field | Required | Notes |
|-----------|----------|-------|
| `type` | On `POST /content` | One of four content types |
| `status` | No | Default `draft` |
| `title` | On create | |
| `description` | No | HTML allowed (sanitized) |
| `excerpt` | No | |
| `slug` | No | Post name |

### `media` object

| API field | Internal meta key |
|-----------|-------------------|
| `url` | `rovidx_smarttv_URL` |
| `duration` | `rovidx_smarttv_Duration` |
| `format` | `rovidx_smarttv_format` |
| `quality` | `rovidx_smarttv_quality` |

### `taxonomy` object

| API field | Storage |
|-----------|---------|
| `genres` | `rovidx_smarttv_genres` |
| `rating` | `rovidx_smarttv_rating` |
| `tags` | WordPress post tags |

### `series` object (episodes)

| API field | Internal meta key |
|-----------|-------------------|
| `season_number` | `rovidx_smarttv_se_no` |
| `episode_number` | `rovidx_smarttv_ep_no` |

### `series` object (series CPT)

| API field | Internal meta key |
|-----------|-------------------|
| `type` | `rovidx_smarttv_series_type` |
| `release_date` | `rovidx_smarttv_series_release_date` |
| `playlist` | `rovidx_smarttv_playlist` (array of post IDs) |
| `thumbnail` | `rovidx_smarttv_series_thumb` |
| `thumbnail_id` | `rovidx_smarttv_series_thumb_id` |
| `genres` | `rovidx_smarttv_series_genres` |

### `captions[]`

| API field | Internal key |
|-----------|--------------|
| `url` | `rovidx_smarttv_cc_uri` |
| `language` | `rovidx_smarttv_cc_lang` |
| `type` | `rovidx_smarttv_cc_type` |

Stored as CMB2 group `rovidx_smarttv_cc`.

### `trickplay[]`

| API field | Internal key |
|-----------|--------------|
| `url` | `rovidx_smarttv_bif_uri` |
| `quality` | `rovidx_smarttv_bif_def` |

Stored as group `rovidx_smarttv_bif`.

### `ads`

| API field | Internal meta key |
|-----------|-------------------|
| `ad_breaks` | `rovidx_smarttv_ad_breaks` |
| `custom_midroll_timer` | `rovidx_smarttv_custom_midroll_timer` |

### `availability`

| API field | Internal meta key |
|-----------|-------------------|
| `start_date` | `rovidx_smarttv_start_date` |
| `end_date` | `rovidx_smarttv_end_date` |

### `vimeo`

| API field | Internal meta key |
|-----------|-------------------|
| `source_url` | `rovidx_smart_tv_vm_pro_url` |

### `thumbnail`

| API field | Action |
|-----------|--------|
| `id` | Sets featured image attachment ID |

## Related guides

- [REST API Overview](rest-api-overview.md)
- [Video Data metabox](metabox-video-data.md) (admin UI for the same fields)
- [Vimeo REST API](rest-api-vimeo.md)
- [Metabox Subscription Access](metabox-subscription-access.md)
