VlogMe / For developers
REST API and MCP workflows
Connect Director and Studio workflows through REST API and MCP, pass prompts and media references, track jobs, and keep results in the shared Lab — the same workflows you run in the VlogMe app.
On this page
How the API works
The REST API and the MCP server run the same jobs as the VlogMe app — Director, Video, Image and Audio Studio, Aisma, DUB and News Videos — on the same account, the same credit balance and the same Lab.
Access: API and MCP are available to every registered VlogMe account. Create a key in Account → API & MCP; no support approval is needed. For volume or an integration for your team, write to sales@vlogme.ai.
An integration then follows five steps:
- Create an API key in Account → API & MCP.
- Upload the photo, video or audio a job needs, or reuse a file from Lab.
- Quote the job: VlogMe returns its exact credit price.
- Start the job with that quote. It never runs at a different price.
- Track it by polling or with a webhook; the results are saved to Lab.
Agents can do the same through the MCP server: its tools cover jobs, the Director, Lab files, projects, templates, voices, News Videos and social publishing, with the same key, balance and checks as REST.
Changes to the API and MCP are announced in the development journal.
Connect your agent
AI agents work on the same account, key, balance and prices through the MCP server at https://vlogme.ai/mcp. MCP server setup has the exact steps for each client:
- Claude Code, Cursor and VS Code
- Gemini CLI and Codex
- n8n workflows
In Claude Code it is one command, with the key in VLOGME_API_KEY:
claude mcp add --transport http vlogme https://vlogme.ai/mcp --header "Authorization: Bearer $VLOGME_API_KEY"
The agent asks for a quote and shows you the credits before any paid job. The MCP server section below lists every tool and the key scope it needs.
API keys and access
Every request carries a key in the Authorization header:
Authorization: Bearer vma_…
- A key can do what you ticked when you made it in Account → API & MCP:
- read: list your Lab files, jobs and balance, and ask for a quote. Every key has it.
- write: upload and import files, rename and archive them, save projects, plan and prepare with the Director, and start paid jobs at their quoted price.
- delete: delete files, projects, voice clones and news monitors. Deleting cannot be undone.
- share: create and revoke public share links.
- publish: publish or schedule videos on your connected social accounts.
- Keys made before these choices keep what they could do: a “Read” key reads, and a “Read and create jobs” key also deletes and shares, as before.
- A request the key may not make is refused with
403andcode: scope_missing.GET /api/meshows the key’s owntoken.scopes. - A key expires after 1 to 365 days (90 by default). Revoke it at any time in Account → API & MCP: integrations that use it stop at once.
- A key cannot change your plan, create other keys, delete your account or open the admin tools; those need a signed-in session (
code: session_required).
Keep keys secret: they act for your account and spend its credits (Terms of Service).
Discover jobs and routes
Two public addresses describe everything an integration can send. They need no key.
GET /api/cataloglists every jobkind(with its workflow or model): its input as JSON Schema, the Lab files it takes, its durations, aspect ratios and qualities, its price rule, an example input with the example’s price in credits, and whether it is available now.?kind=videonarrows the list. It also holds the Director’s schemas: a new project, an edit command, a chat turn and a preparation.GET /api/openapi.jsonis the OpenAPI 3.1 description of the REST API. Each operation’sx-scopenames the key scope it needs.
Fields an entry lists under server_fills, such as the length of a video, are measured by VlogMe from your file, so you can leave them out.
Quote, start and track a job
A job is one piece of work: a clip, an avatar, an image, a voice track, an edit, a dub, an Aisma change, a News Videos video or a Director render. Its kind is one of video, avatar, image, audio, video_edit, dub, trend, aisma, voice_clone, director, and its input holds the settings of the matching screen in the app.
Ordinary Image Editor changes export in the browser and are not a server job. For AI image generation and edits, use kind: image with the matching workflow.
| Request | What it does |
|---|---|
POST /api/jobs/quote | Returns credits, the priced parts and a quote_fingerprint for a kind and input |
POST /api/jobs | Starts the job with the quoted_credits and quote_fingerprint of its quote; an Idempotency-Key header (a UUID) makes a retry return the same job instead of starting a second one |
GET /api/jobs | Your jobs, newest first. Filter with kind, status and project_id; page with limit (up to 100) and the returned next_cursor; fields=compact leaves the inputs out |
GET /api/jobs/{id} | The job's status, its results (the Lab files it made) and any warnings. Add ?wait=30 to wait up to that many seconds for the job to end |
GET /api/jobs/{id}/clips | The clips of a finished Aisma edit: each clip's versions, what regenerating it costs, and whether the full video is up to date |
For example, quote an image and then start it:
curl https://vlogme.ai/api/jobs/quote \
-H "Authorization: Bearer $VLOGME_KEY" \
-H "Content-Type: application/json" \
-d '{"kind": "image", "input": {…}}'
curl https://vlogme.ai/api/jobs \
-H "Authorization: Bearer $VLOGME_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2b8e-7d4a-4f0e-9b1a-2c3d4e5f6a7b" \
-d '{"kind": "image", "input": {…}, "quoted_credits": 12, "quote_fingerprint": "…"}'
If the price or the inputs changed since the quote, the start is refused with 409 and nothing is charged: ask for a new quote. A job that fails returns its eligible credits to your balance automatically. A job cannot be cancelled once it starts, because providers cannot always stop one.
Changing one clip of an Aisma edit. A finished Aisma edit can have one clip made again without redoing the whole video. GET /api/jobs/{id}/clips, where the id is the edit's own job, lists its clips with their index and what regenerating each costs in credits. Quote and start an aisma job whose input is {"clip": {"job_id": "<the edit's job id>", "op": "regenerate", "part": <index>, "clarification": "…"}}: the clarification is optional, and the clip is made on the edit's own version and quality. Only that clip is charged, and nothing is charged when Aisma does not apply the clarification, cannot make the clip or leaves it as filmed. The finished job's input.clip_result states the outcome and, for a clarification that was not applied, the reason; its result is the updated full video, a new file in Lab. clips is null for an edit that has no clips to read: it was made before clips could be changed, or its files went with its source. Otherwise disabled says why no clip can be changed now (starting, failed, busy or materials; null when one can), and finish how the full video is brought up to date (assemble: start a job with {"clip": {"job_id": "…", "op": "assemble"}}; reassemble: POST /api/jobs/{id}/reassemble; null: it is up to date). A clip whose mode is change was left as filmed by Aisma: a key must send a clarification to make it again. Updates that end without a charge are limited by the hour, for each edit and for all the edits of an account together; past either limit a quote and a start answer 429 with retry_after_s. Aisma asks its clarifying questions only in the app: an edit started with a key is never asked.
Make a Director video
A key with the write scope can take a video from an idea to the finished file:
POST /api/director/projectswith{"version": 2, "concept": "…"}creates the project.POST /api/director/projects/{id}/turnswith a newclient_request_idand the project’sbase_revisionasks the Director to plan it.GET /api/director/turns/{turn id}?wait=30waits until the plan is ready or the Director asks a question; answer it withPOST /api/director/turns/{turn id}/answer.POST /api/director/projects/{id}/preparemakes the free pictures, voices and music, andGET /api/director/projects/{id}/viewshows what is ready. They take a while: read/viewagain until each of itsmaterialsisready.POST /api/director/projects/{id}/render/quoteprices the video (remake_scene_numbersmakes chosen scenes again), andPOST /api/director/projects/{id}/renderwith thatrevision,quoted_credits,quote_fingerprintand anIdempotency-Keystarts it. If the plan changed since the quote, the start is refused with409(code: revision_conflict) and nothing is charged.GET /api/jobs/{job id}?wait=30until the job ends; thenGET /api/director/projects/{id}/resultgives the video and its subtitles with links that last 15 minutes.
Planning, chat and free preparation through a key use the same free allowance as the app on your account: an agent that plans a lot uses it up for the app too. When it is used up for now, the answer says limited: true.
Faces and places are free within the allowance. Past it, a free account's pictures are not made: the /prepare answer lists them under plan_required (and skipped), and a plan is needed to keep making pictures. With a plan, pictures past its allowance come back under charged, with their price: quote them with POST /api/jobs/quote (kind director, input {"v": 2, "stage": "materials", "project_id": "…", "revision": 3, "keys": ["…"]}) and start them like any paid job. A picture still missing in /view when the video is rendered is made in the render and is part of its quoted price. A new take of a picture that is already made (Try again) is POST /api/director/projects/{id}/prepare with its key in keys and "regenerate": true.
To change the plan, send a message to /turns (with scope.block_ids to change some scenes only), or a structured edit to POST /api/director/projects/{id}/edits that follows director.edit_command_schema in GET /api/catalog. POST /api/director/projects/{id}/undo restores an earlier revision. Each change carries the base_revision you read and a new client_request_id: a stale revision is refused with 409, and a repeated client_request_id replays the change instead of making it twice.
Files you attach to a plan need rights_confirmed: true. Sent through a key, it is your own confirmation that you have the rights to use the files and the people in them (Terms of Service).
Lab files: upload, import and download
GET /api/assetslists your Lab files, newest first.section=mainis Files (finished videos, results and uploads),workingthe files a project uses while it is made,archivedthe archive, andall(the default) every file that is not archived. Filter withkind,project_id(ornone) andq;fields=compactleaves the metadata out; page withlimitand the returnednext_offset.GET /api/assets/working-projectsgroups Working files by project.POST /api/assets/intentwithmime_type,bytesandtitlereserves a Lab file and returns a resumable (tus) upload address and token. Images: JPEG, PNG, WebP, BMP. Video: MP4, MOV, M4V, up to 150 minutes. Audio: MP3, M4A, WAV, OGG. Up to 1 GB per file.- Add
content_sha256(the file's SHA-256 as 64 lowercase hex characters) and a file you already uploaded is reused: the answer is200withreused: trueand that file, and there is nothing to upload. Sendallow_duplicate: trueas well to keep a second copy. POST /api/assets/{id}/completechecks the upload and makes the file ready to use in a job'sinput.- With an API key, the intent also returns
put_url: one signed address that takes the whole file in a singlePUT(curl -T clip.mp4 -H "Content-Type: video/mp4" "$put_url"), instead of tus. AnIdempotency-Keyheader (a UUID) makes a retry return the same file. POST /api/assets/importwith{"url": "https://…"}and anIdempotency-Keyfetches a file from a public HTTPS address in the background. The answer is202with the new file’s id;GET /api/assets/{id}then showsimport.statusuntil the file is ready, orfailedwith anerror_code. Addresses of VlogMe itself, private networks and IP addresses are refused.PATCH /api/assets/{id}withtitlerenames a file, and witharchived: truemoves it to Archived (falserestores it); files a project uses while it is made stay in Working files.DELETE /api/assets/{id}deletes a file for good (the delete scope). A file that a running job still needs is refused with409.GET /api/assets/working-projects/{id}/cleanupshows what Clean up would delete in one project (earlier takes, unused pictures, leftovers), with the reason for each file.POSTto the same address withasset_idsfrom that preview deletes up to five of them per request (the delete scope). Nothing is ever deleted automatically.GET /api/assets/{id}/downloadreturns a private link that lasts 60 seconds;ttlasks for up to an hour, andredirect=1answers with a redirect to the file, socurl -Ldownloads it.
Files uploaded through the API stay private in your Lab, like the files you upload in the app.
Projects, templates and voices
GET /api/projectslists your projects, newest first: Director projects (with their idea and a summary) and News Videos, Aisma, DUB and Image Editor drafts (with their saved data). Filter withkind; page withlimitand the returnednext_cursor.POST /api/projectswithkind,titleanddatasaves a new draft; anIdempotency-Keyheader makes a retry return the same draft.PUT /api/projects/{id}with the draft’s currentrevisionsaves a change, and an older revision is refused with409.DELETE /api/projects/{id}deletes a project (the delete scope); its Lab files stay.- Director projects are created with
POST /api/director/projects(see above), not as drafts. GET /api/templateslists the published Aisma templates (category,q,limit,cursor),GET /api/templates/{id}shows one, andPOST /api/templates/{id}/openwith anIdempotency-Keyopens it as a new project.GET /api/voiceslists the voices a job or a Director cast can use: premade voices and your ready voice clones.GET /api/voice-cloneslists your clones with their status, andDELETE /api/voice-clones/{id}deletes one, also at the voice provider (the delete scope).
News Videos and social publishing
GET /api/trends/search?q=…searches recent news (languageisenorru;country,category,domains,sort_by).POST /api/trends/scriptwrites a script for a story, grounded in its sources, andPOST /api/trends/verifychecks a script against them.- News monitors look for new stories on a schedule:
GETandPOST /api/trends/monitors,PUTandDELETE /api/trends/monitors/{id}. GET /api/social/connectionsshows your connected social accounts, andGET /api/social/publicationsyour publications with their status. Connecting an account needs a signed-in session in the app.POST /api/social/publicationswithasset_id(a ready video) andplatform, optionallycaption,headline,visibility,cover_asset_idandscheduled_at, and anIdempotency-Key, publishes or schedules the video. It needs the publish scope, which a key has only when you ticked it. A post is public: an agent should show you the video, the platform and the caption, and publish only after your explicit yes.POST /api/social/publications/{id}/cancelcancels a publication that has not gone out yet (the publish or write scope).- The video editor preview (
POST /api/video-editor/preview) answers an MP4 stream, so it is available through REST only.
Waiting: long-poll and webhooks
There are two ways to know when work is done.
Long-poll. GET /api/jobs/{id}?wait=30 and GET /api/director/turns/{id}?wait=30 wait up to that many seconds (0 to 30) for the job or the turn to end (a turn also stops when it asks a question), then answer it with waited_seconds. While it still runs, retry_after_s says when to ask again. An agent on a laptop, which cannot receive webhooks, waits this way.
Webhooks. Add webhook_url, a public HTTPS address, when you start a job with an API key, and VlogMe posts an event when the job ends:
{"id": "job.<job id>.succeeded", "type": "job.succeeded", "created_at": "…",
"job": {"id": "…", "kind": "image", "status": "succeeded", "result_asset_id": "…", "error_code": null}}
- The type is
job.succeeded,job.failedorjob.partial(some results are in Lab and the credits of the missing parts were returned). A job under review (needs_review) has not ended yet: its event follows when it does. - A partial job whose final assembly failed can be assembled again for free with
POST /api/jobs/{id}/reassemble. When that ends, a new event reports the outcome, also when the assembly fails again and the job stays partial. Each outcome has an event id of its own: a partial one ends with itserror_code(job.<job id>.partial.<error code>), followed by.retry<n>once n free assemblies have failed again;GET /api/jobs/{id}shows that count asreassembly_failures. An Aisma edit whose clips were changed is joined another way: for it this request is refused with409(clip_job_required), and the video is joined for free by a job whoseinputis{"clip": {"job_id": "<the edit's job id>", "op": "assemble"}}. Such a job also joins the video after a clip job ended partial withaisma_clip_video_pending. - Each delivery carries
X-VlogMe-Event-Id,X-VlogMe-TimestampandX-VlogMe-Signature: v1=<hex>: an HMAC-SHA256 of<timestamp>.<body>whose key is the SHA-256 digest of your API key. Check the signature and reject old timestamps. - A delivery that does not get a 2xx answer is retried up to eight times, from 30 seconds apart to once an hour. Revoking the key stops its deliveries.
MCP server
AI agents that speak the Model Context Protocol connect to https://vlogme.ai/mcp (JSON-RPC 2.0 over HTTP POST) with the same Authorization: Bearer key; https://vlogme.ai/api/mcp is the same server at a second address. Supported protocol versions: 2026-07-28 (stateless, with the Mcp-Method and Mcp-Name headers and server/discover), and 2025-11-25, 2025-06-18 and 2025-03-26 (with initialize, which answers with the version the client asked for). A request without the MCP-Protocol-Version header is read as 2025-03-26. A request can be up to 1 MB.
The tools cover what a key can do through REST. Each tool needs the scope in the table. The tool list does not depend on the key’s scopes; a call the key may not make comes back as a refusal with code: scope_missing. With ?tools=all on the URL (https://vlogme.ai/mcp?tools=all) the list names every tool in the table; MCP server setup shows how each client connects.
| Tool | Scope | What it does |
|---|---|---|
vlogme_account | read | Account and credit balance |
vlogme_get_catalog | read | Job catalogue |
vlogme_list_assets | read | List Lab files |
vlogme_get_asset | read | Lab file and download link |
vlogme_list_working_projects | read | Working files by project |
vlogme_create_upload | write | Start an upload |
vlogme_complete_upload | write | Finish an upload |
vlogme_import_asset | write | Import a file from a URL |
vlogme_update_asset | write | Rename or archive a file |
vlogme_delete_asset | delete | Delete a Lab file |
vlogme_share_asset | share | Share link on or off |
vlogme_preview_cleanup | read | Preview Clean up |
vlogme_cleanup_working_files | delete | Clean up working files |
vlogme_list_jobs | read | List jobs |
vlogme_get_job | read | Read a job |
vlogme_wait_job | read | Wait for a job |
vlogme_get_job_clips | read | Clips of an Aisma edit |
vlogme_quote_job | read | Quote a job |
vlogme_create_job | write | Start a paid job |
vlogme_reassemble_job | write | Assemble a partial job again |
vlogme_list_projects | read | List projects |
vlogme_save_project | write | Save a draft |
vlogme_delete_project | delete | Delete a project |
vlogme_director_create | write | New Director project |
vlogme_director_get | read | Read a Director project |
vlogme_director_message | write | Ask the Director |
vlogme_director_turn | read | Read or wait for a turn |
vlogme_director_answer | write | Answer the Director |
vlogme_director_turn_action | write | Stop, apply or discard a turn |
vlogme_director_edit | write | Edit the plan |
vlogme_director_undo | write | Restore an earlier revision |
vlogme_director_prepare | write | Prepare pictures, voices and music |
vlogme_director_quote_render | read | Quote the video |
vlogme_director_render | write | Render the video |
vlogme_director_result | read | The finished video |
vlogme_list_templates | read | List templates |
vlogme_get_template | read | Read a template |
vlogme_open_template | write | Open a template |
vlogme_list_voices | read | List voices |
vlogme_delete_voice_clone | delete | Delete a voice clone |
vlogme_trends_search | read | Search the news |
vlogme_trends_discover | read | News suggestions |
vlogme_news_read_article | write | Read a complete news article |
vlogme_news_get_article | read | Saved article and citation paragraphs |
vlogme_trends_script | write | Write a News Videos script |
vlogme_trends_verify | write | Attach sources to a News Videos script (deprecated alias) |
vlogme_news_presenters | read | Saved news presenters |
vlogme_news_create_presenter | write | Save a news presenter |
vlogme_news_update_presenter | write | Update a news presenter |
vlogme_news_delete_presenter | delete | Remove a saved presenter profile |
vlogme_news_tasks | read | News tasks and shared budget |
vlogme_news_create_task | write | Create a news task |
vlogme_news_update_task | write | Change a news task |
vlogme_news_delete_task | delete | Stop and delete a news task |
vlogme_news_run_task | write | Prepare a manual news story |
vlogme_news_task_runs | read | News task run journal |
vlogme_social_status | read | Social accounts and posts |
vlogme_publish_video | publish | Publish a video |
vlogme_cancel_publication | publish / write | Cancel a publication |
- Tools that only read carry
readOnlyHint. Tools that delete carrydestructiveHint, and their description starts with “Irreversible.”; the description of a tool that makes something public starts with “Public.”, and paid tools say that they charge credits. An agent must confirm these calls with you first. - Arguments are checked against each tool’s schema. A wrong or unknown argument is refused before anything is sent, as a result with
isError: trueandcode: invalid_input. - Every list tool takes
limit(1 to 50, 20 by default) andcursor, and answersnext_cursor(nullon the last page). vlogme_wait_jobandvlogme_director_turnwait up to 30 seconds per call; call them again while the answer hasretry_after_s.- Resources:
resources/readservesvlogme://docs/agents(a guide for agents: from an idea to a video, the money rules, waiting and errors),vlogme://catalog(the job catalogue) andvlogme://openapi(the OpenAPI document).initializereturns short instructions with the same flows.
To start a job through MCP:
- Call
vlogme_quote_jobwithkindandinput, then review the returnedcredits. - Call
vlogme_create_jobwith the samekindandinput, a new UUIDidempotency_key,quoted_creditsset to the returnedcredits, and the unchangedquote_fingerprint. For Aisma, also pass the unchangedquote_prooffrom the quote. - If the quote expires or the price or inputs change, get a new quote and confirm it before trying again. Retry an accepted request with the same
idempotency_keyto receive the same job.
A Director video follows the same rule: vlogme_director_quote_render, show the price, then vlogme_director_render with that quote and an idempotency_key.
An optional webhook_url receives the job events described above. The MCP tools use the same API key, credit balance and price checks as REST.
For Codex, add the server to ~/.codex/config.toml and keep the key in the VLOGME_API_KEY environment variable:
[mcp_servers.vlogme]
url = "https://vlogme.ai/mcp"
bearer_token_env_var = "VLOGME_API_KEY"
tool_timeout_sec = 120
Limits and rules
- Jobs cost the same credits as in the app and come from the same balance; the quote is the price.
- An
Idempotency-Keyis a UUID. Reusing one for a different request is refused. - Aisma jobs need the
quote_prooftheir quote returns. It expires: quote again when it does. - An Aisma job takes an optional
engine:v1orv2, andv2when it is left out. The versions differ in price and in how many reference photos they take;GET /api/catalog?kind=aismastates the limit of each. A quote is for one version: quote again to start on the other. A project opened from a template always runs onv2. - Errors are JSON
{"error": "…", "code": "…"}with the HTTP status:400invalid input (invalid_input),403a request the key’s scopes do not allow (scope_missing,session_required),404not found,409the price, inputs or plan changed,429too many requests,503the service or a provider is temporarily unavailable. - Requests are rate limited. Past a limit the answer is
429withcode: rate_limitedand aRetry-Afterheader: wait that many seconds, then try again. - Through MCP, a refused tool call is not an HTTP error: it comes back as a tool result with
isError: truewhose content is the same JSON (error,statusand, when there is one,code). Only a missing or invalid key (401), an account without API access or a foreignOrigin(403) and a malformed request are HTTP errors there. - Work created through the API follows the Terms of Service like work made in the app.


