Changelog
v1.89.0 - Add any part of the transcript to a clip
- New
addandremoveonPATCH /v1/remixes/:id/moments/:momentId: bring a span of transcript into a clip from anywhere in the webinar, or take one out. Adding text outside the clip skips what sits in between. See Update a moment. MCP:update_remix_moment. - Retrimming keeps your cuts. A new
startorendno longer works out the cuts again for the whole clip: cuts already in it stay, and only the newly covered part gets new ones.
v1.88.0 - 16:9 clips for YouTube
- New
clipStyle.ratiovalue16:9onPATCH /v1/remixes/:id: clips made 1920x1080, ready for YouTube. They show the whole webinar frame; set a moment'sframingto crop in. See Style. MCP:update_remix.
v1.87.0 - Name a recording when you start it
- New
nameonPOST /v1/recordings: give the recording its display name up front instead of renaming it after. See Start a recording. MCP:start_recording.
v1.86.1 - Sharper speakers in split clips
- A small camera gets a shorter top part in split clips (down to 30% of the clip), and the speaker is lightly sharpened, so a small thumbnail isn't blown up into a blur. A tiny camera shows as a card over the screen instead. Clips made before show as changed.
v1.86.0 - Split-screen clips
- New
framingmodestackonPATCH /v1/remixes/:id/moments/:momentId:topandbottomboxes, each filling half the clip. See Update a moment. MCP:update_remix_moment. - Clips made automatically now split like Reels: the speaker on top, the shared screen below, captions on the line between. Two or three people on a call stack. Clips made before keep their look until you make them again; they show as changed.
v1.85.0 - Articles in one language
- New
sourceLocaleonPOST /v1/knowledge-base/articlesandPOST /v1/knowledge-base/articles/from-video: write an article in any enabled locale, not only the knowledge base's main one. It is shown only to readers in that language until it is translated. The language is fixed once created; a differentsourceLocaleonPATCHreturns400. See Articles in one language. MCP:create_kb_article,kb_article_from_video. - Articles return
sourceLocale, andGET /v1/knowledge-base/articlesfilters by it. MCP:list_kb_articles,get_kb_article. POST /v1/knowledge-base/articles/:id/translatetranslates from the article's own language, so the main language can be a target. MCP:translate_kb_article.
v1.84.0 - Larger glossaries
- Glossary cap raised from 200 to 10,000 entries on
PUT /v1/brand-kit/glossaryandPOST /v1/brand-kit/glossary/import(CSV up to 10 MB). Translation now uses only the terms that appear in the text being translated. See Glossary. MCP:set_glossary,import_glossary.
v1.83.0 - Webinar remixes
- New
planonPOST /v1/remixes: makes a webinar remix. Clips of the real speaker, a 16:9 recap and posts, from up to 90 minutes of source.rangepicks the part to use, and only that part is billed. See Webinar remixes. MCP:create_remix. - New
PATCH /v1/remixes/:id/moments/:momentIdandPOST /v1/remixes/:id/moments: keep, drop, rename and retrim moments, or add your own. MCP:update_remix_moment,add_remix_moment. - New
PUT /v1/remixes/:id/recap: the recap's order, with title cards. MCP:set_remix_recap. - New
outputTypevaluesclipsandrecaponPOST /v1/remixes/:id/export: make the kept clips (ormomentIds) and the 16:9 recap. Anything already made from the same edits is skipped and free; credits are charged when each video is ready. See Clips and the recap. MCP:export_remix. - New
clipStyleandrecapStyleonPATCH /v1/remixes/:id: shape, captions, headline, closing card and logo. MCP:update_remix. Moments take ahookText, and aframingto frame a clip by hand (a crop, a shared-screen window with the camera as a card, or the whole frame). MCP:update_remix_moment. Made clips' export rows carry theshotsthey were framed with. GET /v1/remixes/:idnow returnspipelineVersion,plan,recap,clipStyle,recapStyleandanalysisProgress.get_remixreturns them too, along withanalysis. Export rows addprogress,durationSecandcreditsCharged(andshotson clips).- Remix credits: analysis is 3 credits per source minute.
POST /v1/remixes/:id/regeneratenow costs 1 credit per run (it was free) and returns402when the balance is short.
v1.82.0 - Module builds priced by video length
doc_video_generateis now 50 credits per minute of finished video (was 5 credits per build), the same rate as assembly guides. A 3-minute module costs 150. The build checks the module's estimated length before it starts and is charged on the length it comes out. Applies toPOST /v1/courses/:id/generate,POST /v1/courses/:id/buildandPOST /v1/videos/from-document.
v1.81.0 - Longer recording prompts
POST /v1/recordings:promptnow takes up to 50,000 characters, up from 5,000, so a full training script fits. See AI Recorder.
v1.80.0 - Video from a document, one-step module builds
- New
POST /v1/videos/from-document: one finished video from a document, unattended, with optionalpaceandaiVideo. See Create a video from a document. MCP:create_video_from_document. - New
POST /v1/courses/:id/build: a module's video in one call (storyboard when needed, AI visuals, narration, slides), returning thevideoIdat once. See Build a module in one step. MCP:build_course_module. - Fixed
POST /v1/courses: courses created through the API now read the document (or the video's narration) before planning. Before, planning failed with "No extracted pages to plan from."
v1.79.0 - Course pace and AI video
- New
pacefield on courses:snackable,course(default) orinDepth. It sets module length, scene pace, the narration's voice and, forsnackable, big captions. Set it onPOST /v1/coursesorPATCH /v1/courses/:id;GET /v1/courses/:idreturns it. See Pace. - New
aiVideofield on courses:{ enabled, stylePresetId }replaces stock photos with AI-generated pictures and a few short looping clips. Business and Enterprise only; other plans get403 limit_exceeded. Generate makes the pictures, charged asai_footage_stillandai_footage_clip, and checks the most a module can cost before it starts. See AI video. MCP:create_course,update_course,get_course. ai_footage_clipnow costs 16 credits (was 40), for courses and Studio alike.- Exported videos with AI pictures now carry the AI footage marking in their metadata.
v1.78.0 - Opening slide duration
- New
openingSlideDurationfield on the Brand Kit: how long the title slide at the start of a new video is held, 2-60 seconds (default 5). Returned byGET /v1/brand-kit, set withPATCH /v1/brand-kit(nullresets it). See Opening slide. MCP:update_brand_kit.
v1.77.0 - Account context on saved logins
- New
contextfield on saved logins: who the login is and what it can see and do, for example "Teacher account: manages classes, assigns lessons, sees grades". Every item ofGET /v1/recorder-sessionshas it (nullwhen unset), andPATCH /v1/recorder-sessions/:sessionsets it (up to 2000 characters,nullclears). It is never performed as steps: Pulse uses it to write docs for the right audience. See Account context. MCP:list_recorder_sessions,update_recorder_session.
v1.76.0 - Company sign-in for knowledge base readers
- New
access.authMethodvalueoidconPATCH /v1/knowledge-base: readers of a gated knowledge base sign in through your own identity provider (OpenID Connect). Enterprise plan; we set up the connection first, and until thenoidcreturns400.GET /v1/knowledge-basecan now returnoidcinaccess.authMethod. See Company sign-in. MCP:update_knowledge_base.
v1.75.0 - Module translation uses credits
POST /v1/modules/:id/translatenow charges credits:module_translateper module per target language, on success only. If the balance can't cover every target, nothing is translated and the call returns403 limit_exceeded. Listed inGET /v1/usage/credits. A module translated as part of a video translation isn't charged again. See Translation. MCP:translate_module.
v1.74.0 - Translation pricing: knowledge base articles and slide videos
POST /v1/knowledge-base/articles/:id/translatenow charges credits from the workspace credit balance:kb_article_translateper article per target language, on success only. If the balance can't cover every target, nothing is translated and the call returns403 limit_exceeded. The price is listed inGET /v1/usage/credits. See Translation. MCP:translate_kb_article.- No limit on locales. A knowledge base can enable as many locales as you need. The dashboard no longer stops at 3.
- Video translation is now 10 credits per minute per target language (was 8). See
GET /v1/usage/credits. - A video made of slides is now priced on its full length when translated, including 3D assembly and assembly-guide videos. It used to be priced on its 1.5-second carrier clip, which billed 1 credit however long the slides ran.
v1.73.0 - Several saved logins per site
- A site can now have several saved sessions, for example "Sandbox" and "Admin user". Every
item of
GET /v1/recorder-sessionshas new fieldsid,name,isDefaultandcreatedBy. One session per site is the default. See Saved logins. MCP:list_recorder_sessions. - New
sessionIdfield onPOST /v1/recordingspicks the session to start signed in with. Leave it out to use the site's default. See Pick a session. MCP:start_recording. PATCHandDELETE /v1/recorder-sessions/:sessiontake a session id. A domain still works and means that site's default session.PATCHhas new fieldsnameandisDefault. See Rename it, or make it the default. MCP:update_recorder_session.DELETEby domain returns409when the site has more than one session, and lists them. Delete by id instead. The response now includesid. Deleting the default makes the most recently used remaining session the new default. See Delete a session. MCP:delete_recorder_session.
v1.72.0 - AI footage is for paid plans only
- Trials can no longer generate AI footage. Every
/v1/ai-mediagenerate endpoint (shot, stills, clips, scenes, scene translation) now returns402on a trial, as it already did on the free plan. Listing and fetching past generations still works. See AI footage.
v1.71.0 - Faster AI clips
- AI clips now run on HeyGen Video 1.0 (
model: "heygen-video-1") instead of Veo 3.1 Lite. A clip usually finishes in under a minute and follows the motion in the shot more closely. Same request, samedurationSecandresolutionvalues, same credits. See Animate a still. - Clips carry generated ambient sound (no music or speech) and can run slightly past
durationSec. Studio places them muted and cut to length; do the same on the timeline API. - At
720pthe frame follows the still (1344×768 for a 16:9 still).
v1.70.0 - Scenes timed to the voiceover, translated, with your logo
- Scene items carry
anchor(the narration words where each is spoken) when you sendnarration. Studio uses them to reveal each step as it is said; synced scenes carryrevealAt. See Animated scenes. - New
POST /v1/ai-media/scenes/translatetranslates a scene's on-screen text, keeping layout, numbers, colors and timing. Charged on success. MCP:translate_ai_scene. - Scenes show your Brand Kit logo (
theme.logoUrl) unlessshowLogoisfalse. - Refine a shot:
POST /v1/ai-media/shotacceptscurrentandchangeand returns the same shot with only that changed. MCP:plan_ai_shot.
v1.69.0 - Animated scenes
- New
POST /v1/ai-media/scenesdesigns a short motion-graphics scene in your Brand Kit colors and font from a description or narration: a process flow, checklist, key number, comparison, key points or timeline. Place it on a Studio timeline as a clip oftype: "scene"; its text, colors and font stay editable. See Animated scenes. Charged on success. MCP:create_ai_scene. - New
routefield onPOST /v1/ai-media/shot:footage,animationorscreen, the tool that fits the request. - Studio timelines accept clips of
type: "scene"inPUT /v1/studio/projects/:id/timeline.
v1.68.0 - AI footage
- New AI footage endpoints generate B-roll that matches your narration, stills
first:
POST /v1/ai-media/shotplans a shot and warns when AI video is the wrong tool (free),POST /v1/ai-media/stillsgenerates 1-4 stills, andPOST /v1/ai-media/clipsanimates one into a silent 4, 6 or 8 second clip (pollGET /v1/ai-media/:id).GET /v1/ai-medialists them. Twelve style presets, including illustrated ones for kids and teens, and astyleNotefor your own look. Stills and clips are charged on success only; see Credit costs. Scopes:studio:read,studio:write. MCP:plan_ai_shot,generate_ai_stills,animate_ai_still,list_ai_media,get_ai_media. - Studio exports that use AI footage are marked as containing AI-generated content in the MP4's metadata.
v1.67.0 - Video Intro Maker
- New tool
video-intro-maker: turns a logo into an animated 4, 6 or 8 second MP4 intro in16:9,9:16or1:1, in one of 11 styles. Run it with Execute a tool;GET /v1/tools/video-intro-makerlists every parameter. Each run is charged once, as a flat per-run tool charge. MCP:execute_tool.
v1.66.0 - Keep saved logins longer, cut page loads
- New
ttlDaysfield onPATCH /v1/recorder-sessions/:domain:14(default),30,90,180or365days after the session was last used.setupPromptis now optional on the same call, and a field you leave out stays as it is. See How long a session is kept. MCP:update_recorder_session. - New
ttlDaysfield on every item ofGET /v1/recorder-sessions. - New
removeLoadingoption onPOST /v1/recordings. Whentrue, the waits while pages load are cut out of the video. Defaultfalse. See AI Recorder. MCP:start_recording.
v1.65.0 - Rename AI recordings
- New
PATCH /v1/recordings/:jobIdwith{"name": "..."}sets a recording's display name, andnullclears it. The dashboard's recordings list shows the name instead of the prompt. See AI Recorder. MCP:update_recording. - New
namefield on every recording response (nullwhen unset). Thepromptis unchanged.
v1.64.0 - Scripts checked against the screen
- Analysis now checks the script against the video. After Analyze writes the script, each line is checked against what is on screen during its window. An AI-written line that narrates the wrong moment is rewritten to describe its own window, with the same timing. A script you supplied keeps its words: a line may only be moved to the moment it describes.
- New
unverifiedfield on subtitle lines inGET /v1/videos/:id/subtitles(and the MCPget_subtitlestool). It is only present, astrue, on lines we could not confirm match the screen. Editing a line's text removes it. See Get Subtitles. - Scripts built from the video's own speech are not checked: their words are what was said at that moment.
v1.63.0 - Nine more languages
GET /v1/languages now returns 83 languages, up from 74. Existing codes are unchanged, and the list
comes from the same registry the product uses, so clients that read it need no change.
- New codes -
yueCantonese,uzUzbek,mnMongolian,tgTajik,mtMaltese,yoYoruba,miMāori,ocOccitan,astAsturian. Accepted anywherelanguageis - Analyze, Translate, Voiceover and Update Video. - These nine are spoken by
eleven_v4only. A Voiceover request in one of them useseleven_v4even when you pineleven_multilingual_v2oreleven_v3, which can't speak them. - MCP:
list_languagesreturns them with no change, because it reads the same endpoint. If you cached the list, refresh it.
v1.62.0 - Knowledge base redirects
- Redirects now forward readers. Redirects from
POST /v1/knowledge-base/redirects(and the MCPcreate_kb_redirecttool) are now applied on your help site. Before, they were saved but readers still got a 404. - Renaming an article keeps its old link working. Changing
sluginPATCH /v1/knowledge-base/articles/:idnow adds a redirect from the old address. - Moved articles forward to their new section. Old links to an article moved to another section, or in a renamed section, now forward to its current address.
v1.61.0 - Eleven v4 for every language
model: autonow useseleven_v4for every language inPOST /v1/videos/:id/voiceoverand the MCPgenerate_voiceovertool, English included. Pineleven_multilingual_v2to keep a video on the older model.speedandsentencePauseSecondswork on every model. See Voiceover.
v1.60.0 - Eleven v4 voiceover
- Languages the multilingual model can't speak now use
eleven_v4inPOST /v1/videos/:id/voiceover(and the MCPgenerate_voiceovertool) withmodel: auto, the default. That covers Hebrew and 44 other languages, and translated voiceovers. Each line is now conditioned on its neighbours, so the voice stays steadier from line to line.eleven_v4is also a newmodelvalue you can pin.eleven_v3stays pinnable. See Voiceover. - New voices in
GET /v1/voices(and the MCPlist_voicestool): 11 native Hebrew voices and 6 English narrators. Voices made for one language carry a newlanguagefield. See Voices. speedandsentencePauseSecondsnow work in every language. Languages outside the multilingual model used to ignore both; Vidocu now applies them to the generated audio.speedis now 0.7-1.2. The voice engine rejected anything above 1.2, so those requests failed. Values up to 1.3 are still accepted and spoken at 1.2.
v1.59.0 - Max length for AI recordings
POST /v1/recordingstakesmaxDurationSec, and so does the MCPstart_recordingtool. The agent plans to fit that many seconds, the replay speeds up when the plan runs over, and the finished video is cut at the limit, so it also caps what the job is charged.0or absent means no limit, as before. See AI Recorder.
v1.58.0 - Download links for private media
GET /v1/videos/:id/downloadreturnsdownloadUrlanddownloadUrlExpiresAt, and so does the MCPget_download_urltool. Fetch files fromdownloadUrl. In a workspace with private media it is a signed link that works for one hour. Everywhere else it is the same asurland never expires. See Download Files.- The
export.completedwebhook carriesdownloadUrlsanddownloadUrlsExpireAt, on the same terms, with links that work for 24 hours in a workspace with private media. - Docs correction: the
export.completedpayload was documented with the wrong field names. It sendsprojectId,videoUrl,srtUrlandvoiceoverUrl, and always has. See Webhook events. - Saving a signed or view link stores the file's permanent address instead. If a write sends
back a link Vidocu handed out, such as a
downloadUrl, the file's permanent address is saved, so a saved link never stops working.
v1.57.2 - Deleting a video deletes its files
DELETE /v1/videos/:idnow removes the video's stored files, in the API, the app and the MCPdelete_videotool alike: the source upload, exports, screenshots and voice clips. Files that something else in the workspace still uses stay, such as a duplicate of the video or a Knowledge Base article that shows its screenshots.- Fix: deleting a video, or a folder with
cascade=true, used to delete the video's upload and exports outright, which broke any duplicate that shared them, and could delete brand-kit intros, outros and music that other videos use. Both now go through the same reference check.
v1.57.1 - Take one language down; each language names its own approvers
- Archiving a translated package withdraws its language from the Knowledge Base. The master and the other languages stay live. Unarchiving publishes it again; approving a new package in that language replaces it. An older approved version never comes back on its own. See Languages of an approved article.
- Archiving a translated package no longer archives the training. The training is shared with the master and every other language, and archiving one language used to retire it for all of them. It is archived only with the last package that uses it.
- A language page shows that language's own approvers and approval date, not the master's.
- Docs correction: a language version is changed by translating the video again and approving the new package. Approving a duplicate of a translated package does not change the Knowledge Base.
v1.57.0 - An approved article's languages come from approved packages
- Approving a translated package publishes its language in the Knowledge Base. On an article published from an approved package, each language comes from the article of the translated package in that language, copied word for word, once that package is approved. No separate publish step. See Languages of an approved article.
- Until then, that language is hidden from readers everywhere, including search, Ask, the sitemap, hreflang and the offline export. Older machine translations of such an article stay in the dashboard, hidden.
- An approved language version can't be edited, re-translated or deleted (
409). - Publishing an approved package through the API now records its approvers, as the dashboard
always has. Articles published through
POST /v1/knowledge-base/articles,PATCH /v1/knowledge-base/articles/:idorfrom-videoshowed no "Approved by" before.
v1.56.1 - Filter the planner by withdrawn or blocked
GET /v1/modules/plannernow acceptsstatus=revokedandstatus=blocked. Both statuses were added in v1.56.0 but the filter still rejected them. The MCP planner tool takes them too.POST /v1/modules/planner/qualificationis now in the OpenAPI spec and the Postman collection. It shipped in v1.56.0 without them.
v1.56.0 - Withdraw or block a training qualification
- New:
POST /v1/modules/planner/qualificationtakes a qualification away from one or more people, with a reason that is required and recorded.action: "withdraw"lets them earn it back by re-taking the training;action: "block"bars them from it, and no later pass or trainer sign-off lifts it. Up to 200 people per call. Needs thecanLockpermission, the same one as signing somebody off. POST /v1/modules/:id/qualificationsnow answers409for somebody who has been blocked, instead of signing them off.- Two new planner statuses,
revokedandblocked, onGET /v1/modules/plannerand its CSV. They outrank every other status, including a later pass. Rows in either state carry asanctionobject withkind,at,reasonandbyName. A blocked cell never counts as overdue; a withdrawn one does. - Somebody who re-qualifies after a withdrawal reads as
renewed, notpassed. The withdrawal is a documented gap and stays visible in the record after it has been put right. GET /v1/modules/:id/qualificationsstill lists sign-offs only. Withdrawals and blocks are stored alongside them and were previously indistinguishable from a sign-off to any caller reading the newest record.- New MCP tool
withdraw_qualification.
v1.55.3 - Analysis is billed by the video's real length
- Analyze and
/processcheck your balance before any work. A fresh upload's length isn't known when you call them, so they need at least one minute of analysis in your balance, and the analysis measures the file before it starts. A video longer than your balance covers is refused before anything is processed: the job fails with a "Not enough credits" error and nothing is charged. Before this, a new upload skipped the balance check. - Analysis is charged by the measured length of the file, never less than the length you sent. Remix works the same way.
- Charges larger than your balance now count against it. An operation that finishes after your balance ran out (for example a recording longer than expected) leaves the balance below zero, so the next request is refused until you buy credits or your plan renews. Before this, the difference was dropped.
- Course actions check credits.
POST /v1/courses, planning, storyboards and module generation answer403 limit_exceededwhen the balance can't cover the step, like the dashboard. Before this they started anyway. - Voiceover and tool runs draw on purchased credits once your plan's credits are used up, the same way the dashboard does.
v1.55.2 - No length limit per video
- Removed: the per-video duration limit. Analyze, translate, voiceover, export and
/processno longer refuse a video for being longer than your plan's maximum, on any plan. A long video costs more, and a request your balance can't cover is still refused withlimit_exceeded. limits.maxVideoDurationonGET /v1/usageis now always0and is deprecated.
v1.55.1 - Fixes to section permissions and history
- Fixed:
/articles/from-videorefused by a section'spublishersanswered400. It now answers403 insufficient_role, as documented in v1.54.0. A409from its approval gate now keepsapprovalBlocked,approvalStatusandrequestIdnext to the message. - Sending back a section's current
sharedWithorpublishersis not a change. A caller that is not an owner or admin can include the stored value (ornullon create) without a403. - A move writes one history entry.
PATCH /v1/knowledge-base/articles/:idwith onlysectionIdrecords the move and no separate "edited" entry, like the dashboard. - Fixed:
aiGeneratedAudioonPATCH /v1/videos/:idkept the last export. Changing it now marks the export out of date, so the next export renders the file again with the label.
v1.55.0 - AI-generated audio is marked
- Exported videos carry an AI-audio marking in their MP4 metadata when the sound contains a
Vidocu voiceover, AI avatar speech, or audio the owner declared as AI-generated. The package
manifest carries the same record in
aiProvenance.audio. See AI-generated audio. aiGeneratedAudioonPOST /v1/videos/uploadandPATCH /v1/videos/:iddeclares that an imported video's own audio is AI-generated; video responses return it. Refused on a locked video.- MCP:
upload_videoandupdate_videotakeaiGeneratedAudio; video results carry it. - Dashboard: a checkbox next to "Keep my own voice" in the upload window, and an "AI audio label" block in the editor's Video tab.
v1.54.0 - Who can publish in a section, and a clearer history
- Sections take
publishers. A list of workspace members who may create, move or publish articles in that section; owners and admins always may, and an empty list means only them.POST/PATCH /v1/knowledge-base/articles,/articles/from-videoand publishing answer403 insufficient_rolefor anyone else. See Who can publish in a section. - Removed: a locked article's
sectionIdno longer returns423when shared sections require approval (added in v1.52.0). Where an article may go is now decided by the section'spublishers, not by the lock. sharedWithandpublishersare owner and admin information. Other callers no longer receive them, and setting either needs an owner or admin (403).- Change history from the API. Creating, publishing, unpublishing and moving an article through the API now write the same history entries as the dashboard. A move is its own entry naming both sections.
- Fixed:
/articles/from-videowithstate: "published"skipped the package's approval gate. It now answers409until the approval is complete, like the dashboard. - MCP:
create_kb_sectionandupdate_kb_sectiontakepublishers.
v1.53.1 - Export music volume overrides work
- Fixed:
music.volumeandmusic.duckVolumeonPOST /v1/videos/:id/exportplayed almost silent. Both take 0 to 1, but the value reached the renderer as a percentage, so0.3played the music at 0.3% instead of 30%. They are now converted, and the documented 0 to 1 scale is unchanged, so requests that already send it need no change. The same applies to the MCPexport_videotool. See Export.
v1.53.0 - Background music defaults that new videos actually use
POST /v1/videosnow starts a video with the Brand Kit's music: the workspace's default track when it has one, and its volume, volume while a voiceover plays, fade length and "play in scenes" values. Before, a video created through the API had none of them. See Background music defaults.- The defaults are copied at creation, never inherited later. Changing
backgroundMusicVolumeand the related fields on the Brand Kit affects videos created afterwards only. - Dashboard: the controls, which had no reachable screen, are now under Brand Kit -> Music -> Settings. In the editor, a video's Music settings say whether they still match the Brand Kit and offer "Reset to Brand Kit defaults". The fade can go up to 10 seconds there too.
- Fixed: a video generated from a document in a workspace with a default track came out with no music at all.
v1.52.0 - Share a section with outside readers
- Sections take
sharedWith.POST /v1/knowledge-base/sectionsandPATCH /v1/knowledge-base/sections/:idaccept email domains and addresses that may read a top-level section of a gated knowledge base. Those readers sign in and see only the sections shared with them; the knowledge base's own access list keeps full access. Sub-sections follow their parent. See Sharing a section with outside readers. PATCH /v1/knowledge-basetakesaccess, and the knowledge base answers it:openSignup,allowedEmailDomains,explicitAllowedEmails,authMethodand the newsharedSectionsRequireApproval. With that on, an article in a shared section shows only while its package is approved and locked, and a locked article'ssectionIdreturns423. See Approval for shared sections.- Fixed:
visibilityon the knowledge base ispublicorgated. The endpoint validated it against the article values (public,staff,customers), so a gated knowledge base could not be set through the API at all. - Access is checked on every request. Removing a domain or address used to leave its readers signed in until their session expired. They now lose access on their next page.
- MCP:
create_kb_sectionandupdate_kb_sectiontakesharedWith;update_knowledge_basetakesaccessand the correctvisibilityvalues; results carry both. - Dashboard: a "Share with outside readers" block on each top-level section's edit row, and an "Approval for shared sections" switch under Settings -> Access.
v1.51.0 - A locked article's address is frozen too
slugis no longer accepted on a locked article.PATCH /v1/knowledge-base/articles/:idnow returns423for a slug change while the article is locked, the same as for its content.sectionId,state,seoandtagIdsstill work. The slug was editable for one release on the reasoning that a frozen article is the one whose URL outlives it; a regulated customer pointed out the cost - an approved path could be aimed at different content with nothing in the approval record to show for it. Changing an address now takes an unlock, and therefore a fresh approval round. See Locked articles.- MCP:
update_kb_articlesays so, and a locked slug change returns the same423. - Dashboard: the URL slug field is disabled on a locked article, and the locked banner says the address is frozen.
v1.50.0 - Section names in every language
- Sections take
translations.POST /v1/knowledge-base/sectionsandPATCH /v1/knowledge-base/sections/:idaccept a section'snameanddescriptionper locale, keyed by locale code.PATCHmerges by locale andnullremoves one. Only enabled, non-default locales are accepted; anything else is a400. See Section names in other languages. - The public site reads them. A reader on a translated locale used to see every section name in the main language, in the navigation, on the cards, in breadcrumbs and in search results. Those now use the translation, falling back to the main-language text per field. Offline exports do the same in each language they carry.
- MCP:
create_kb_sectionandupdate_kb_sectiontaketranslations, and section results carry them. - Dashboard: the section edit row has an "Other languages" block for every enabled locale, with a button that drafts the names by machine translation. Nothing is saved until you save the row.
v1.49.0 - Articles from slide-built videos
- A video built from a deck can generate an article.
POST /v1/videos/:id/articleread only the video's transcript, so anything made from a deck - Course Builder, "Keep my slides", the document and presentation converters - had nothing to read and returnedVideo must be analyzed before generating an article. It now writes from the slides themselves: each slide's heading, on-screen text and the narration spoken over it, in deck order. Recorded videos are unchanged and still write from their transcript. - The 400 now reads
Video must be analyzed, or have slides with narration, before generating an article, and only fires when there is neither. - Dashboard: the same fix. The Article tab in the video editor refused deck-built videos with
Either keyEvents or subtitles are required to generate a help article; it now generates from the slides, illustrated with the slides' own pictures rather than frames of the source file.
v1.48.0 - A locked article keeps its address editable
slugjoins the fields a locked article accepts.PATCH /v1/knowledge-base/articles/:idon a locked article now takesslugalongsidesectionId,state,seoandtagIds; everything else still returns423. A locked article is exactly the one whose URL outlives it, and correcting a path should not require breaking the permanent record to do it. The change still registers a redirect from the old slug.- Dashboard: the article editor saves those fields while locked. Section, URL slug and the SEO fields sat enabled on a locked article but were dropped before the request went out, so the edits vanished without an error. They save now, and the save indicator stays visible while locked. The title, body and excerpt are frozen and read-only, as before.
- MCP:
update_kb_articlesays the same in its description.
v1.47.0 - Section thumbnails
- Sections take a
thumbnailUrl.POST /v1/knowledge-base/sectionsandPATCH /v1/knowledge-base/sections/:idaccept a publicly reachable image URL, shown on the section's card on the public help site.PATCHwithnullremoves it. Every section in theGETresponse now answersthumbnailUrl-nullwhen it has none - so clients see one shape. - The shape is a knowledge-base setting, not a per-section one. Squares (a tile beside the section name) or cover (a 16:9 banner across the top of the card), chosen in the dashboard under Settings -> Homepage. A section with no image keeps a tinted initial in either shape, so a grid never renders a gap.
- MCP:
create_kb_sectionandupdate_kb_sectiontakethumbnailUrl;list_kb_sectionsreturns it alongsidedescription.
v1.46.0 - Courses know who took them
PATCH /v1/courses/:idtakes asettingsobject. It decides who may open the course link (access.identityfromanonymousthrough to a verified email or a Vidocu account, plus additive audience rules: open enrollment, email domains, an invite list, the training roster) and what marks a module complete (completion.ruleofwatch,watch_quizormanual, with a watched threshold, andcompletion.sequentialto lock each module until the one before it is done). Settings are merged, so a partial patch leaves the fields it does not name alone. An optionalaccessCodeis a shared code checked at the door; it is stored hashed and never returned.- New
GET /v1/courses/:id/progress. Per-module completion rates, a per-learner grid, a drop-off funnel (funnel), weekly completions (completionsByWeek),neverStartedand the median time to finish. The dashboard renders the same figures on a course's Analytics tab. The people list is a union of everyone with progress, everyone invited, and the training roster when the course admits it - so somebody who was invited and never started is a row, not an absence. - Course learners join the training roster. A learner who identifies with a verified email is
upserted into the workspace's people list, so
GET /v1/modules/plannersees them. Completing a course does not create a qualification; that stays a trainer sign-off. - Quiz attempt emails are stored lowercased. Every reader of the submissions collection normalizes, so an address recorded as typed joined to nothing - a mixed-case learner could pass a quiz and never complete the module gated on it.
v1.45.0 - Articles can attach and detach their video
PATCH /v1/knowledge-base/articles/:idacceptslinkedVideoId. Attach the video an article documents, or sendnullto detach it. Detaching clearslinkedVideoTimestamptoo and leaves the video itself untouched. The field is frozen on a locked article (423), and a call that attaches a video and publishes at once is gated on the video it is attaching.- Removing an opening/closing scene, background music, a video background, captions or an avatar from a video now persists. A cleared field reached the save as "not mentioned" rather than as a clear, so the old value survived every write - including on the article pages that render from the same document.
v1.44.0 - Transcript runs stop when there is no speech; pasted scripts are timed by sentence
scriptSource: "transcript"no longer falls back to AI narration. A recording with no usable speech fails the analysis job witherrorCode: "no_speech"(transcription_failedfor a transient error) instead of quietly writing a script the caller did not ask for.GET /v1/jobs/:idand the jobs list carry the newerrorCodefield.customScriptis timed sentence by sentence. A plain-prose script used to land on the timeline paragraph by paragraph. The job result'sscriptNoticenow also says when the script is longer than the footage.
v1.43.0 - Planner rows name their package; locked articles stay in their languages
GET /v1/modules/plannerrows carryvideoId. The package to open the training in - the master of its language family when it has one. Absent when the training is attached to no package. The dashboard's Planner links each training through it.POST /v1/knowledge-base/articles/:id/translaterefuses a locked article (423,article_locked). A lock freezes the article in every language: no new translation is generated, and an existing one can no longer be edited or marked reviewed. Before, the source could be signed off and a machine translation of it appear in the Knowledge Base with nobody having approved it.
v1.42.0 - Course modules are editable slides
POST /v1/courses/:id/generatebuilds slides, not a rendered file. A generated module is now a video made of one editable slide per storyboard scene, each carrying its own voiceover and word timings. Nothing is rendered until export, so every scene's layout, text, picture and narration can still be changed in the video editor. Before, the module was rendered straight to an MP4 and only the narration stayed editable. The job, thevideoIdit produces, and everything you can do with that video are unchanged. See Generate.
v1.41.1 - Cloned voices stay in their workspace
GET /v1/voiceslists only your own clones. The stock library came straight from the voice provider's account, which is shared by every workspace, so it also carried every workspace's cloned voices. Clones are now listed only for the workspace that made them; the stock library is unchanged. The dashboard's voice pickers had the same leak and are fixed the same way.
v1.41.0 - Ask holds a conversation
POST /v1/knowledge-base/asktakeshistory. Pass the earlier turns of a conversation (oldest first, up to 20) and a follow-up is answered in the light of them, with retrieval kept on the same subject. The answer is markdown now - steps, bold control names, and an article's screenshot when one shows the step - and is grounded in the matched articles in full rather than a short preview of each. See Ask.
v1.40.0 - No placeholders go live
- Publishing refuses unfinished articles.
PATCH /v1/knowledge-base/articles/:idwithstate: "published"(andPOST .../articlescreated as published) returns409while the body still carries a[TODO: ...]placeholder outside an HTML comment; the message lists the first few. Generated drafts leave one wherever a detail could not be confirmed, and resolving them is part of finishing the article. See Publishing and approvals. - Publishing indexes the article for Ask AI. It always said so; in fact only an edit to an already-published article was indexed, so a draft published untouched stayed invisible to Ask AI (while search found it). Publishing, editing a published article and unpublishing now each update the index, from the dashboard and from the API alike.
v1.39.0 - Offline copies are versioned
- Every offline export has a
version. Builds with the same tag selection form a series and are numbered in order; the number is in the ZIP filename and in the footer of every exported page. Failed builds don't consume a number. See Offline export.
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