Changelog
v1.38.0 - Offline copies of the knowledge base
- A knowledge base can be exported as a static site.
POST /v1/knowledge-base/exportsbuilds a ZIP with branding, sections, articles, images, each article's exported video and a client-side search index; it opens fromindex.htmlwith no server. Pick languages, restrict to tagged articles, and choose whether to include videos (a missing or stale export is rendered first and metered like any export). PollGET /v1/knowledge-base/exports/:id; the list carries presigned download links and astaleflag once the content moves on. See Offline export.
v1.37.0 - Tags on knowledge base articles
- Articles can carry tags. Tags are private labels for filing, never shown on the public site,
and the way you will pick articles for an offline export. The list lives on the knowledge base:
PATCH /v1/knowledge-basewith the fulltagsarray creates, renames and deletes in one call, and a deleted tag is pulled from every article. Assign withtagIdson article create and update; filter the list withtagId.tagIdsstays editable on a locked article. See Tags.
v1.36.0 - Language families, a shared training across languages, and the whole planning half of a lock
- Translating a package now links the two. Both carry a
languageGroup— the id of the first package in the family — so "this instruction in every language" is one request:GET /v1/videos?languageGroup=vid_abc123.translatedFromrecords the one hop. Both arenullon packages translated before this shipped; no migration invented families for them. See Language families. - A translated package now has a training, and it is the SAME training. It used to have none. The translated package points at the source's module and the module gains a translation in the target language, rather than being copied. A copy per language would double every row of the Training Planner and split one requirement's qualification records across several trainings. See What a translation creates.
- In the Knowledge Base, a translated article now plays the video in the reader's language when the package was translated into it, instead of the source-language video under translated text.
- The lock carve-out covers the whole planning half.
settings.availableFrom,settings.availableUntil,settings.qualificationValidDays,settings.requiresTrainerApprovalandsettings.recordAttemptsjoinsettings.mandatoryandkeywordsas editable on a locked module.settings.participantIdentitydeliberately stays frozen: it decides whether a result can be attributed to a person, which is evidence. See Planning metadata and locks. - Approvers are emailed when a planning field moves after they approved it, through the API as well as the app. A signature should never be quietly amended underneath the person who gave it.
- Every one of those fields is now in the change history, not just
mandatoryandkeywords. - Fixed: a saved planning change could look unsaved in the app. Switching to another tab in the training editor and back rebuilt the fields from the module as it was when the page loaded, so a change that had been saved showed its old value — and setting it "again" then recorded nothing, because nothing had changed. The values now survive a tab switch.
- MCP:
list_videosacceptslanguageGroup;languageGroupandtranslatedFromadded to the video output shape.
v1.35.0 - Archived trainings, several keywords, and a record of what a lock lets through
Three changes to the planner and to what a locked module keeps.
includeArchived=truenow actually shows archived trainings. It did not:readiness, which defaults to the narrowest option with trainings behind it, ran afterwards and removed them again, because a retired training is rarely still published. Readiness no longer applies to archived trainings, since a training answers "is this finished" by being archived. See Which trainings belong in a plan.- The keyword filter takes several.
?keyword=Safety&keyword=Annualor?keywords=Safety,Annual. Several keywords are an OR. One keyword behaves exactly as before. See Keywords. - Changes to
settings.mandatoryandkeywordson a locked module are recorded - who, when, and whether the module was locked at the time. Those two fields are the only ones a lock lets through, so an approval that can be amended afterwards needs a trail. Visible in the app on a training's Change history tab. See Planning metadata and locks. - Fixed:
PATCH /v1/modules/:idreplaced the wholesettingsobject. A body carrying only{"settings": {"mandatory": true}}droppedrecordAttempts,participantIdentityandqualificationValidDaysfrom that module. Settings now merge, so a partial update changes only the keys it names. - MCP:
training_planneraccepts an array forkeyword.
v1.34.0 - Twenty more languages
GET /v1/languages now returns 74 languages, up from 54. Nothing else changed: the same codes
still work, and the list is served from the registry the product uses, so no client that reads it
needs a change.
- New codes -
azAzerbaijani,kkKazakh,kyKyrgyz,mkMacedonian,beBelarusian,bsBosnian,isIcelandic,gaIrish,cyWelsh,glGalician,lbLuxembourgish,asAssamese,sdSindhi,psPashto,jvJavanese,cebCebuano,haHausa,soSomali,nyChichewa,lnLingala. Accepted anywherelanguageis - Analyze, Translate, Voiceover and Update Video. psandsdare right-to-left, and are treated as such in subtitles and articles.- MCP:
list_languagesreturns them with no change - it reads the same endpoint. If you cached the list, refresh it.
v1.33.0 - A decision, not a checkbox
The planner's "not applicable" checkbox answered two questions with one blank box: this combination was ruled out, or nobody had looked at it yet. It is now three states. See Which combinations have to be trained.
applicabilityon every planner row -undecided(the state every combination starts in),applicable(somebody deliberately ruled it in) ornot_applicable(somebody deliberately ruled it out). Filter the grid withGET /v1/modules/planner?applicability=undecided.PUT /v1/modules/planner/deadlineacceptsapplicability. Sendundecidedto erase a decision.dueAtand the decision stay independent.notApplicablestill works, everywhere it did.trueisnot_applicable,falseisundecided, and it is still returned on every row.applicabilitywins when both are sent. Cells written before this release read correctly with no migration.includeArchived=truebrings retired trainings back into the planner, flaggedarchivedon the row. They stay out by default - a retired training is not work still to do - but a training somebody completed before it was withdrawn is still a record they may have to produce. The response carriesarchivedCounteither way. This reverses "archived trainings are no longer in the planner at all" from v1.31.0: the right answer was a filter, not a rule.- The CSV export's
N/Acolumn is nowDecision(-,A,N/A), plus anArchivedcolumn. - MCP:
training_plannertakesapplicabilityandincludeArchived;set_training_deadlinetakesapplicability.
v1.32.0 - One package, one name
A workspace can now insist that a video, its help article and its training carry the same title. Off by default, so nothing you already named moves.
naming.syncPackageTitlesworkspace setting. With it on, an article or training generated from a video takes the video's title verbatim instead of writing its own.PATCH /v1/videos/:idcascades a rename. Renaming a video renames its help article and its linked training module in the same request. A locked module is skipped - a lock is irreversible, and an approved round is locked - and the rename still succeeds. Renaming a locked video is still refused with423, unchanged.- Titles edited by hand are left alone. The setting governs generation and rename, nothing else.
- Knowledge Base articles are deliberately not renamed. A published article's title drives its public slug, and a video rename must not churn live URLs.
- MCP:
update_videorenames the package when the setting is on. No request or response fields changed.
v1.31.0 - A planner you can narrow, and a lock that knows what it protects
The planner shows every training against every person, which is what makes it useful and what makes it long. See The planner.
readiness=published|approved|allonGET /v1/modules/planner. A training appears the moment it is defined, so the default now excludes work in progress. Omit the parameter and the server picks the narrowest option that actually has trainings behind it, then reports it back asreadinesswithreadinessCountsfor all three.- Archived trainings are no longer in the planner at all. Archived means retired. The history stays in the analytics endpoints.
keywordson a module — up to 20 tags, 40 characters each, set withPATCH /v1/modules/:id.GET /v1/modules/planner?keyword=Safetyfilters by one, matched whole and case-insensitively, and the response carries every keyword in use in the workspace.settings.mandatoryandkeywordsare now editable on a LOCKED module. A lock freezes the evidence; who must take a training and how it is filed is not evidence. Everything else still returns423, and a request mixing the two is rejected whole. See Planning metadata and locks.- MCP:
training_plannertakesreadinessandkeyword;update_moduletakeskeywords.
v1.30.0 - Filtering for what is missing
Two filters on GET /v1/videos, both for finding the gap rather than the record. See
List videos.
approval=pending|approved|rejected|withdrawn— the latest approval decision on the package. Paired withbackup=noneit is the pre-audit check: signed off, with nothing filed offline.kb=published|not_published|none— Knowledge Base state.not_publishedcovers a video with no article and one whose article is still a draft;noneis the narrower "no article was ever created from it". Resolved from the articles on every request, so it cannot go stale after one is archived or deleted.- MCP:
list_videostakesapprovalandkb.
v1.29.0 - Planning a large grid
The planner is a full cross-product, which is what makes it useful and what makes it long. These are the four ways to cut it down. See Training Modules.
mandatoryon a training —PATCH /v1/modules/:idwith{ "settings": { "mandatory": true } }marks it compulsory for everyone.GET /v1/modules/planner?mandatory=truethen answers "who is missing something they must have" in one call.notApplicableon a cell —PUT /v1/modules/planner/deadlinewith{ "notApplicable": true }rules out a combination that will never be relevant. Ruled-out cells are hidden unless you passincludeNa=true, and never count as overdue. Reversible at any time.dueAtandnotApplicableare independent: sending one leaves the other alone.- Sorting —
sort=urgency|training|person|status|expires|deadlinewithdir=asc|desc. Rows with no value for the sorted column sort last in both directions. - Planner rows now carry
mandatoryandnotApplicable. - MCP:
training_plannertakesmandatory,includeNa,sortanddir;set_training_deadlinetakesnotApplicable, anddueAtis now optional.
v1.28.0 - Setup instructions on saved logins
A saved login now carries the steps the recorder performs on that site before every recording and screenshot, off camera. See Setup instructions.
setupPrompton every item fromGET /v1/recorder-sessions-nullwhen unset.- New
PATCH /v1/recorder-sessions/:domain-{ "setupPrompt": "..." }sets it,nullclears it. Up to 2000 characters.404when the domain has no saved login. Requiresrecordings:write. - A recording started with its own
setupPromptstill wins for that job; the session's is unchanged. - MCP:
list_recorder_sessionsreturnssetupPrompt; newupdate_recorder_sessiontool.
v1.27.0 - The training planner
Who has not done a training, which every other training endpoint is structurally unable to answer. See Training Modules.
- New
GET /v1/modules/planner— one row per (training, person), most urgent first. Includes people who have never attempted anything, sostatus: "not_started"finally has somewhere to appear.daysToDueis negative once a deadline has passed. - New
PUT /v1/modules/planner/deadline— the date by which one person must complete one training.dueAt: nullclears it. A deadline is an expectation, not a record, so it can be set on somebody who has never attempted the training. - New
GETandPOST /v1/modules/people— the training roster. Adding somebody before they have trained at all is what makes "has never done it" visible for a new employee. Idempotent on email. - Statuses:
passed,renewed,expired,awaiting_signoff,in_progress,not_started.renewedmeans a qualification lapsed and was earned again; renewing early, before expiry, is not a gap and stayspassed. unattributedAttemptsreports attempts recorded without an email, which belong to nobody on the grid rather than being silently dropped.
v1.26.0 - Knowledge Center sub-sections
Sections in the Knowledge Center can now nest one level deep. See Sub-sections.
- New
parentIdon every section returned byGET /v1/knowledge-base/sections, create, update andreorder.nullfor a top-level section, otherwise the id of its top-level parent. Sections created before this release come back withparentId: null. - Accepted on
POSTandPATCH /v1/knowledge-base/sections. The parent must exist, belong to the same knowledge base, and be top-level; a section cannot be its own parent; a section that already has sub-sections cannot be nested. Each of these is a400 validation_error. DELETE /v1/knowledge-base/sections/:idnow returns400while the section still has sub-sections, alongside the existing409while it still holds articles.positionorders siblings.reordernumbers top-level sections and each parent's sub-sections as separate groups, so a mixed list never interleaves them.- Nothing moves: slugs stay unique across the whole knowledge base and public URLs stay flat, so nesting a section never breaks a link.
- MCP:
list_kb_sections,create_kb_section,update_kb_sectionandreorder_kb_sectionscarryparentIdin their input and structured output.
v1.25.1 - Package backup state on videos
Which published content has no offline backup yet, in one query.
- New
packageDownloadobject on list and get, recording when a video's package ZIP was last built and by whom.nullmeans never. - New
backupfilter on list:nonefor videos that have never had a package built,takenfor those that have. - Stamped when the ZIP finishes building and its link is sent, not when someone clicks that link. The build is what answers "has a backup been taken".
v1.25.0 - Read-only projects
A project folder can now be readable by the whole workspace while only a named few can change what is in it. See Project Access.
- New
"readonly"value foraccess.modeon create and update, alongside the existingworkspaceandrestricted.memberIdsnow means "who may see it" underrestrictedand "who may change it" underreadonly. - New
folder_read_onlyerror code,403. Returned by every write against an item in a read-only project: editing, generating, translating, voiceover, locking, archiving, requesting approval, publishing, moving, duplicating and deleting, plus renaming or deleting the project. - Reads are untouched. Listings include the project, videos open, and the package ZIP still downloads - a read-only project is meant to be consumed.
- Deciding an approval and commenting stay open to anyone who can see the project. Approvers are named explicitly, and a comment is feedback about a package rather than part of it.
403here, not404: the caller can see the item, so it says why. A restricted project keeps answering404.- Filing something new into a project - a video, a Studio project, a remix - is now checked as a
write against the target project on every path that accepts a
projectId.
v1.24.1 - Studio projects know where they came from
A video in the app can now be opened directly in Studio, which rebuilds it as editable layers. When that happens the resulting Studio project records which video it came from.
- New
sourceVideoIdonGET /v1/studio/projectsand the single-project endpoint. It is the id of the video the project was imported from, ornull. - Informational only. The video is a separate object: it is not locked, hidden or otherwise changed by the Studio project pointing at it, and it may since have been deleted.
- Set once, when the project is created. It is not writable, and duplicates and templates made from such a project do not inherit it - the relation belongs to the one project built from that video.
v1.24.0 - Project access
A project folder can now be limited to specific people instead of the whole workspace. See Project Access.
- New
accessobject on create, update, get and list.{ "mode": "workspace" }is the default every project already had;{ "mode": "restricted", "memberIds": [...] }limits it. - A restricted project, and every video filed in it, returns
404 not_foundfor anyone who can't reach it - not403. Listings simply omit it. - Workspace owners and admins always have access, listed or not. Otherwise a project could be stranded with nobody able to reach it.
- API keys are not subject to restrictions - a key authenticates as a workspace, not a person. OAuth tokens are, and see exactly what their user sees in the app.
- Setting
accessneeds the permission to manage members. An update that omits it leaves the current setting alone, so a rename can't quietly open a project up. - Videos that aren't filed in a project stay visible workspace-wide, and existing share links keep working.
- The check covers every endpoint that reads or acts on a video - analyze, export, translate,
voiceover, article, subtitles, script, download, update, delete, governance, and job polling - plus
the ones that pull a video's content elsewhere: remixes, module generation, course creation and
knowledge-base/articles/from-video. Moving a video into a restricted project is checked too. - Studio projects, remixes and courses are filed in projects as well, and hide with them - on
GET /v1/studio/projects,GET /v1/remixes,GET /v1/coursesand each of their single-item endpoints.
v1.23.0 - AI Recorder on every paid plan
The AI Recorder is no longer an add-on you have to ask for. Every paid plan
includes it, so POST /v1/recordings works on any workspace that isn't on the free plan.
- A free-plan workspace still gets
403. So does a workspace whose subscription has lapsed, for as long as it stays lapsed. - New
429- two recordings run per workspace at a time. Recording browsers are a shared pool, so a start beyond that is refused rather than queued indefinitely. A job that is waiting for a free browser reportsprogress.step: "queued". - A
429returnsrate_limit_exceeded, notlimit_exceeded. It means wait, not buy credits.
v1.22.1 - AI provenance for courses and Studio
The Art. 50(2) marking now covers the two remaining places Vidocu writes text.
- Courses -
aiProvenanceonGET /v1/courses,GET /v1/courses/:idandGET /v1/courses/:id/storyboard(per module), plus anX-Content-Provenanceheader on the storyboard response and the record on the public course share payload. Generating a module now also marks the narration on the resulting video, so every video surface inherits it. - Studio -
aiProvenanceonGET /v1/studio/projects/:idwhen the assistant wrote text in the project. Recorded at project level and server-owned: the editor only reports that the assistant acted, and the record is stamped server-side so it can't be forged.
Still nothing visible, still no setting.
v1.22.0 - AI provenance
Text Vidocu generates is now marked as machine-generated in a machine-readable form, meeting our Article 50(2) obligation under the EU AI Act ahead of the 2 December 2026 date.
aiProvenanceon the article and subtitles responses, plus anX-Content-Provenanceheader on both and ondownload.- The same record is written into each export format's own metadata slot - XMP for PDF, custom
document properties for DOCX,
<meta>tags for HTML and knowledge-base pages, aNOTEblock for WebVTT, andmanifest.jsonfor the package ZIP. humanEditedis derived by comparing the stored text against the hash taken at generation, so it reflects what actually happened rather than a flag someone had to remember to set.
Nothing visible changed. No badge, no label, no difference in how an article, PDF or knowledge-base page renders. There is no setting: the duty falls on us as the provider of the generation system, not on the workspace.
SRT and Notion have no metadata slot that leaves the content untouched, so their marking travels alongside - header, manifest and sidecar. The reasoning is written up in full.
v1.19.1 - Custom caption height
captions.positionPercenton export - withposition: "custom", place burned-in captions anywhere from0(as high as they go) to100(as low as they go) instead of only top, middle or bottom.- Both ends stop at a safe margin and the caption is anchored by its own edge, so no value can push it off screen. Out-of-range numbers are clamped.
top,middleandbottomrender exactly where they always did.
v1.21.0 - Studio export
POST /v1/studio/projects/:id/export renders a Studio timeline to video. Returns a job to poll;
counts as one export against the plan.
Together with the timeline endpoint this closes the loop: build a timeline over the API, render it, download the result - no editor required.
The render logic moved to lib/studioExport.ts so the dashboard and the API run the same code
rather than two copies of the Remotion composition props.
v1.20.0 - Studio
The multi-track editor's projects.
- Projects - list, create, get, rename, delete. The list returns timeline counts; a single project returns tracks, clips and media in full.
- Duplicate - copies the timeline, never the share link or export state.
- Share links - idempotent minting, with visibility as a separate switch so revoking doesn't break the URL.
- Templates - the workspace's own plus the global gallery.
The timeline is read-only through the API: it's a large interdependent document the editor owns. Exporting isn't exposed yet - it needs the same extraction Remix export went through.
New scopes: studio:read, studio:write.
v1.19.0 - Remix export and regenerate
The two Remix endpoints v1.17.0 shipped without.
POST /v1/remixes/:id/export- blog, LinkedIn and X return their content immediately; shorts and trimmed cuts start a render and return a job.POST /v1/remixes/:id/regenerate- rewrite a text output from the analyzed transcript. Free, and it replaces the existing draft.
Both run the same code as the dashboard rather than a second copy, so the lambda payloads and the generation prompts exist in exactly one place.
v1.18.0 - Training Modules + Brand Kit assets
- Training modules - generate, edit, lock, translate, and the compliance records around them: attempts, passers, trainer sign-offs and workspace analytics.
POST /v1/modules/:id/submitrecords a graded attempt. Grading runs server-side against the answer keys, so an LMS integration never needs them.- Answer keys are included by default on a single module and excluded everywhere else; pass
forLearner=truefor the learner-safe shape. - Brand Kit assets -
GET|POST /v1/brand-kit/assets,DELETE /v1/brand-kit/assets/:id.
New scopes: modules:read, modules:write.
v1.17.0 - Remix
One long video into shorts, a blog post and social copy.
- Create and analyze -
POST /v1/remixes,POST /v1/remixes/:id/analyze. Sourced from a workspace video or an external URL. - One analysis per workspace at a time. A second request returns status
queuedrather than failing, and starts on its own. - Read, update, delete plus
GET /v1/remixes/:id/exports.
Starting an export and regenerating drafted copy are not exposed yet - both need extracting out of their session-bound handlers first, so the API and dashboard run the same code.
New scopes: remixes:read, remixes:write.
v1.16.0 - AI Recorder
Describe a flow, get a screen recording.
- Start a recording -
POST /v1/recordings. Long-running; poll the job. - Status carries two distinct failure shapes:
aborted(no usable video) andpartial(a video that doesn't show the whole flow). Don't treat a partial recording as finished. POST /v1/recordings/:jobId/input- hand over a one-time code or 2FA challenge when the agent pauses for one.- Download returns a time-limited URL rather than the bytes.
- Saved logins -
GET /v1/recorder-sessions,DELETE /v1/recorder-sessions/:domain. Stored cookies are never returned.
Charged per minute of finished video on completion, with a preflight balance check. Failed and aborted jobs are free.
New scopes: recordings:read, recordings:write.
v1.15.0 - Knowledge Center
The hosted help site, end to end.
- Knowledge base -
GET|POST|PATCH|DELETE /v1/knowledge-base. One per workspace, so it's a singular resource. - Sections and articles - full CRUD, cursor-paginated listing, Markdown content.
POST /v1/knowledge-base/ask- retrieval-grounded answers with citations, for support-bot integrations. Answers from your published articles, not from general model knowledge.- Import from video, translation, reindex, redirects and analytics.
Locked articles are frozen to sectionId, state and seo; publishing respects the source video's
approval round.
Knowledge Center AI operations bill against the add-on's own AI credit pool, not the workspace credit balance.
New scopes: knowledge_base:read, knowledge_base:write.
v1.14.0 - Locks & Approvals
The controls that make a video library auditable.
- Locks -
POST|DELETE /v1/videos/:id/lock. Freezing cascades to the linked training module and KB articles. Unlocking is refused while an approval round is open. - Approvals - request, list, decide, withdraw. Every named approver must approve; one rejection fails the round. Only a named approver can decide, and only once.
- Comments - review notes, optionally pinned to a timestamp.
Actions record who performed them: OAuth tokens are attributed to their user, API keys to the workspace owner. For per-person attribution in an audit trail, use OAuth rather than a shared key.
New scopes: locks:write, approvals:read, approvals:write, comments:read, comments:write.
v1.13.0 - Courses
Turn a document or an existing video into a set of modules, each of which becomes one video.
- Courses -
POST /v1/coursesfrom a PDF, DOCX, PPTX, Keynote, TXT or an existing video; list, read, update and delete. - Storyboard -
GET|POST /v1/courses/:id/storyboard. The read includesomissions(source content deliberately left out) andwarnings, so a review can see what was skipped on purpose. - Generate -
POST /v1/courses/:id/generaterenders one module into an ordinary video, which then works with export, translate and everything else.
Each step is async and returns a jobId. Only one step runs per module at a time - a second
request gets 409.
New scopes: courses:read, courses:write.
v1.12.0 - Brand Kit
The settings that keep generated output on-brand are now readable and writable by API. They were always applied - nothing could inspect or change them, so an API-only integration was stuck with whatever the dashboard had.
- Brand Kit -
GET|PATCH /v1/brand-kit: music, scenes, watermark, background, caption and article styling, default voice and language. - Pronunciations - how words should be said in narration.
- Brand skills - reusable style guides, applied per video via
scriptSkillIdon analyze. - Glossary - brand terms and their translations, including CSV import with merge or replace. This feeds the translation pipeline, so it directly improves translation quality.
New scopes: brand_kit:read, brand_kit:write.
v1.11.0 - Phase 1 complete
- Create a photo avatar -
POST /v1/avatars, from a public image URL. Enterprise plan; new scopeavatars:write. - Article styling -
styleon generate and fetch, returned asarticleStyleso embedded HTML can be rendered on-brand. Presentation only; the wording is unchanged. - Cursor pagination on projects - now on all three collection endpoints.
API keys created in an admin or internal workspace now carry admin status. Previously only OAuth tokens did, so an admin's API key was metered and throttled like any customer's.
v1.10.0 - The rest of the options
- Voiceover:
model,speed,stability. - Analyze:
keyEvents,analysisModel,subtitleModel,autoZoom. - Export:
reframe,slides,avatarSettings. - Get the article -
GET /v1/videos/:id/article, in Markdown or HTML, without regenerating it. - Get one avatar -
GET /v1/avatars/:id. - Delete a cloned voice -
DELETE /v1/voices/:id. New scopevoices:write. - WebVTT -
download?type=vtt, generated from the subtitles, so it works without an export. - Cursor pagination on
/v1/videosand/v1/jobs.pagestill works;cursoris what to use when walking a collection that's changing under you.
Not available through the API, with reasons: article PDF/DOCX export and auto-extracted screenshots (both need capabilities the API service doesn't carry), voice cloning (needs recorded consent), and voiceover loudness matching (only applies to single-clip regeneration).
v1.9.0 - Scripts, downloads, webhooks and idempotency
The last of the gaps that made the API awkward to build against.
Edit the script
- Get and replace a video's timed lines - the text burned in as subtitles and spoken as narration. Fix a typo without re-analyzing.
- Editing a line's text drops the narration generated from it, so an export can't say something
the subtitles no longer show.
voiceoverInvalidatedLinestells you how many lines were affected; untouched lines keep their audio.
Get your files
- Download -
GET /v1/videos/:id/download?type=…for the exported video, the source, the voiceover audio, the SRT, or the thumbnail. Returns a clear reason when the file isn't ready instead of anullfield.
Manage webhooks
- Create, update and delete webhooks through the API. Previously dashboard-only, so an integration couldn't provision its own delivery endpoint.
- The signing secret is returned once, at creation. Re-enabling a failed webhook resets its failure count.
Retry safely
- Idempotency - send
Idempotency-Keyon anyPOSTand the request runs once, however many times it arrives. A duplicate export or tool run costs real money; this is the general fix.
More options
- Voiceover gained
sentencePauseSecondsandapplyPronunciations(on by default, matching everywhere else in Vidocu). - Article gained
language,instructionsandformat(markdownorhtml).
New scopes: webhooks:read, webhooks:write. subtitles:write now also covers script edits.
v1.8.0 - Look up voices, avatars and what things cost
Three reference endpoints, plus a machine-readable spec.
- Voices -
GET /v1/voices.voiceIdwas a required parameter with no way to discover a valid value, so callers copied one out of the dashboard. Your own cloned voices come first, markedcustom: true. - AI Avatars -
GET /v1/avatars. Searchable by name; your workspace's photo avatars always come first. - Credit costs -
GET /v1/usage/credits. What each operation costs alongside your balance, so you can price a job before starting it. - OpenAPI spec -
openapi.json, generated from the server's own validation schemas rather than written by hand, so it can't drift from what the API accepts.
New scopes: voices:read, avatars:read. Available through MCP as list_voices, list_avatars
and get_credit_costs.
v1.7.1 - Tool runs are charged on completion
Tool runs started through the API were checked against your balance at dispatch and then never deducted - the run happened, the balance didn't move. They're now charged when the run succeeds, using the quantity the renderer reports rather than the estimate in your request.
- A failed run costs nothing. Charging happens on success, not dispatch.
- The billed quantity is the real one - actual output duration, actual slide count.
- Grandfathered minutes plans are unaffected - tool runs remain uncharged there.
If you've been running tools through the API, expect balance.used in GET /v1/usage to
start moving where it previously stood still.
v1.7.0 - Control how videos are analyzed and rendered
Export accepted one field, language. Everything else came from the stored
video and your Brand Kit, so "render this one vertical without a watermark" wasn't expressible.
It now takes per-request overrides: ratio, watermark, captions, music, openingSceneUrl,
closingSceneUrl, zooms and elements. Precedence is request > video > Brand Kit, and the
overrides apply to that render only - nothing stored changes. Pass false to drop a whole track:
{"watermark": false, "music": false}.
Analyze gained the options the product has had all along: contentStyle
(how-to, sop, promotional, training, announcement), productName, scriptSource
(analyze the footage, reuse the transcript, keep the original audio, or supply your own script),
customScript, scriptSkillId for a Brand Kit style guide, and forceRefresh.
Both are available through the MCP server on export_video and analyze_video.
v1.6.0 - Manage videos, find jobs, look up languages
Four endpoints that were missing rather than broken.
- Update Video -
PATCH /v1/videos/:id. Rename, move between projects, or adjust the context used when generating content. A locked video can still be moved; anything else returns423. - Delete Video -
DELETE /v1/videos/:id. Removes the video and its stored files. Until now you could create videos through the API and never remove them. Locked videos are refused. - List Jobs -
GET /v1/jobs. Recent jobs newest first, filterable bystatusandtype, for when you've lost ajobId. - Languages -
GET /v1/languages. All 54 supported languages with the exact codesanalyze,translate,voiceoverandsubtitleLanguageexpect, so you don't have to guess one and get a400.
All four are available through the MCP server as update_video, delete_video, list_jobs and
list_languages.
v1.5.0 - Locks, roles, and honest tool pricing
Four corrections to existing endpoints. Nothing was renamed or removed.
Locked content is now respected
A locked video's content is frozen while it moves through an approval cycle. The API previously
ignored locks entirely: analysis, voiceover, translation and article generation would all overwrite
a locked package, and DELETE /v1/projects/:id?cascade=true would delete locked videos along with
their stored files.
- Those four operations now return
423 Locked - A cascading project delete is refused if the project holds any locked video
GET /v1/videosandGET /v1/videos/:idreturnlockedandlock- Exporting a locked video still works - rendering from frozen content is the point
Workspace roles apply to OAuth tokens
Scopes describe what an integration asked for; the workspace role behind the token describes what
that person may do. Both are now enforced, so a token minted by a viewer can hold videos:write
and still be refused with 403 insufficient_role.
API keys are unchanged - a key authenticates as a workspace, not a user, and keeps full workspace permissions.
Tools bill at their real rate
Every tool executed through the API used to bill the same flat per-run rate regardless of what it did. Each tool now bills against its own entry: per minute, per slide, or per run. Most are unchanged at 1 credit per minute; the expensive ones are now charged properly (AI avatar generation is 150 credits per minute). See Execute Tool.
Presentation tools (PDF, PPTX, Keynote, Google Slides to video) now execute correctly through the API; previously they were dispatched to the wrong backend.
AI avatar generation and subtitle burning now work through the API. Both render inside Vidocu
rather than on the tool backend, so they were previously unreachable. They behave like any other
tool - 202 with a jobId - except they don't fire a tool.completed webhook, so poll
GET /v1/jobs/:id for those two. List Tools reports apiSupported
for every tool; it's false only when a tool genuinely can't be reached.
Usage reports your actual unit
GET /v1/usage now returns billingModel and a unit-tagged balance block. Most
workspaces are billed in credits, which the old videoMinutes field labelled as minutes. That
field is kept with the same values and is now deprecated.
v1.4.1 - API keys on every plan
The REST API is no longer gated to Business. API keys now work on every Vidocu plan, including Free - same as the MCP integration. Your plan only determines your monthly allowance and max video duration per request. See Plans & Limits.
v1.4.0 - API access included with Business
The standalone API plans (Starter, Growth, Scale) are gone. API access is now part of your Vidocu plan.
- REST API (API keys) is available on the Business plan and above. There's no separate API subscription to buy.
- The Claude / MCP integration works on any plan when you connect with OAuth.
- One shared meter. API usage now draws from the same monthly video-minute allowance as the app, instead of a separate API quota.
- Fixed rate limit of 60 requests/minute for every plan.
- No more per-feature gating. Translation, voiceover, and
/processare available to every API caller. Within/process, only analysis and translation consume minutes; voiceover, export, and help articles are free.
See Plans & Limits for the full breakdown.
v1.3.0 — MCP Server
Connect Vidocu to AI assistants like Claude via the Model Context Protocol.
- MCP server at
mcp.vidocu.ai— 15 tools covering all API operations - Streamable HTTP transport, stateless, works with Claude Desktop and other MCP clients
- Authenticate with your existing API key via
X-Vidocu-Api-Keyheader
v1.2.0 — One-Shot Processing
Process a video end-to-end with a single API call. Upload a video URL and specify which operations to run — the API chains them automatically and reports progress via job polling or webhooks.
New endpoint
- Process video —
POST /v1/videos/process— upload + analyze + optionally generate voiceover, help article, export, and translations in one request (Business+)
New webhook events
process.completed— all pipeline steps finished successfullyprocess.failed— a step in the pipeline failed
Improvements
- Analysis results (subtitles, key events, status) are now persisted to the video document immediately after analysis completes, so
GET /v1/videos/:id/subtitlesreturns results without requiring a separate save step
v1.1.0 — Tools API
Execute free tools (video trimmer, subtitle translator, transcript extractor, etc.) programmatically through the API.
New endpoints
- List tools —
GET /v1/tools— discover all available tools and their parameter schemas - Get tool —
GET /v1/tools/:type— get a single tool's full definition - Execute tool —
POST /v1/tools/:type/execute— run a tool and get a job ID
Improvements
tool.completedandtool.failedwebhook payloads now includetoolTypeandresultfields- Job polling (
GET /v1/jobs/:id) now supports tool jobs - Usage tracking includes
toolExecutionscounter
v1.0.0 — Initial release
The Vidocu API v1 is now available.
Endpoints
- Upload —
POST /v1/videos/upload - List videos —
GET /v1/videos - Get video —
GET /v1/videos/:id - Analyze —
POST /v1/videos/:id/analyze - Export —
POST /v1/videos/:id/export - Translate —
POST /v1/videos/:id/translate(Growth+) - Subtitles —
GET /v1/videos/:id/subtitles - Voiceover —
POST /v1/videos/:id/voiceover(Growth+) - Article —
POST /v1/videos/:id/article - Jobs —
GET /v1/jobs/:id - Usage —
GET /v1/usage
Features
- API key authentication (
vdo_live_format) - Per-key rate limiting with response headers
- Webhook delivery with HMAC SHA-256 signatures
- 4 plans: Starter, Growth, Scale, Enterprise
- JSON and SRT subtitle formats