Skip to content
These docs describe the Veilus release after v0.2.1, coming soon. If you have v0.2.1, some screens and features (Datasets, Trash, the new profile panel, many MCP tools) are not in your version yet.

REST API

Veilus can run a small REST API on your own machine, so other programs you run — scripts, other apps, an LLM agent — can manage profiles and proxy pools, drive a running profile’s page, and run and schedule Veilus Flow scripts.

The API is off by default. Turn it on from the API & MCP page in the app sidebar, which shows the port it’s listening on, lets you mint and revoke named tokens, and gives ready-made connection snippets.

The API only listens on 127.0.0.1 — nothing outside your machine can reach it. It reaches every profile, so it’s gated behind the Pro plan or higher and stays off until you turn it on.

Every request needs a bearer token, minted from the API & MCP page. Each token has a name (so you can tell tools apart) and can be revoked independently — a token’s full value is shown only once, at creation time.

Authorization: Bearer <token>

Each token can make at most 30 expensive calls per 60 seconds: POST to launch a profile, create profiles, create a proxy pool, run a script, run a batch, or run a schedule now. Past that the API answers 429 with a Retry-After header. Reads and cheap calls such as stopping a profile aren’t counted.

The port is chosen when you turn the API on and shown on the API & MCP page. Replace <port> below with that value.

http://127.0.0.1:<port>
Terminal window
curl -X GET \
-H "Authorization: Bearer $VEILUS_API_TOKEN" \
http://127.0.0.1:<port>/v1/profiles

GET /v1/profiles

List Veilus browser profiles, with their running state; a running profile carries `cdpUrl`.

GET /v1/capacity

Return the current browser pool capacity and usage.

GET /v1/dsl/schema

Return the JSON schema for the drag-and-drop DSL.

POST /v1/dsl/compile

Compile a drag-and-drop DSL script into runnable code.

Field Type Required Description
dsl object yes DSL script body
target string yes

POST /v1/profiles/:id/launch

Launch a profile's browser and wait for it to start; returns `{pid, cdpUrl}`, a full pool fails with 409 rather than queuing. Optional body `{diagnostic: true}`: the profile's proxy without its fingerprint, in a temporary directory.

Field Type Required Description
diagnostic boolean no Diagnostic launch: the profile's proxy, but none of its fingerprint, in a fresh temporary browser directory deleted on stop — no cookies or logins, and nothing is written to the profile. The page sees THIS machine's real values (platform, CPU cores, GPU, screen, timezone, languages): use it to tell whether a site blocks the fingerprint or the IP/proxy, never on an account you care about. The engine's CDP hiding still applies; WebRTC is restricted to the proxy. Default false.

POST /v1/profiles/:id/stop

Stop a running profile's browser.

POST /v1/scripts/run

Start a script run on given profiles; returns the run immediately (its `id` is the run_id).

Field Type Required Description
profile_ids string[] no
script_id string (uuid) yes
variables object no

POST /v1/scripts

Save an agent-authored Raw script into Veilus Flow.

Field Type Required Description
description string no
name string yes
script_id string (uuid) no Script to replace; omit to create a new one
source string yes Full TypeScript source

GET /v1/scripts

List every script without its source: id, name, version, mode (raw or dsl), origin and whether it is approved.

GET /v1/scripts/:id

Read a Raw script's source and approval state.

GET /v1/runs/:id

Read a script run's result by run_id.

POST /v1/profiles

Create 1-50 profiles; with a proxy pool, timezones follow each slot's geo.

Field Type Required Description
content_dataset_id string (uuid) no Consume dataset for the Content slot
count integer yes
identity_dataset_id string (uuid) no Fixed dataset: one unassigned row per new profile
name_template string no {n} becomes 1, 2, ...
os string no
proxy_pool_id string (uuid) no
tags string[] no

GET /v1/profiles/:id/proxy

Show a profile's proxy: pool, slot, host:port and geo, never the password.

GET /v1/proxy-pools

List proxy pools with entry counts and detected countries.

POST /v1/proxy-pools

Create a static proxy pool from proxy lines; bad lines are reported by number.

Field Type Required Description
lines string[] yes
name string yes
type string no

POST /v1/proxy-pools/:id/assign

Assign a proxy pool to profiles; refuses profiles that already have a proxy unless force.

Field Type Required Description
force boolean no
profile_ids string[] yes

POST /v1/proxy-pools/:id/test

Test every proxy in a pool now: alive, latency, exit IP and geo.

GET /v1/schedules

List schedules with their script, target profiles, timing and next run.

POST /v1/schedules

Create a schedule for an approved script on explicit profiles; a once schedule turns itself off after it runs.

Field Type Required Description
concurrency integer no
cron_expr string no 5 fields, e.g. "0 * * * *"
daily_hour integer no
daily_minute integer no
enabled boolean no
interval_minutes integer no interval: count of interval_unit
interval_unit string no
name string yes
profile_ids string[] yes
run_at string (date-time) no RFC 3339 with offset, e.g. 2026-10-04T09:00:00+07:00; required for once
schedule_type string yes
script_id string (uuid) yes An approved script
stagger_ms integer no
weekly_day integer no 0 = Sunday

POST /v1/schedules/:id/enabled

Turn a schedule on or off; turning it on recomputes its next run.

Field Type Required Description
enabled boolean yes

POST /v1/schedules/:id/run

Run a schedule once now; returns the run immediately.

POST /v1/scripts/batch

Run an approved script on many profiles; returns the run immediately.

Field Type Required Description
concurrency integer no
profile_ids string[] yes
script_id string (uuid) yes
stagger_ms integer no
variables object no

POST /v1/profiles/:id/variables

Replace all stored variables of a profile; returns the variable names only.

Field Type Required Description
variables object yes

GET /v1/runs

List recent runs, newest first; query schedule_id and limit (default 20, max 100).

GET /v1/openapi.json

Return the OpenAPI 3.1 document describing this REST API.

POST /v1/profiles/:id/navigate

Load a URL in a running profile's tab and wait for the load event.

Field Type Required Description
url string yes

GET /v1/profiles/:id/snapshot

Accessibility snapshot of a running profile's page, with [id=N] per element.

POST /v1/profiles/:id/click

Click the element with a node id from snapshot or wait-for-element, with a real mouse; refuses hidden or covered elements.

Field Type Required Description
node_id integer yes

POST /v1/profiles/:id/type

Focus an element by node id and type text into it.

Field Type Required Description
node_id integer yes
text string yes

POST /v1/profiles/:id/press-key

Press one named key (Enter, Tab, Escape, arrows, Backspace, Delete, Space).

Field Type Required Description
key string yes

POST /v1/profiles/:id/scroll

Scroll a running profile's page by about a number of pixels in one direction, with mouse-wheel steps at the pointer; reports the pixels scrolled.

Field Type Required Description
amount integer yes
direction string yes

POST /v1/profiles/:id/evaluate

Run JavaScript in a running profile's page; 64 KiB result cap, 10 s timeout.

Field Type Required Description
expression string yes

POST /v1/profiles/:id/wait-for-element

Wait until a CSS selector matches and return the element's node id.

Field Type Required Description
selector string yes
timeout_ms integer no

POST /v1/profiles/:id/set-file

Attach a file from the app's uploads folder to a file input by node id.

Field Type Required Description
node_id integer yes
path string yes

GET /v1/datasets

List datasets with their columns and row counts by state; never row values.

POST /v1/datasets

Create a fixed or consume dataset from columns and rows; bad rows are reported by number.

Field Type Required Description
columns object[] yes
mode string yes
name string yes
rows object[] no One object per row, keyed by column name; every value must be a string — convert numbers and dates to text before sending
rows_per_run integer no

GET /v1/datasets/:id/rows

Read a dataset's rows by page (query offset, limit); secret columns are never returned.

POST /v1/datasets/:id/rows

Append rows to a dataset; bad rows are reported by number.

Field Type Required Description
rows object[] yes One object per row, keyed by column name; every value must be a string — convert numbers and dates to text before sending

POST /v1/datasets/:id/assign

Assign a dataset to profiles, into the slot its mode implies; a taken slot is refused unless force.

Field Type Required Description
force boolean no
profile_ids string[] yes

POST /v1/datasets/:id/unassign

Remove a dataset from profiles; their fixed rows become unassigned again.

Field Type Required Description
profile_ids string[] yes

POST /v1/datasets/:id/reset

Return every used row of a consume dataset to available.

GET /v1/openapi.json returns the OpenAPI 3.1 document for this API (requires a token like any other route). The API & MCP page also has a Copy OpenAPI JSON button if you’d rather not curl it yourself.