The Demonstrations API lets your customers record browser workflows through a shareable URL — no Anchor account required. A customer opens the link, performs a task in a live browser, and Anchor automatically generates a reusable deterministic workflow from the recording.
How it works
- Create a demonstration session via API — you get back a
share_url
- Send the share URL to your customer (email, embed, etc.)
- Customer opens the link, sees a live browser, and performs the task
- Customer clicks “Finish Demonstration” — the recording is submitted
- Anchor generates a workflow from the recorded actions
- Poll the status endpoint until it reaches
completed — you get task_id and tool_id
API Endpoints
Create a demonstration
curl -X POST https://api.anchorbrowser.io/v1/demonstrations/ \
-H "anchor-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task_name": "Download invoice report",
"task_description": "Navigate to Reports, select the monthly invoice report, and download it as PDF",
"identity_id": "OPTIONAL_IDENTITY_ID",
"user_name": "John"
}'
Request body:
| Field | Type | Required | Description |
|---|
task_name | string | Yes | Name for the workflow being recorded |
task_description | string | Yes | Natural language description of what the task does — used by the AI to understand the recording |
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 recording 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 recording completes.
curl https://api.anchorbrowser.io/v1/demonstrations/SESSION_ID \
-H "anchor-api-key: YOUR_API_KEY"
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, user is recording |
processing | Recording complete, workflow is being generated |
completed | Workflow generated successfully — task_id and tool_id are available |
failed | Workflow generation failed |
stopped | Session was stopped before completing |
Complete recording
Called automatically by the recording UI when the user clicks “Finish Demonstration”. Can also be called programmatically.
curl -X POST https://api.anchorbrowser.io/v1/demonstrations/SESSION_ID/recording/complete \
-H "anchor-api-key: YOUR_API_KEY"
Response:
{
"session_id": "abc123-...",
"status": "processing",
"hektor_project_id": "proj-uuid-...",
"task_id": "task-uuid-..."
}
This endpoint:
- Ends the browser session (triggers upload of recorded actions)
- Waits for the recording artifacts to be uploaded to S3
- Submits the recording to Hektor for workflow generation
- Returns immediately with
status: "processing"
Stop demonstration
Stop a demonstration without generating a workflow. Useful for cleanup.
curl -X POST https://api.anchorbrowser.io/v1/demonstrations/SESSION_ID/stop \
-H "anchor-api-key: YOUR_API_KEY"
Response:
End-to-end example
import requests
import time
API_KEY = "YOUR_API_KEY"
BASE = "https://api.anchorbrowser.io"
# 1. Create demonstration
demo = requests.post(f"{BASE}/v1/demonstrations/", headers={"anchor-api-key": API_KEY}, json={
"task_name": "Download invoice report",
"task_description": "Go to Reports > Invoices, select this month, download PDF",
"identity_id": "your-identity-id",
"user_name": "Sarah",
}).json()
print(f"Send this link to your customer: {demo['share_url']}")
session_id = demo["session_id"]
# 2. Poll until completed
while True:
status = requests.get(
f"{BASE}/v1/demonstrations/{session_id}",
headers={"anchor-api-key": API_KEY},
).json()
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 customer opens it. The customer will see the target application already logged in and can immediately start recording the task.
{
"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 customer can log in manually during the recording. Set identity_skip_validation: true (default) to ensure this behavior.
Share URL and the recording UI
The share_url opens a full-screen recording interface with:
- Live browser iframe — the customer interacts with the actual website
- Live Browser Events panel — shows clicks, typing, navigation in real-time
- “Finish Demonstration” button — completes the recording and triggers workflow generation
When the customer 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.