/healthIs the local API up
Reachable without a token — it is mounted before the auth middleware.
Permission: noneRate limit: 100 requests/minute
200 OK
{ "status": "ok", "timestamp": 1787553311344 }The desktop app serves an HTTP API on your machine so your own scripts can list profiles, launch them with a CDP endpoint, and run workflows.
26 endpoints
The server binds to the loopback interface only, so it is reachable from the machine running the app and nowhere else. The port comes from LOCAL_API_PORT and defaults to 3030.
http://127.0.0.1:3030Every endpoint except /health and /status needs an API token in the X-Token header. Tokens are created in your account, not in the app.
Example request
curl http://127.0.0.1:3030/profiles \
-H "X-Token: <your api token>"Tokens are validated against the cloud and cached. If the cloud is unreachable the app falls back to the cached validation for up to a day, so automation keeps working through a short outage.
Each token carries a permission set per category — profiles, workspaces, instant_profiles and rpa — and every endpoint below states the check it performs.
A broad grant covers the narrower checks it contains: delete also satisfies write and read. The operational actions are separate — start does not imply stop, and neither is implied by read — so grant each one you actually need.
| Endpoint requires | Satisfied by any of |
|---|---|
read | readwritedelete |
write | writedelete |
delete | delete |
start | start |
stop | stop |
execute | execute |
logs | logs |
create | create |
connect | connectcontrol |
control | control |
Limits are counted per token over a rolling minute, and each route group gets its own tier.
default100 requests/minuteprofile60 requests/minuterpa60 requests/minutestrict10 requests/minuteEvery response carries the current budget
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-ResetFailures answer with success: false, a human-readable error and a machine-readable code.
{ "success": false, "error": "Missing X-Token header", "code": "UNAUTHORIZED" }
{ "success": false, "error": "Permission denied: profiles.start", "code": "FORBIDDEN" }
{ "success": false, "error": "Too many requests", "code": "RATE_LIMIT_EXCEEDED", "retryAfter": 42 }Cheap checks for whether the app is up and whether it can still reach the cloud.
/healthIs the local API up
Reachable without a token — it is mounted before the auth middleware.
Permission: noneRate limit: 100 requests/minute
200 OK
{ "status": "ok", "timestamp": 1787553311344 }/statusCloud connection and last sync
Reachable without a token — it is mounted before the auth middleware.
Permission: noneRate limit: 100 requests/minute
200 OK — lastSync is the newest of profiles, workflows and workspaces
{ "online": true, "lastSync": 1787553311344, "timestamp": 1787553311999 }/listProfiles currently running
Permission: noneRate limit: 100 requests/minute
200 OK
{
"success": true,
"data": [{ "profile_id": "abc", "port": 19001, "status": "RUNNING" }]
}/statsCache, sync queue and running counts
Permission: noneRate limit: 100 requests/minute
Start and stop the profiles synced from your account. Starting one hands back a CDP endpoint you can drive with Puppeteer or Playwright.
/profilesList cached profiles
Reads the local cache. If the cache is empty it syncs from the cloud first, so the first call after a fresh start is slower.
Permission: profiles.readRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
workspace_id | query | string | Only return profiles in this workspace. |
/profiles/syncForce a sync from the cloud
Permission: profiles.readRate limit: 60 requests/minute
/profiles/:profileIdOne profile from the cache
Permission: profiles.readRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
profileIdrequired | path | string | Profile id. |
/profiles/:profileId/startLaunch the profile browser
Returns the CDP url to attach an automation library to. Without a port the app picks a free one in 19000-19999. The profile must already be in the cache — sync first or you get 404.
Permission: profiles.startRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
profileIdrequired | path | string | Profile id. |
port | query | number | Debugging port to use, 1-65535. |
200 OK
{
"success": true,
"data": {
"profile_id": "abc",
"port": 19001,
"cdp_url": "http://127.0.0.1:19001"
}
}/profiles/:profileId/stopClose the profile browser
Permission: profiles.stopRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
profileIdrequired | path | string | Profile id. |
/profiles/:profileId/statusRUNNING or STOPPED
Permission: profiles.readRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
profileIdrequired | path | string | Profile id. |
Throwaway profiles created on the spot, without saving anything to your account. Rate limited hardest of all the groups.
/instantCreate and launch a throwaway profile
Permission: instant_profiles.createRate limit: 10 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
fingerprint | body | object | Fingerprint hints such as os and version. |
proxy_id | body | string | Proxy from your account to route the profile through. |
200 OK
{
"success": true,
"data": { "profile_id": "instant_…", "port": 19002, "cdp_url": "http://127.0.0.1:19002" }
}/instant/:profileIdClose and discard an instant profile
Permission: instant_profiles.deleteRate limit: 10 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
profileIdrequired | path | string | Profile id. |
/instant/:profileIdOne instant profile
Permission: noneRate limit: 10 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
profileIdrequired | path | string | Profile id. |
/instantAll live instant profiles
Permission: noneRate limit: 10 requests/minute
Run the workflows you built on the canvas, on a saved profile or on a fresh instant one, and follow the task while it runs.
/rpa/workflowsList workflows
Permission: rpa.readRate limit: 60 requests/minute
/rpa/workflows/:workflowIdOne workflow, including its graph
Permission: rpa.readRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
workflowIdrequired | path | string | Workflow id. |
/rpa/workflows/syncForce a workflow sync
Permission: rpa.readRate limit: 60 requests/minute
/rpa/tasksRun a workflow on a profile
Permission: rpa.executeRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
workflow_idrequired | body | string | Workflow to run. |
profile_idrequired | body | string | Profile to run it on. |
400 when either field is missing
{
"success": false,
"error": "workflow_id and profile_id are required in request body"
}/rpa/tasks/instantRun a workflow on a fresh instant profile
Creates the profile, runs the workflow on it, and needs no profile_id.
Permission: rpa.executeRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
workflow_idrequired | body | string | Workflow to run. |
profile_config | body | object | Same shape as the instant profile body. |
/rpa/tasksList tasks
Permission: rpa.readRate limit: 60 requests/minute
/rpa/tasks/:taskIdOne task and its state
Permission: rpa.readRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
taskIdrequired | path | string | Task id. |
/rpa/tasks/:taskId/stopStop a running task
Permission: rpa.stopRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
taskIdrequired | path | string | Task id. |
/rpa/tasks/:taskId/logsLogs for a task
Permission: rpa.logsRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
taskIdrequired | path | string | Task id. |
Read-only view of the workspaces profiles are grouped into.
/workspacesList workspaces
Permission: workspaces.readRate limit: 60 requests/minute
/workspaces/syncForce a workspace sync
Permission: workspaces.readRate limit: 60 requests/minute
/workspaces/:workspaceIdOne workspace
Permission: workspaces.readRate limit: 60 requests/minute
| Name | In | Type | Description |
|---|---|---|---|
workspaceIdrequired | path | string | Workspace id. |