Send a shareable link so someone can demonstrate a task in a live browser. Anchor captures every event and compiles it into deterministic, repeatable code with an AI fallback — the same outcome as creating a task from a demonstration in the UI.
Use this when the person who knows the flow isn’t at the keyboard in your Anchor workspace.
How it works
- Create a demonstration session via API — you get back a
share_url
- Send the link to the person who will demonstrate the task
- They open it, see a live browser, and perform the task
- They click Finish Demonstration — the demonstration is submitted
- Anchor compiles the captured events into a task
- Poll the status endpoint until it reaches
completed — you get task_id and tool_id
API Endpoints
Create a demonstration
import AnchorBrowser from 'anchorbrowser';
const anchorClient = new AnchorBrowser({ apiKey: process.env.ANCHOR_API_KEY });
const demo = await anchorClient.post('/v1/demonstrations/', {
body: {
task_name: 'Download invoice report',
task_description: 'Navigate to Reports, select the monthly invoice report, and download it as PDF',
user_name: 'John',
},
});
console.log('Share URL:', demo.share_url);
console.log('Session ID:', demo.session_id);
console.log('Task ID:', demo.task_id);
import os
from anchorbrowser import Anchorbrowser
anchor_client = Anchorbrowser(api_key=os.getenv('ANCHOR_API_KEY'))
demo = anchor_client.post(
'/v1/demonstrations/',
body={
'task_name': 'Download invoice report',
'task_description': 'Navigate to Reports, select the monthly invoice report, and download it as PDF',
'user_name': 'John',
},
)
print('Share URL:', demo['share_url'])
print('Session ID:', demo['session_id'])
print('Task ID:', demo['task_id'])
Request body:
| Field | Type | Required | Description |
|---|
task_name | string | Yes | Name for the task being demonstrated |
task_description | string | Yes | Natural language description of what the task does — helps Anchor interpret the demonstration |
identity_id | string | No | Pre-authenticate the browser with a saved identity |
identity_skip_validation | boolean | No | Skip identity validation (default: true) |
user_name | string | No | Display name shown in the demonstration UI (“Thanks, John!”) |
session_config | object | No | Override browser session settings (start URL, proxy, timeouts, etc.) |
Response:
{
"session_id": "abc123-...",
"live_view_url": "https://connect.anchorbrowser.io/...",
"share_url": "https://app.anchorbrowser.io/demonstrate?token=eyJ...",
"share_token": "eyJ...",
"share_expires_at": "2026-04-15T09:00:00.000Z",
"task_id": "task-uuid-..."
}
The share_url is a signed JWT link valid for 1 hour. The customer does not need an Anchor account — the token contains the session and team context.
Get demonstration status
Poll this endpoint to track progress after the demonstration is submitted.
const status = await anchorClient.get(`/v1/demonstrations/${sessionId}`);
console.log(status);
status = anchor_client.get(f'/v1/demonstrations/{session_id}')
print(status)
Response:
{
"session_id": "abc123-...",
"status": "completed",
"hektor_project_id": "proj-uuid-...",
"task_id": "task-uuid-...",
"task_version_id": "ver-uuid-...",
"tool_id": "tool-uuid-...",
"created_at": "2026-04-15T07:32:12.865Z"
}
Status values:
| Status | Description |
|---|
recording | Browser session is live — demonstration in progress |
processing | Demonstration complete — Anchor is compiling the task |
completed | Task generated — task_id and tool_id are available |
failed | Task generation failed |
stopped | Session was stopped before completing |
Complete demonstration
Called automatically when the user clicks Finish Demonstration. Can also be called programmatically via POST .../recording/complete.
const result = await anchorClient.post(
`/v1/demonstrations/${sessionId}/recording/complete`,
);
console.log(result);
result = anchor_client.post(f'/v1/demonstrations/{session_id}/recording/complete')
print(result)
Response:
{
"session_id": "abc123-...",
"status": "processing",
"hektor_project_id": "proj-uuid-...",
"task_id": "task-uuid-..."
}
This endpoint:
- Ends the browser session and uploads the captured events
- Waits for demonstration artifacts to be stored
- Submits them for task generation
- Returns immediately with
status: "processing"
Stop demonstration
Stop a demonstration without generating a task. Useful for cleanup.
const result = await anchorClient.post(`/v1/demonstrations/${sessionId}/stop`);
console.log(result);
result = anchor_client.post(f'/v1/demonstrations/{session_id}/stop')
print(result)
Response:
End-to-end example
import AnchorBrowser from 'anchorbrowser';
const anchorClient = new AnchorBrowser({ apiKey: process.env.ANCHOR_API_KEY });
// 1. Create demonstration
const demo = await anchorClient.post('/v1/demonstrations/', {
body: {
task_name: 'Download invoice report',
task_description: 'Go to Reports > Invoices, select this month, download PDF',
identity_id: 'your-identity-id',
user_name: 'Sarah',
},
});
console.log(`Send this link to your customer: ${demo.share_url}`);
const sessionId = demo.session_id;
// 2. Poll until completed
let status;
while (true) {
status = await anchorClient.get(`/v1/demonstrations/${sessionId}`);
console.log(`Status: ${status.status}`);
if (['completed', 'failed', 'stopped'].includes(status.status)) break;
await new Promise((r) => setTimeout(r, 5000));
}
// 3. Use the generated task
if (status.status === 'completed') {
console.log(`Task ID: ${status.task_id}`);
console.log(`Tool ID: ${status.tool_id}`);
}
import os
import time
from anchorbrowser import Anchorbrowser
anchor_client = Anchorbrowser(api_key=os.getenv('ANCHOR_API_KEY'))
# 1. Create demonstration
demo = anchor_client.post(
'/v1/demonstrations/',
body={
'task_name': 'Download invoice report',
'task_description': 'Go to Reports > Invoices, select this month, download PDF',
'identity_id': 'your-identity-id',
'user_name': 'Sarah',
},
)
print(f"Send this link to your customer: {demo['share_url']}")
session_id = demo['session_id']
# 2. Poll until completed
while True:
status = anchor_client.get(f'/v1/demonstrations/{session_id}')
print(f"Status: {status['status']}")
if status['status'] in ('completed', 'failed', 'stopped'):
break
time.sleep(5)
# 3. Use the generated task
if status['status'] == 'completed':
print(f"Task ID: {status['task_id']}")
print(f"Tool ID: {status['tool_id']}")
Identity pre-authentication
Pass an identity_id to pre-authenticate the browser before the link is opened. The user will see the target application already logged in and can start the demonstration immediately.
{
"task_name": "Export quarterly report",
"task_description": "Navigate to the reports section and export Q1 data",
"identity_id": "7f0db4ad-74ca-42e5-896e-3f0daea36c13"
}
If identity authentication fails (expired credentials, site unreachable), the session still starts — the user can log in manually during the demonstration. Set identity_skip_validation: true (default) to ensure this behavior.
Share URL and the demonstration UI
The share_url opens a full-screen demonstration interface with:
- Live browser — interact with the actual website
- Live Browser Events panel — clicks, typing, and navigation as they happen
- Finish Demonstration — submits the demonstration and starts task generation
When the user finishes, they see a confirmation screen. If the share URL was opened as a popup (via window.open), the parent window receives a demonstration-complete postMessage with the task_id, task_version_id, and tool_id.
Session configuration
Override default session settings:
{
"task_name": "My task",
"task_description": "Task description",
"session_config": {
"browser": {
"start_url": "https://app.example.com/dashboard"
},
"session": {
"timeout": {
"max_duration": 60,
"idle_timeout": 30
}
}
}
}
Default demonstration timeouts are max_duration: 30 minutes and idle_timeout: 30 minutes.