# Revid API — Article to video (`article-to-video`)

> Summarize any web page or article into a narrated short video.

Endpoint: `POST https://www.revid.ai/api/public/v3/render` — auth header `key: YOUR_API_KEY` (get a key at https://www.revid.ai/account).
Cost: 10 credits per call + generation costs. Estimate first with `POST https://www.revid.ai/api/public/v3/calculate-credits` (same body, no auth).

## Required input

- source.url

## Defaults for this workflow

- media.type: `moving-image`
- AI voice-over: enabled by default
- Background music: enabled by default
- Captions: enabled by default (preset `Wrap 1`, position `bottom`)
- Aspect ratio: `9:16` (portrait) by default

## Minimal request

```bash
curl -X POST 'https://www.revid.ai/api/public/v3/render' \
  -H 'Content-Type: application/json' \
  -H 'key: YOUR_API_KEY' \
  -d '{"workflow":"article-to-video","source":{"url":"https://en.wikipedia.org/wiki/Honey"}}'
```

## Full example

```json
{
  "webhookUrl": "https://your-server.com/revid/webhook",
  "workflow": "article-to-video",
  "source": {
    "url": "https://open.spotify.com/track/5Cp75TUMrHF6c8xbhdligS"
  },
  "media": {
    "type": "moving-image",
    "quality": "ultra"
  },
  "options": {
    "summarizationPreference": "summarize",
    "targetDuration": 30
  },
  "metadata": {
    "urlType": "spotify",
    "duration": 194
  }
}
```

## Parameters for this workflow

Top-level fields:

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `workflow` | string | **Yes** |  | `script-to-video` / `prompt-to-video` / `audio-to-video` / `music-to-video` / `article-to-video` / `avatar-to-video` / `static-background-video` / `motion-transfer` / `caption-video` / `ad-generator` | The generation workflow. Decides which source input is required and every default below. |
| `webhookUrl` | string | No |  |  | Public URL called when the render finishes (success or failure). Strongly recommended over polling. Accepted aliases: webhook. |
| `projectId` | string | No |  |  | Reuse an existing project instead of creating a new one. The project must belong to the API key's workspace. Accepted aliases: pid. |
| `aspectRatio` | string | No | `"9:16"` | `9:16` / `16:9` / `1:1` / `auto` | Output aspect ratio. Accepted aliases: ratio. |
| `metadata` | object|null | No |  |  | Free-form object stored with the project and echoed in webhooks. For URL sources, metadata.duration (seconds) speeds up processing. |
| `characterIds` | string[] | No |  |  | IDs of saved consistent characters to feature in the video. Get IDs from GET /api/public/v3/consistent-characters. Selecting characters can force media.imageModel to ultra when the preset requires it. Accepted aliases: selectedCharacters, options.characterIds, options.selectedCharacters. |

### `source` (required for this workflow)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `source.url` | string | audio-to-video, music-to-video, article-to-video, motion-transfer, caption-video |  |  | The source content URL: audio file, video file, YouTube link, Spotify track, article page, or PDF depending on the workflow. http(s) is enforced; bare domains get https:// prepended. Workflows: audio-to-video, music-to-video, article-to-video, motion-transfer, caption-video, static-background-video. |
| `source.scrapingPrompt` | string | No |  |  | Custom instructions for extracting content from the source page (e.g. "focus on the pricing section"). Workflows: article-to-video. Accepted aliases: options.scrapingPrompt, scrapingPrompt. |
| `source.websiteToRecord` | string | No |  |  | URL of a website to screen-record as footage for the video. Accepted aliases: websiteToRecord. |
| `source.quizzData` | object | No |  |  | Quiz definition for quiz videos: { title, questions: [{ id, question, answers: [{ id, answer, isCorrect }] }] }. Accepted aliases: options.quizzData, quizzData. |

### `media` (optional)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `media.type` | string | No | moving-image for most workflows; ai-video for prompt-to-video and audio-to-video | `moving-image` / `ai-video` / `stock-video` / `custom` | The visual engine for the video. Default: moving-image for most workflows; ai-video for prompt-to-video and audio-to-video. |
| `media.quality` | string | No | `"pro"` | `standard` / `pro` / `ultra` | Convenience profile that picks imageModel + videoModel for you. Explicit media.imageModel / media.videoModel override it. |
| `media.imageModel` | string | No |  | `cheap` / `good` / `ultra` | Image generation model. Auto-adjusted when needed: ai-video forces ultra, and presets/characters can upgrade it. Accepted aliases: imageGenerationModel. |
| `media.videoModel` | string | No |  | `base` / `pro` / `ultra` / `veo3` / `sora2` | Video generation model used when video clips are generated. Accepted aliases: videoGenerationModel. |
| `media.density` | string | No |  | `low` / `medium` / `high` | How many distinct visuals per minute of video. More visuals = livelier video and higher generation cost. Accepted aliases: mediaMultiplier. |
| `media.animation` | string | No | `"soft"` | `none` / `soft` / `dynamic` / `depth` | How still images are animated. Ignored for other media types. Only applies when media.type = moving-image. Accepted aliases: typeMovingImageAnim. |
| `media.mediaPreset` | string | No | `"DEFAULT"` |  | Visual style preset slug (e.g. DEFAULT, ANIME, PIXAR, GHIBLI, REALISM, ...). See the preset list in the docs. A preset can override media.imageModel when it requires a specific model. Only applies when media.type = moving-image or ai-video. Accepted aliases: media.generationPreset, options.generationPreset, generationPreset. |
| `media.maxItems` | integer | No |  | min 1 | Hard cap on the number of generated/selected media items. Accepted aliases: maxNbMedias. |
| `media.provided` | array | media.type = custom (>= 1 item); motion-transfer (target image) |  |  | Your own media items. Used as the only visuals when media.type = custom or media.useOnlyProvided = true; otherwise used as references/anchors. Items: { url (required), type, title, ... }. Accepted aliases: inputMedias. |
| `media.useOnlyProvided` | boolean | No | `false` |  | Use only media.provided[] items; disable AI media generation/search. Default: true for motion-transfer and ad-generator. Accepted aliases: options.useOnlyProvidedMedia, useOnlyProvidedMedia. |
| `media.useProvidedInOrder` | boolean | No | `false` |  | Map media.provided[] items to script sections in order (no AI picking). Forces useOnlyProvided. Fewer media than sections: adjacent sections are grouped; extra media are ignored. Requires at least one image/video item. Only applies when media.type = custom. |
| `media.mergeVideos` | boolean | No | `false` |  | Merge multiple provided videos into one sequence. |
| `media.mergeVideosFull` | boolean | No | `false` |  | Merge provided videos keeping their full length. |
| `media.addAudioToVideos` | boolean | No | true for prompt-to-video with media.type = ai-video, false otherwise |  | Generate ambient audio/sound for AI video clips. Default: true for prompt-to-video with media.type = ai-video, false otherwise. |
| `media.turnImagesIntoVideos` | boolean | No | `false` |  | Animate provided still images into video clips. |
| `media.applyStyleTransfer` | boolean | No | `false` |  | Re-style provided media to match the selected preset. |

### `voice` (optional, enabled by default)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `voice.enabled` | boolean | No | on for script/prompt/article/avatar/static/ad workflows; off for audio/music/caption/motion workflows |  | Generate an AI voice-over for the script. Default: on for script/prompt/article/avatar/static/ad workflows; off for audio/music/caption/motion workflows. Accepted aliases: hasToGenerateVoice. |
| `voice.voiceId` | string | No | `"cgSgspJ2msm6clMCkdW9"` |  | Voice ID (ElevenLabs or cloned voice). Browse voices at revid.ai or clone one via POST /api/public/v3/voice-clone. Accepted aliases: voice.id, selectedVoice. |
| `voice.stability` | number | No | `0.2` | min 0, max 1 | Voice stability. Lower = more expressive, higher = more consistent. |
| `voice.speed` | number | No | `1` | min 0.5, max 2 | Speech speed multiplier. |
| `voice.useLegacyModel` | boolean | No | `false` |  | Use the previous-generation voice model. |
| `voice.enhanceAudio` | boolean | No | `false` |  | Post-process the voice track for cleaner audio. Accepted aliases: options.hasToEnhanceAudio, hasToEnhanceAudio. |
| `voice.language` | string | No |  |  | Language code for voice-over and script generation (e.g. "en", "fr", "es"). 70+ languages supported. Accepted aliases: options.language, language, lang. |

### `captions` (optional, enabled by default)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `captions.enabled` | boolean | No | `true` |  | Burn animated captions into the video. Accepted aliases: disableCaptions (inverted). |
| `captions.preset` | string | No | `"Wrap 1"` |  | Caption style preset. Available: Basic, Revid, Hormozi, Ali, Wrap 1, Wrap 2, Faceless, Elegant, Difference, Opacity, Playful, Bold Punch, Movie, Outline, Cove, Beat, Floating, Gram, Word by Word. |
| `captions.position` | string | No | `"bottom"` | `top` / `middle` / `bottom` | Vertical position of the captions. |

### `music` (optional, enabled by default)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `music.enabled` | boolean | No | on for script/prompt/article/static/ad/caption/motion workflows; off for audio/music/avatar workflows. Auto-enabled when any other music field is set. |  | Add a background music track. The whole music block also accepts the legacy alias name `audio`. Default: on for script/prompt/article/static/ad/caption/motion workflows; off for audio/music/avatar workflows. Auto-enabled when any other music field is set.. Accepted aliases: audio.enabled, disableAudio (inverted). |
| `music.trackName` | string | No | `"Observer"` |  | Name of a track from the Revid library (115+ tracks, e.g. Observer, Snaps, Bright Morning, Chill Wave, Epic Battle Orchestra). Ignored when music.audioUrl is set. Accepted aliases: audio.trackName, selectedAudio. |
| `music.audioUrl` | string | No |  |  | Custom background music URL. Checked for reachability (HEAD request) before the render starts. Accepted aliases: music.url, audioUrl. |
| `music.generateMusic` | boolean | No | `false` |  | Generate an AI music track instead of using the library/custom URL. Accepted aliases: music.generate, options.generateMusic, hasToGenerateMusic. |
| `music.generationMusicPrompt` | string | No |  |  | Prompt for AI music generation (style, mood, instruments). Accepted aliases: music.generationPrompt, options.generationMusicPrompt, generationMusicPrompt. |
| `music.musicGenerationModel` | string | No | `"base"` |  | Model used for AI music generation. |

### `options` (optional)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `options.targetDuration` | integer | No |  | min 1 | Target output duration in seconds for URL-driven workflows. In prompt workflows this acts as an alias of options.promptTargetDuration. Workflows: article-to-video, audio-to-video, music-to-video, caption-video. Accepted aliases: targetDuration. |
| `options.summarizationPreference` | string | No |  | `summarize` / `summarizeIfLong` / `no-summarization` | How to condense source content into the script. Workflows: article-to-video, script-to-video. |
| `options.outputCount` | integer | No | `1` | min 1, max 10 | Number of video variations to generate. Each variation consumes credits. Accepted aliases: nbGenerations. |
| `options.disableAudio` | boolean | No |  |  | Hard override: strip background music from the output regardless of the music block. Accepted aliases: disableAudio. |
| `options.disableVoice` | boolean | No |  |  | Hard override: no voice-over regardless of the voice block. Accepted aliases: disableVoice. |
| `options.soundEffects` | boolean | No | `false` |  | Generate sound effects matched to the scenes. Accepted aliases: hasToGenerateSoundEffects. |
| `options.addStickers` | boolean | No | `false` |  | Add animated stickers/emojis matched to the script. Accepted aliases: addStickers. |
| `options.nsfwFilter` | boolean | No | `false` |  | Filter NSFW content in generated media. Accepted aliases: enableNsfwFilter. |
| `options.language` | string | No |  |  | Language override for the whole generation (same as voice.language). Accepted aliases: language, lang, voice.language. |
| `options.watermark` | object|null | No |  |  | Custom watermark object forwarded as-is ({ url, position, opacity, ... }). null removes it. Accepted aliases: watermark. |
| `options.selectedPalette` | string | No |  |  | Color palette name for generated visuals. |
| `options.preventSummarization` | boolean | No | `false` |  | Never shorten the provided text (overrides summarization heuristics). |
| `options.hasToGenerateCover` | boolean | No | `false` |  | Generate a cover/thumbnail image for the video. |
| `options.coverTextType` | string | No | `"layers"` |  | Style of the text on the generated cover. |
| `options.hasTextSmallAtBottom` | boolean | No | `false` |  | Show a small text line at the bottom of the video. |
| `options.customImageGenerationRulesSlug` | string | No |  |  | Slug of saved custom image generation rules to apply. |

### `render` (optional)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `render.resolution` | string | No | `"1080p"` | `720p` / `1080p` / `4k` | Output resolution. 4k exports cost extra credits. Accepted aliases: resolution. |
| `render.compression` | number | No | `18` | min 0, max 50 | H.264 CRF-style compression. Lower = better quality and bigger files. Accepted aliases: compression. |
| `render.frameRate` | number | No | `30` | min 1, max 60 | Output frame rate. Accepted aliases: frameRate. |

### `advanced` (optional)

| Field | Type | Required | Default | Allowed | Description |
|---|---|---|---|---|---|
| `advanced.customCreationParams` | object | No |  |  | Expert escape hatch: extra legacy creationParams merged into the final payload. Workflow identity keys (slug, flowType) stay locked. Use only with guidance from the Revid team. Accepted aliases: customCreationParams. |

## Notes

- Control summarization with options.summarizationPreference and length with options.targetDuration.
- source.scrapingPrompt gives custom instructions for extracting content from the page.

## Response

Success: `{ "success": 1, "pid": "...", ... }` — the render is asynchronous. Get the result via your `webhookUrl` or poll `GET /api/public/v3/status?pid=...`.

Errors: 400 — validation error. The message names the exact field, e.g. "voice.speed must be between 0.5 and 2." 401 — missing or invalid API key (header `key`). 500 — internal error. Credits consumed by a failed render are refunded automatically.

---

All workflows: [script-to-video](https://www.revid.ai/llm/api/script-to-video.md) · [prompt-to-video](https://www.revid.ai/llm/api/prompt-to-video.md) · [audio-to-video](https://www.revid.ai/llm/api/audio-to-video.md) · [music-to-video](https://www.revid.ai/llm/api/music-to-video.md) · [article-to-video](https://www.revid.ai/llm/api/article-to-video.md) · [avatar-to-video](https://www.revid.ai/llm/api/avatar-to-video.md) · [static-background-video](https://www.revid.ai/llm/api/static-background-video.md) · [motion-transfer](https://www.revid.ai/llm/api/motion-transfer.md) · [caption-video](https://www.revid.ai/llm/api/caption-video.md) · [ad-generator](https://www.revid.ai/llm/api/ad-generator.md)

More: [endpoint reference](https://www.revid.ai/llm/api/endpoints.md) · [interactive docs](https://www.revid.ai/docs) · [OpenAPI spec](https://www.revid.ai/postman/revid-public-v3-render.openapi.json) · [MCP server](https://www.revid.ai/mcp)
