REST API · v1

One Bearer key, from goal to action.

A small, versioned REST surface under /api/v1/*: run a goal, dispatch to the semantic cache, queue async jobs, or replay a compiled skill. Usage-billed in credits, with the cache outcome and cost in every response header.

run.sh — request + responsebash
curl https://twin-browser.com/api/v1/run \
  -H "Authorization: Bearer ab_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.acme.com/invoices",
    "prompt": "export last month as CSV",
    "success": { "kind": "urlIncludes", "value": "/exports" }
  }'

# HTTP/2 200
# x-twin-cache:      hit          ← matched a compiled skill
# x-twin-skill:      acme-export  ← which skill replayed
# x-twin-llm-calls:  0            ← zero model calls on a cache hit
#
# { "success": true, "path": [ … ], "credits_charged": 1 }
The integration

Three lines from your stack to ours.

No SDK required — the twin client and one fetch call against https://twin-browser.com/api/v1 are interchangeable. The cache outcome and exact credit cost come back in the response headers, so the wedge is observable from line one.

run.tstypescript
// One key, one POST. Base URL: https://twin-browser.com/api/v1
const res = await fetch('https://twin-browser.com/api/v1/run', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TWIN_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://app.acme.com/invoices',
    prompt: 'export last month as CSV',
    success: { kind: 'urlIncludes', value: '/exports' },
  }),
});

const run = await res.json();
// Cache + cost are in the response headers — read the wedge directly:
res.headers.get('x-twin-cache');      // 'hit' | 'miss'
res.headers.get('x-twin-llm-calls');  // '0' on a replay
console.log(run.success, run.credits_charged); // true 1
How a call flows

Authenticated, observable, settled

Every call runs the same four stages — and the third is where cost falls away.

  1. 1

    Authenticate

    Every call carries Authorization: Bearer with a per-tenant key. Default-deny RLS scopes every read and write to your tenant; an invalid key fails closed with 401.

  2. 2

    Observe the target

    Twin loads the URL you passed and serializes it into a compact, numerically-indexed map of interactive elements — token-efficient state, not raw HTML.

  3. 3

    Replay or plan

    The semantic cache fuzzy-matches the request to a compiled skill. On a hit it replays deterministically with zero LLM calls; on a miss the planner discovers a path and compiles it.

  4. 4

    Settle & audit

    Credits settle on the first terminal read — failed, cancelled, or unsolved actions refund in full. The goal, path, target, and key are written to the audit log.

The surface, grouped

Five families, one engine

Run goals, compile and replay skills, manage vault secrets, watch runs live, and read the rate card — each is a thin, predictable set of endpoints.

Run & dispatch

Run a goal synchronously, queue it as an async job, or hand it to the semantic cache to replay-or-compile.

  • POST /run
  • POST /dispatch
  • POST /jobs
  • GET /jobs/:id

Skills

Compile a goal into a named deterministic skill, list your skills, and replay them with no LLM in the loop.

  • POST /skills
  • GET /skills
  • POST /skills/:name/run

Secrets

Store credentials in the vault as named references — filled at run time on your own runs, never returned or logged.

  • POST /secrets
  • GET /secrets
  • DELETE /secrets/:name

Runs & live view

Watch a run live over SSE, hand back a 2FA code when it pauses, replay its recording, or serialize a page to indexed state.

  • POST /live
  • POST /live/resume
  • GET /runs/:id/video
  • POST /observe

Pricing & corpus

Read the public credit rate card and search the sanitized cross-tenant skill corpus by intent.

  • GET /pricing
  • GET /library
Endpoints

The /api/v1 reference

Costs are in credits. Metered LLM cost is charged as the higher of the flat price and actual usage; failed, cancelled, or unsolved actions are fully refunded.

MethodEndpointCreditsDescription
POST/api/v1/run10Run a goal synchronously on the target URL you provide. A sign-in run parks on a 2FA/approval wall by default (returns status:"paused" + sessionId).
POST/api/v1/agent10+Premium (Pro plan): one call forcing the full anti-detection stack (stealth + human mimicry + sticky residential proxy). Same body as /run plus a required { authorized:true } attestation.
POST/api/v1/dispatch1 / 10Semantic cache: replay a matched skill (hit) or compile + cache (miss).
POST/api/v1/jobs10Submit a goal as an async background job (202 + job id).
GET/api/v1/jobs/:idPoll an async job; settles credits on the first terminal read.
GET/api/v1/jobs/:id/streamServer-sent progress frames for a running job.
POST/api/v1/jobs/:id/cancelCancel a running job (full refund).
POST/api/v1/skills50Compile a skill (discover + minimize).
GET/api/v1/skillsfreeList your compiled skills.
POST/api/v1/skills/:name/run1Deterministically replay a compiled skill (no LLM).
POST/api/v1/secretsfreeStore a credential in the vault as a named reference.
GET/api/v1/secretsfreeList secret names and metadata (never the values).
GET/api/v1/libraryfreeSearch the cross-tenant shared skill corpus (sanitized metadata).
POST/api/v1/observe1Serialize a page into indexed DOM state without acting.
POST/api/v1/live10Run a goal and watch it live (SSE screencast); also recorded.
POST/api/v1/live/resumefreeHand a 2FA code (or cancel) to a live run waiting on an await-user step.
POST/api/v1/runs/:id/resume10Continue a paused (HITL) run after an out-of-band approval.
GET/api/v1/runs/:id/videofreeStream a run’s recording (webm).
GET/api/v1/pricingfreePublic credit rate card (edge-cached).

Full request/response shapes, success-condition specs, and error codes live in the docs.

Response headers

Read the wedge on every call

The cache outcome and cost ride back in x-twin-* headers — no body parsing to see whether a call hit a compiled skill or how many model calls it cost.

HeaderExampleMeaning
x-twin-cachehit · missWhether a compiled skill matched and replayed.
x-twin-skillacme-exportName of the skill that replayed, when cached.
x-twin-llm-calls0 … nModel calls made for this request — 0 on a replay.
x-twin-credits1 … 50Credits charged (mirrors the body’s credits_charged).
x-twin-run-idrun_…Stable id to fetch the recording or audit record.
Skills

Compile once, replay for one credit

Compile a goal into a named, deterministic skill, list your skills, and replay them with no LLM in the loop — the cheap, repeatable path.

skills.shbash
# Compile a goal into a reusable, deterministic skill (discover + minimize).
curl -X POST https://twin-browser.com/api/v1/skills \
  -H "Authorization: Bearer ab_live_…" -H "Content-Type: application/json" \
  -d '{ "url": "https://app.acme.com/invoices",
        "prompt": "export last month as CSV", "name": "acme-export" }'
# → { "name": "acme-export", "steps": 6, "credits_charged": 50 }

# List your compiled skills.
curl https://twin-browser.com/api/v1/skills -H "Authorization: Bearer ab_live_…"

# Replay a skill by name — zero LLM, deterministic, 1 credit.
curl -X POST https://twin-browser.com/api/v1/skills/acme-export/run \
  -H "Authorization: Bearer ab_live_…" -H "Content-Type: application/json" \
  -d '{ "url": "https://app.acme.com/invoices" }'
# → { "success": true, "credits_charged": 1, "x-twin-llm-calls": 0 }
Operating the API

Limits, discovery, and the rate card

Rate limits

Applied per tenant. Over the limit returns 429 with a Retry-After header — back off and retry. Higher tiers raise limits and replay throughput.

OpenAPI + rate card

The surface is described by an OpenAPI document for client generation and agent discovery, and the live rate card is JSON at /api/v1/pricing.

Auth & audit

Per-tenant keys, default-deny RLS, and an audit log on every call. The target URL is the authorization signal — see the security page.

FAQ

API, answered

How do I authenticate?
Every request carries an Authorization: Bearer header with a per-tenant API key. Keys are shown once at creation and stored only as a hash. Create one in the dashboard after signing up and keep it server-side.
What are the x-twin-* response headers?
Every response includes x-twin-cache (hit or miss), x-twin-skill (the skill that replayed), x-twin-llm-calls (model calls made — 0 on a replay), x-twin-credits, and x-twin-run-id. They let you read the cache outcome and the exact cost of a call without parsing the body.
Is there an OpenAPI spec?
Yes. The /api/v1 surface is described by an OpenAPI document so you can generate clients and let agents discover the endpoints. The public rate card is served as JSON at /api/v1/pricing, and the endpoint reference and error codes live in the docs.
How are rate limits enforced?
Limits are applied per tenant. When you exceed your limit the API returns 429 with a Retry-After header; back off and retry. High-volume and Enterprise plans get raised limits and priority replay throughput.
What does a call cost?
Costs are in credits. A read is 1, a solved goal is 10, a compile is 50, and a deterministic replay is 1. Metered LLM cost is passed through at 1× and billed as the higher of the flat price and actual usage. Failed, cancelled, or unsolved actions are fully refunded.

Prefer tools over endpoints?

The same engine is an MCP server for Claude and Cursor and a one-line LangChain adapter.