> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anchorbrowser.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Demonstrations API

> Let external users record browser workflows via a shareable link

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

1. **Create** a demonstration session via API — you get back a `share_url`
2. **Send** the share URL to your customer (email, embed, etc.)
3. Customer opens the link, sees a live browser, and **performs the task**
4. Customer clicks "Finish Demonstration" — the recording is submitted
5. Anchor **generates a workflow** from the recorded actions
6. **Poll** the status endpoint until it reaches `completed` — you get `task_id` and `tool_id`

## API Endpoints

### Create a demonstration

<CodeGroup>
  ```bash cURL theme={null}
  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"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.anchorbrowser.io/v1/demonstrations/",
      headers={"anchor-api-key": "YOUR_API_KEY"},
      json={
          "task_name": "Download invoice report",
          "task_description": "Navigate to Reports, select the monthly invoice report, and download it as PDF",
          "user_name": "John",
      },
  )
  data = response.json()
  share_url = data["share_url"]  # Send this to your customer
  session_id = data["session_id"]
  task_id = data["task_id"]
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.anchorbrowser.io/v1/demonstrations/', {
    method: 'POST',
    headers: {
      'anchor-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      task_name: 'Download invoice report',
      task_description: 'Navigate to Reports, select the monthly invoice report, and download it as PDF',
      user_name: 'John',
    }),
  });
  const { share_url, session_id, task_id } = await response.json();
  ```
</CodeGroup>

**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:**

```json theme={null}
{
  "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-..."
}
```

<Note>
  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.
</Note>

### Get demonstration status

Poll this endpoint to track progress after recording completes.

```bash theme={null}
curl https://api.anchorbrowser.io/v1/demonstrations/SESSION_ID \
  -H "anchor-api-key: YOUR_API_KEY"
```

**Response:**

```json theme={null}
{
  "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.

```bash theme={null}
curl -X POST https://api.anchorbrowser.io/v1/demonstrations/SESSION_ID/recording/complete \
  -H "anchor-api-key: YOUR_API_KEY"
```

**Response:**

```json theme={null}
{
  "session_id": "abc123-...",
  "status": "processing",
  "hektor_project_id": "proj-uuid-...",
  "task_id": "task-uuid-..."
}
```

This endpoint:

1. Ends the browser session (triggers upload of recorded actions)
2. Waits for the recording artifacts to be uploaded to S3
3. Submits the recording to Hektor for workflow generation
4. Returns immediately with `status: "processing"`

### Stop demonstration

Stop a demonstration without generating a workflow. Useful for cleanup.

```bash theme={null}
curl -X POST https://api.anchorbrowser.io/v1/demonstrations/SESSION_ID/stop \
  -H "anchor-api-key: YOUR_API_KEY"
```

**Response:**

```json theme={null}
{
  "success": true
}
```

## End-to-end example

<CodeGroup>
  ```python Python theme={null}
  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']}")
  ```
</CodeGroup>

## 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.

```json theme={null}
{
  "task_name": "Export quarterly report",
  "task_description": "Navigate to the reports section and export Q1 data",
  "identity_id": "7f0db4ad-74ca-42e5-896e-3f0daea36c13"
}
```

<Tip>
  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.
</Tip>

## 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:

```json theme={null}
{
  "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.
