Skip to main content

AI Recorder

Describe a flow in plain words and an agent drives a real browser to produce a screen recording of it. No screen capture, no narration script, no editing.

The AI Recorder is included on every paid plan. On a free plan, starting a recording returns 403.

Start a recording

POST /v1/recordings

curl -X POST https://api.vidocu.ai/v1/recordings \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Show how to invite a teammate and set their role to Editor",
"url": "https://app.example.com/settings/team",
"device": "desktop"
}'
{ "jobId": "video_recording_1786093699160_motd1r", "status": "pending" }

Returns 202. Recordings take minutes, not seconds - poll the job.

Two recordings run per workspace at a time; a third start returns 429. Recording browsers are a shared pool, so a job may also sit queued briefly before it starts - progress.step reports queued while it waits.

FieldTypeDescription
promptstringWhat the recording should show. Required
urlstringWhere to start
devicedesktop | mobileViewport to record in
pacingrelaxed | standard | briskReplay speed of the finished video
moderegular | follow | stepssteps drives an explicit list instead of planning
stepsarray{instruction, url?} - required when mode is steps

A 422 means the recorder read the prompt and judged it not actionable. The response carries rejected: true and usually a suggestion for a rewrite - show it rather than retrying blindly.

Attachments and file uploads are dashboard-only; the API takes JSON.

Check on it

GET /v1/recordings/:jobId

{
"jobId": "video_recording_...",
"status": "completed",
"aborted": false,
"partial": true,
"partialReason": "The export dialog needed a paid plan, so the last two steps aren't shown.",
"duration": "547s",
"completedAt": "2026-08-12T21:04:00.000Z"
}

Two failure shapes matter, and they are not the same thing:

  • aborted - the agent stopped and there is no usable video. A paywall, a missing permission, a UI that doesn't exist. error holds its reason.
  • partial - a video exists, but it doesn't show the whole flow. The steps that worked were recorded rather than thrown away. partialReason says what's missing.

Never present a partial recording as a finished tutorial. status is completed in both cases; the flags are what tell them apart.

duration is the agent's wall-clock runtime, not the video's playback length.

When the agent gets stuck on a value

POST /v1/recordings/:jobId/input with {"value": "..."}

Some flows pause for something only a person has - a one-time code, a 2FA challenge, a security answer. The job waits, and this hands the value over.

Ask a human for it. Don't guess, and don't forward a credential that wasn't given for this purpose.

Get the file

GET /v1/recordings/:jobId/download

{ "downloadUrl": "https://...", "expiresIn": 3600 }

A time-limited URL, not the bytes - fetch it directly. 409 if the job hasn't completed.

List and delete

GET /v1/recordings - cursor-paginated, filterable by status.

DELETE /v1/recordings/:jobId removes the job from the list. A video already imported from it is a separate object and is untouched.

Saved logins

GET /v1/recorder-sessions · PATCH /v1/recorder-sessions/:domain · DELETE /v1/recorder-sessions/:domain

To record a site behind a login, the recorder can keep the session and reuse it next time. Sessions are keyed by domain - one per domain per workspace - and expire on their own.

The stored cookies never leave Vidocu. The API reports that a session exists, when it expires, and its setup instructions:

{
"sessions": [
{
"domain": "app.example.com",
"setupPrompt": "Switch to the Acme workspace and close the welcome banner",
"createdAt": "2026-08-01T09:12:00.000Z",
"updatedAt": "2026-08-20T14:03:00.000Z",
"expiresAt": "2026-09-19T14:03:00.000Z"
}
]
}

Setup instructions

setupPrompt is a short set of steps the recorder performs on that site before every recording and screenshot, off camera - switching to the right workspace, dismissing a welcome banner, opening the demo account. It is part of the session, so it applies to recordings started from the dashboard, the API, and Pulse screenshots alike. null when unset.

PATCH /v1/recorder-sessions/:domain with { "setupPrompt": "..." } sets it; { "setupPrompt": null } clears it. Up to 2000 characters. Returns the updated session (domain, setupPrompt, updatedAt, expiresAt), or 404 when there is no saved login for the domain. Requires recordings:write and a role that can edit.

A recording request that carries its own setupPrompt wins over the session's for that one job; the session's is not changed.

Billing

Charged per minute of finished video when the job completes, with a 1-minute minimum that covers the fixed planning cost every job pays. A balance check runs before the job starts, so one that could never be paid for doesn't begin.

Failed and aborted jobs are free. A partial recording produced a video, so it is charged for what it produced.

Errors

StatusCodeCause
402/403limit_exceededFree plan, or not enough balance to start
404not_foundNo such recording in this workspace
409conflictDownload requested before the job finished
422validation_errorThe recorder judged the prompt not actionable
429rate_limit_exceededTwo recordings are already running for this workspace