How to Use Vidiome's API to Automate Article Generation from Video
Technical tutorial for developers: use Vidiome's POST /api/v1/articles endpoint to automate video-to-article generation at scale. Curl + Node.js examples included.
Vidiome's REST API turns a YouTube video into a structured blog article with a single request. You send a YouTube URL, Vidiome reads the video's transcript, writes the article with an LLM, and returns it as JSON: a title and a list of sections, each with its own H2 title, content and timestamps.
This tutorial covers authentication, the request and response format, curl and Node.js examples, batch processing, publishing to WordPress, and the limits you need to plan for.
Who This Tutorial Is For
- SaaS developers building content automation features for clients or internal tools
- Content agencies processing many videos per week who want to skip the manual steps
- Platform teams plugging video-to-article into an existing CMS or content workflow
If you're an individual creator rather than a developer, the Vidiome web app is the faster path. It also captures a screenshot for every section, which the API does not do.
Vidiome
Turn your videos into SEO traffic machines
Generate my first articleNo credit card required · 120 free credits
Prerequisites
- A Vidiome account on a paid plan (Starter, Pro or Business). API requests from free accounts are refused with
403. - An API key, created in the app under Profile → API keys. Keys start with
vdm_live_. Keep them secret: anyone with the key can spend your credits. - A YouTube video that has a transcript (manual or automatic captions). The API works from that transcript.
New accounts get 120 free credits to try the web app before choosing a plan.
Endpoint: POST /api/v1/articles
Request
POST https://www.vidiome.com/api/v1/articles
Content-Type: application/json
x-api-key: vdm_live_YOUR_KEY
Authorization: Bearer vdm_live_YOUR_KEY works too.
Request body
{
"youtubeUrl": "https://www.youtube.com/watch?v=XXXXXXXXXXX",
"language": "en"
}
| Field | Type | Required | Description |
|---|---|---|---|
youtubeUrl |
string | Yes | Full URL of a YouTube video |
language |
string | No | Language the article is written in: en, fr, es, pt, de, ru, hi, uk, id or tr. Set it explicitly: without it, no language is enforced |
That's the whole request. There is no file upload, output-format or keyword parameter.
Response
The call is synchronous: the connection stays open while Vidiome generates the article, then the full result comes back. Expect anywhere from a few seconds to a few minutes depending on the video's length.
{
"id": "5b0c9c2e-6f1d-4d8a-9a57-2f1f3c1e8b21",
"title": "How to Repurpose One Video into a Month of Content",
"sections": [
{
"id": "a3f1…",
"title": "Introduction: one video, many formats",
"content": "Most creators publish a video and move on…\n\n### Why the transcript is only a starting point\n\n…",
"startTime": 0,
"endTime": 74,
"images": []
}
],
"videoUrl": "https://www.youtube.com/watch?v=XXXXXXXXXXX",
"videoId": "XXXXXXXXXXX",
"language": "en",
"creditsUsed": 40,
"creditsRemaining": 460,
"createdAt": "2026-09-26T10:23:41.000Z"
}
A few things to know about the response:
sectionsgo in reading order: an introduction, the body sections, then a conclusion.titleis the section's H2.contentis text with###lines for H3 subheadings, blank lines between paragraphs,**bold**and-list items.startTime/endTimeare in seconds and point to the part of the video each section comes from. Handy for embedding the video at the right moment.imagesis always empty through the API. Screenshots are captured in the browser by the web app. To add them, open the article in Vidiome and pick them there, or use your own images.- The article is saved to your account (
id). It shows up in your Vidiome dashboard, where you can edit it.
Code Examples
curl
curl -X POST https://www.vidiome.com/api/v1/articles \
-H "Content-Type: application/json" \
-H "x-api-key: $VIDIOME_API_KEY" \
-d '{
"youtubeUrl": "https://www.youtube.com/watch?v=XXXXXXXXXXX",
"language": "en"
}'
Node.js (fetch)
const VIDIOME_API_KEY = process.env.VIDIOME_API_KEY;
async function generateArticle(youtubeUrl, language = 'en') {
const response = await fetch('https://www.vidiome.com/api/v1/articles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': VIDIOME_API_KEY,
},
body: JSON.stringify({ youtubeUrl, language }),
// Generation can take a few minutes: don't let the client give up first.
signal: AbortSignal.timeout(6 * 60 * 1000),
});
const data = await response.json();
if (!response.ok) {
const error = new Error(`Vidiome API ${response.status}: ${data.error}`);
error.status = response.status;
error.retryAfter = Number(response.headers.get('retry-after')) || null;
throw error;
}
return data;
}
// Turn the sections into Markdown (or feed them to your own renderer).
function toMarkdown(article) {
const body = article.sections
.map((section) => `## ${section.title}\n\n${section.content}`)
.join('\n\n');
return `# ${article.title}\n\n${body}\n`;
}
const article = await generateArticle('https://www.youtube.com/watch?v=XXXXXXXXXXX');
console.log(toMarkdown(article));
console.log(`Credits used: ${article.creditsUsed}, left: ${article.creditsRemaining}`);
Automation Workflow
┌─────────────────────────────────────────────────────────┐
│ VIDEO SOURCE LAYER │
│ YouTube playlist / channel / list of URLs │
└──────────────────────┬──────────────────────────────────┘
│ YouTube URLs
▼
┌─────────────────────────────────────────────────────────┐
│ ORCHESTRATION LAYER │
│ Cron job / n8n / Make.com / your own queue │
│ - Skip URLs already processed │
│ - Stay under 10 requests per minute per key │
│ - Retry on 429 / 502 after the Retry-After delay │
└──────────────────────┬──────────────────────────────────┘
│ POST /api/v1/articles
▼
┌─────────────────────────────────────────────────────────┐
│ VIDIOME API │
│ 1. Fetch the YouTube video's transcript │
│ 2. Write the article with an LLM │
│ 3. Save it to your account, return title + sections │
└──────────────────────┬──────────────────────────────────┘
│ Article JSON
▼
┌─────────────────────────────────────────────────────────┐
│ POST-PROCESSING LAYER │
│ - Convert sections to HTML or Markdown │
│ - Human review (recommended) │
│ - Images, internal links, meta description, schema │
└──────────────────────┬──────────────────────────────────┘
│ Publish-ready article
▼
┌─────────────────────────────────────────────────────────┐
│ CMS / PLATFORM │
│ WordPress / Ghost / Webflow / Contentful / Sanity │
└─────────────────────────────────────────────────────────┘
Use Cases
Batch processing a YouTube channel
Each API key is limited to 10 requests per minute. Since every request stays open until its article is ready, a small number of parallel requests is plenty:
async function processVideos(urls, { language = 'en', concurrency = 2 } = {}) {
const results = [];
const queue = [...urls];
async function worker() {
while (queue.length > 0) {
const url = queue.shift();
try {
results.push({ url, article: await generateArticle(url, language) });
} catch (error) {
if (error.status === 429 && error.retryAfter) {
await new Promise((r) => setTimeout(r, error.retryAfter * 1000));
queue.push(url); // try again later
} else {
results.push({ url, error: error.message });
}
}
}
}
await Promise.all(Array.from({ length: concurrency }, worker));
return results;
}
Stop the batch when you get a 402: your credit balance is too low for the next video.
Publishing to WordPress
Vidiome returns sections, not HTML, so convert them first. A Markdown library such as marked does the job, or you can keep the conversion minimal:
import { marked } from 'marked';
async function publishToWordPress(article, { siteUrl, username, appPassword }) {
const credentials = Buffer.from(`${username}:${appPassword}`).toString('base64');
const html = marked.parse(
article.sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n')
);
const response = await fetch(`${siteUrl}/wp-json/wp/v2/posts`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`,
},
body: JSON.stringify({
title: article.title,
content: html,
status: 'draft', // review before publishing
}),
});
return response.json();
}
One video, several languages
Run one request per language. Each one is a separate generation and costs credits like any other:
const LANGUAGES = ['en', 'fr', 'es', 'de'];
async function generateInLanguages(youtubeUrl) {
const versions = {};
for (const language of LANGUAGES) {
versions[language] = await generateArticle(youtubeUrl, language);
}
return versions;
}
Limits and Credits
- Rate limit: 10 requests per minute per API key, on every paid plan. Beyond that you get
429with aRetry-Afterheader (in seconds). - Duration: each request can run for up to 5 minutes on Vidiome's side. Very long videos may not fit; split your workflow or use the web app for them.
- Credits: the API charges the same as the web app, at the current rate of 4 credits per minute of video with a 20-credit minimum (a 10-minute video uses 40 credits, a 60-minute one 240). Each response tells you
creditsUsedandcreditsRemaining. See pricing for plans and credit packs.
Error Handling
Errors come back as JSON with an error field.
| Status | error |
What to do |
|---|---|---|
400 |
Invalid request body or invalid-youtube-url |
Check the URL and the language code |
401 |
Missing API key / Invalid or revoked API key |
Check the x-api-key header |
402 |
insufficient-credits (with required and available) |
Top up credits or upgrade your plan |
403 |
api_access_requires_paid_plan |
Move to a paid plan |
404 |
no-captions |
The video has no transcript; try another video |
429 |
rate limit, or transcript_provider_rate_limited |
Wait for Retry-After, then retry |
500 |
article_generation_failed |
Retry once; if it keeps failing, contact us |
502 |
transcript_provider_unavailable / llm_provider_error |
Temporary: retry with a delay |
Frequently Asked Questions
Can I send a video file instead of a YouTube URL?
No. The API only accepts YouTube URLs, and the video needs a transcript. For MP4, MOV or WebM files, use the web app: it transcribes the audio and also captures a screenshot for each section.
Is there a webhook or a status endpoint?
No. The request is synchronous and returns the finished article. If you process many videos, put the calls in your own job queue (a cron job, n8n, Make.com, a worker) and store the results as they come in.
Where do articles generated through the API go?
They're saved to your Vidiome account, so you'll find them in your dashboard. That's the easiest way to add screenshots, fix a passage with the AI rewrite, or export the article as HTML or Markdown.
Next Steps
Explore related solutions
Discover more ways to turn video into high-ranking written content.
Automate YouTube-to-article conversion with the Vidiome API
Send a YouTube URL to the Vidiome API and get the finished article back as JSON: a title and sections. 10 languages, paid plans, 10 requests/min.
Deliver client SEO articles from video at agency scale
Vidiome delivers structured SEO blog articles from client videos in under 5 minutes — not hours. Agency-grade AI video-to-article platform. 10 languages.
Scale SaaS content marketing with video — automated
Vidiome converts product demos, webinars and tutorials into SEO blog articles in under 5 minutes. SaaS teams ship ~100 articles/month on the Business plan.
Vidiome
Turn your videos into SEO traffic machines
Generate my first articleNo credit card required · 120 free credits