---
title: "The /api/v1 API for pipelines"
url: https://phatdev.net/en/docs/media-studio/api-v1
lang: en
updated: 2026-10-20
alternate:
  vi: https://phatdev.net/docs/media-studio/api-v1
markdown: https://phatdev.net/en/docs/media-studio/api-v1.md
---

# The /api/v1 API for pipelines

Part of the doc set: [Media Studio](https://phatdev.net/en/docs/media-studio.md)

> Key authentication, background jobs, idempotency, the x-engine header, the endpoint list and error codes.

Every Media Studio feature can be called through the REST API - this is how an article pipeline fetches its own images, banners, charts and videos.

## Authentication

- Create a key under **Cài đặt → API keys** (Settings → API keys), one key per service. Send the header `x-api-token: <key>`.
- **Fail-closed**: if no key has been created yet, the API is **locked**, not open.
- No key needed for: `GET /api/v1/info`, `/api/v1/openapi.json`, `/api/v1/docs`, `/api/v1/health`.

```bash
curl https://media.phatdev.net/api/v1/info          # all parameters + endpoints
curl https://media.phatdev.net/api/v1/openapi.json  # OpenAPI 3.0 spec
curl https://media.phatdev.net/api/v1/health        # version, ready engines, usage limits
```

## Background jobs and duplicate protection

Long jobs (a review-pack takes 4-5 minutes, video rendering) are easily cut off mid-connection. Use:

- `"async": true` → you get `202` + a `jobId`, then poll `GET /api/v1/jobs/:id`.
- The `x-idempotency-key` header → calling again with the same key **returns the earlier result** without generating anything new.
- Without a key: an identical request that is already running is shared; if it just finished but the client had disconnected, the retry gets the result right away (within 30 minutes).
- `"returnB64": false` keeps the response light and returns only the `url`.
- The `x-engine` header (see `GET /api/v1/info` for the values) → accept only images from the main engine; if the main engine reaches its usage limit you get `503` immediately.

Every image-generating response has an **`engine`** field telling you which engine drew it (the main engine or the fallback).

## Main endpoints

| Group | Endpoints |
|---|---|
| Product photos | `POST /generate` · `/review-pack` · `/bg-swap` · `/knowledge-pack` · `/create` · `/compare-ref` · `/qa` |
| Banners and charts | `POST /banner` · `/chart` |
| Video | `POST /auto-script` · `/html-video/render` · `/render-video` · `/render-pro` · `GET /html-video/templates` |
| Script and voice | `POST /script` · `/script/srt` · `/tts` · `/tts/summary` · `/tts/podcast` · `/transcribe` · `/transcribe/srt` |
| Image processing | `POST /remove-bg` · `/upscale` · `/tinypng` |
| Models and brands | `GET/POST /models` · `POST /models/:id/pose` · `/models/:id/uniform` · `GET /brands` · `GET/POST /wallpapers` |
| Library | `GET /library` · `GET /image/:id?res=2k\|4k` · `DELETE /library/:id` · `GET /jobs/:id` |

> **Removed:** `POST /video` (Grok Imagine) has returned `410` since v1.13.3; `render-pro` in Grok clip mode now runs image mode with Ken Burns instead.

## Examples

```bash
# Review photo set + Featured image in one call (runs in the background)
curl -X POST https://media.phatdev.net/api/v1/review-pack \
  -H 'Content-Type: application/json' -H 'x-api-token: <key>' \
  -H 'x-idempotency-key: rog-scar18-2026-10' \
  -d '{"refUrls":["https://.../anh-H1.jpg"],"spaceId":"studio","productName":"ROG Strix SCAR 18","featured":{"title":"Đánh giá ROG Strix SCAR 18"},"async":true}'
# → 202 { jobId }  → GET /api/v1/jobs/<jobId>

# Video script from a product link (progress returned as SSE)
curl -N -X POST https://media.phatdev.net/api/v1/auto-script \
  -H 'Content-Type: application/json' -H 'x-api-token: <key>' \
  -d '{"productUrl":"https://hungphatlaptop.com/...","brandName":"Hưng Phát Laptop"}'
```

## Error codes

| Code | Meaning | What your pipeline should do |
|---|---|---|
| `400` | Bad parameters (wrong frame, broken reference image...) | Fix the request |
| `401` | Missing / wrong key | Check `x-api-token` |
| `410` | Feature removed | Stop calling it |
| `422` | Unusable result (for example an empty transparent PNG) | Retry with a different image |
| `503` | Engine overloaded / usage limit reached | Wait and retry (with an idempotency key) |
