# Short Drama API (`ezvidnet/short-drama-api`) Actor

Drama & short-drama catalogs from the Movies API Gateway. 40 providers (DramaWave, ReelShort, NetShort, DramaBox, ShortMax, FlexTV, iDrama, StardustTV2, CubeTV, MoboReel, GoodShort.....), one interface, cursor-paginated. Built for streaming sites, aggregators, and SEO pipelines.

- **URL**: https://apify.com/ezvidnet/short-drama-api.md
- **Developed by:** [Ezvid.Net](https://apify.com/ezvidnet) (community)
- **Categories:** Other, Videos, Social media
- **Stats:** 1 total users, 0 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Short Drama API Actor

Pulls drama, movie, and short-drama catalogs from the **Ezvid Movies API Gateway**
in a single, normalized interface. Built for streaming-site owners, content
aggregators, SEO pipelines, and anyone who needs structured drama data at scale.

### What it does

This Actor wraps the public [Ezvid Movies API](https://api.ezvid.net/docs) and
exposes it as an Apify Actor. It supports **15 upstream providers** behind one consistent input schema:

| Provider       | Best for                                       | Special actions |
| -------------- | ---------------------------------------------- | --------------- |
| DramaWave      | Long-form Chinese / Korean / Asian dramas       | `hot`           |
| ReelShort      | Vertical short dramas (English)                | —               |
| DramaBox       | Mobile-first short dramas                      | `latest`, `vip` |
| FlexTV         | Multi-region short dramas                      | `ranking`, `hot`|
| iDrama         | Classic Asian dramas                           | —               |
| StardustTV2    | Mixed catalog, anime & series                  | —               |
| CubeTV         | Anime & TV modules                             | —               |
| GoodShort      | Short dramas with channel discovery            | `channels`, `hot` |
| ShortMax       | ShortMax catalog                               | `ranking`       |
| NetShort       | NetShort catalog                               | —               |
| FlickReels     | FlickReels catalog                             | `trending`      |
| FreeReels      | FreeReels with rich for-you feed               | `foryou`, `hot`, `trending`, `categories` |
| StarShort      | Mobile dramas (uses `locale` not `language`)   | `latest`, `trending`, `recommended`, `watch` |
| DramaBite      | DramaBite with fresh m3u8 per episode           | `recommended`, `source` |
| GoldDrama      | GoldDrama catalog                              | `latest` (as `new`) |

#### Action reference

Every provider supports a **core set**: `home`, `search`, `detail`, `episodes`. Most also support `categories` / `channels`. The rest are provider-specific power-user actions.

Two specialized actions need **two** path params:

- `starshort` · `watch` → needs `id` (show) + `ep` (episode number)
- `dramabite` · `source` → needs `id` (drama) + `ep` (episode order) — returns a **fresh m3u8 URL** for one episode

Pagination is handled automatically via the upstream **opaque cursor** (default) or via `page=` (DramaBox's `/latest`). Set `maxPages` and the Actor will keep calling until the cursor is empty, the page counter exhausts, or the limit is hit.

#### Per-provider quirks

- **StarShort** uses `keyword` for search and `locale` for language instead of `q` / `language`. The Actor handles this automatically — you still pass `query` and `language` in input.
- **StarShort** has no `/home` — `home` maps to `/content/hot` (the closest equivalent).
- **DramaBite's** `source` action returns a single fresh m3u8 URL (not a list). Useful right before playback.
- **GoldDrama** has no `/langs` endpoint — the `language` input is silently ignored for this provider.

### Input

| Field        | Type    | Required | Notes                                                                 |
| ------------ | ------- | -------- | --------------------------------------------------------------------- |
| `provider`   | string  | ✅       | One of: `dramawave`, `reelshort`, `dramabox`, `flextv`, `idrama`, `stardusttv2`, `cubetv`, `goodshort`, `shortmax`, `netshort`, `flickreels`, `freereels`, `starshort`, `dramabite`, `golddrama` |
| `action`     | string  | ✅       | One of 15 actions (each provider supports a subset — see table above) |
| `query`      | string  | when `action=search` | Search keyword                                              |
| `id`         | string  | when `action=detail`/`episodes`/`watch`/`source` | Content ID — get it from a `home` or `search` run |
| `ep`         | string  | when `action=watch` or `source` | Episode number (1-based)                          |
| `language`   | string  |          | Provider-specific. StarShort → `locale`, others → `language` (see `/api/<provider>/langs` to list codes) |
| `category`   | string  |          | Optional category scope (provider-specific)                           |
| `page`       | integer |          | Used by DramaBox's `/latest` only. Ignored elsewhere.                 |
| `limit`      | integer |          | Page size, default 20, max 100                                        |
| `maxPages`   | integer |          | Pages of cursor pagination, default 1, max 50                         |
| `apiKey`     | string  |          | Your own Ezvid API key. **Leave blank** to use the Actor's built-in key (pay-per-result on Apify Store) |

### Output

Every result is pushed to the **default dataset** as a JSON object. Each
record is enriched with a `_meta` envelope:

```json
{
  "id": "tt_abc123",
  "title": "Sample Drama",
  "year": 2025,
  "episodes": 16,
  "poster": "https://cdn.ezvid.net/posters/abc123.jpg",
  "stream": "https://stream.ezvid.net/hls/abc123/master.m3u8",
  "_meta": {
    "provider": "dramawave",
    "action": "home",
    "page": 1,
    "url": "https://api.ezvid.net/api/dramawave/tabs?limit=20",
    "fetchedAt": "2026-08-10T03:55:01.123Z"
  }
}
```

A run summary is also written to the **OUTPUT key-value store** with counts
and timestamps.

### Quick examples

#### 1. Latest 100 titles from DramaBox (one page)

```json
{ "provider": "dramabox", "action": "home", "limit": 100, "maxPages": 1 }
```

#### 2. Search DramaWave for "revenge"

```json
{ "provider": "dramawave", "action": "search", "query": "revenge", "limit": 50 }
```

#### 3. Get a fresh m3u8 for a single DramaBite episode

```json
{ "provider": "dramabite", "action": "source", "id": "drama_abc123", "ep": "5" }
```

#### 4. Watch metadata for a StarShort episode

```json
{ "provider": "starshort", "action": "watch", "id": "show_xyz", "ep": "12", "language": "id" }
```

#### 5. Crawl a full category across 10 pages

```json
{ "provider": "goodshort", "action": "home", "category": "romance", "limit": 50, "maxPages": 10 }
```

#### 6. StarShort "For You" — pass `query` is not needed, but the upstream requires `locale`

```json
{ "provider": "starshort", "action": "recommended", "language": "id" }
```

### Authentication

The Actor calls Ezvid's API with an `X-API-Key` header.

- **Free users** can paste their own Ezvid API key into the `apiKey` input.
- **Pay-per-result users** leave the field empty — the Actor uses an embedded
  key from its `EZVID_API_KEY` secret. Configure that secret in the Actor's
  **Settings → Environment variables** when you publish it on Apify Store.

### Local development

Requirements: Node 18+, [Apify CLI](https://docs.apify.com/cli).

```bash
## Install deps
npm install

## Run locally (uses input from storage/key_value_store/INPUT.json)
EZVID_API_KEY=your_key npm start
```

### Deploying to Apify Store

```bash
## 1. Login (one-time)
apify login

## 2. Push — the CLI auto-creates the Actor on the platform
##    using the name from .actor/actor.json ("short-drama-api")
apify push

## 3. In the Apify Console (https://console.apify.com):
##    - Open the new Actor "short-drama-api"
##    - Settings → Environment variables → add EZVID_API_KEY=<your master key>
##    - (Optional) Secrets → same value via secret reference
##    - Publication → "Publish" → fill the public listing from this README
```

> ⚠️ The CLI has no `apify actors create` command. `apify push` is the
> command that both creates the Actor (if it doesn't exist) and uploads
> the source code. The Actor's name is read from `.actor/actor.json`.

### Pricing strategy (suggestion)

On Apify Store you can set **pay-per-event** pricing so users pay only for
records they actually pull:

| Event           | Suggested price |
| --------------- | --------------- |
| Actor start     | $0.001          |
| Record returned | $0.0005 – 0.002 |

This way your upstream cost (`/api/dramawave/*` calls) is covered and you
keep a margin. The built-in key is billed to the Actor, not to the end user.

### Limits & caveats

- Upstream API may rate-limit; this Actor uses Apify's default retries but
  if you hit a 429, lower `maxPages` or run in smaller batches.
- The Ezvid API is not affiliated with the upstream drama providers — make
  sure your use case complies with their terms.
- The Actor does not stream video; it returns metadata + HLS URLs. The end
  user (or your downstream system) is responsible for the actual playback.

### License

MIT — do whatever you want, just don't blame us if upstream breaks.

# Actor input Schema

## `provider` (type: `string`):

Which upstream provider to query.

## `action` (type: `string`):

What to do with the provider. 'search' requires `query`, 'detail'/'episodes' require `id`, 'source'/'watch' require `id` + `ep`. Each provider supports a subset of these — invalid combos throw a clear error.

## `query` (type: `string`):

Required when action = 'search'. (StarShort uses 'keyword' under the hood, but you always pass this field.)

## `id` (type: `string`):

Required when action = 'detail', 'episodes', 'watch', or 'source'. Get IDs from a 'home' or 'search' run.

## `ep` (type: `string`):

Required when action = 'watch' (StarShort) or 'source' (DramaBite). The 1-based episode position.

## `language` (type: `string`):

Provider-specific. StarShort uses 'locale' (e.g. 'id', 'en'); all others use 'language' (see /api/<provider>/langs for codes).

## `category` (type: `string`):

Optional category to scope the list (provider-specific).

## `page` (type: `integer`):

Used by DramaBox's /latest endpoint instead of cursor. Ignored elsewhere.

## `limit` (type: `integer`):

Results per page. Upstream may cap.

## `maxPages` (type: `integer`):

How many pages to walk. 1 = single page only. Cursor-paginated endpoints follow the cursor until exhausted or this limit; page-based endpoints (e.g. /latest) increment `page`.

## `apiKey` (type: `string`):

Leave blank to use the Actor's built-in key (pay-per-result on Apify Store). If you have your own Ezvid API key, paste it here to use it for free.

## Actor input object example

```json
{
  "provider": "dramawave",
  "action": "home",
  "page": 1,
  "limit": 20,
  "maxPages": 1
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "provider": "dramawave",
    "action": "home",
    "page": 1,
    "limit": 20,
    "maxPages": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("ezvidnet/short-drama-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "provider": "dramawave",
    "action": "home",
    "page": 1,
    "limit": 20,
    "maxPages": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("ezvidnet/short-drama-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "provider": "dramawave",
  "action": "home",
  "page": 1,
  "limit": 20,
  "maxPages": 1
}' |
apify call ezvidnet/short-drama-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ezvidnet/short-drama-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/q4Bs4iFsMJwTOV2jH/builds/SyZl2CMRpYqfrzUbf/openapi.json
