CAPABILITY · JOBS
Work that outlives the request, with a signed callback
Submit a run as a background job and get an id immediately — then poll it, stream its status, or receive an HMAC-signed webhook when it completes.
POST /api/v1/jobs → 202 { jobId }Capability
Inside async jobs & webhooks
A synchronous run holds the connection for its whole duration, which is right when your agent is waiting on the answer and wrong when the work is a ten-minute crawl. Jobs are the same execution with a different cadence: submit, get an id, and pick how you find out it finished — poll, stream, or a signed webhook you can verify.
Three ways to learn it finished
Poll GET /jobs/{id}, subscribe to GET /jobs/{id}/stream for status frames as the engine transitions, or set callbackUrl and receive a POST on completion.
Webhooks you can actually verify
With callbackSecret set, the delivery carries x-twin-signature: sha256=<hex HMAC of the raw body>, plus x-twin-event (job.completed | job.failed | job.cancelled) and x-twin-job-id. Delivery retries a couple of times and never blocks the job.
Cancellation is a full refund
POST /jobs/{id}/cancel best-effort aborts the in-flight work, flips the run to cancelled and refunds the reservation in full. Cancelling an already-terminal job is a no-op that returns its state.
Jobs park too
A sign-in job that hits a 2FA wall parks like a synchronous run: GET /jobs/{id} reports status "paused" with a sessionId, and POST /runs/{id}/resume continues it.
How it works
The mechanism, in execution order
4 stages, in the order the runtime performs them — not a summary of them.
- 1SubmitPOST /api/v1/jobs with a run body plus optional callbackUrl / callbackSecret. The response is 202 with a jobId.
- 2ReserveThe worst-case credit cost is reserved up front, so a job cannot start work it cannot pay for.
- 3ObservePoll, stream status frames, or wait for the callback. Billing settles once on the first terminal status.
- 4SettleComplete charges, failed and cancelled refund. A client that disconnected from the stream settles on its next poll.
In practice
A call you can paste and run
Verify the signature over the RAW body before you trust the payload — that is what callbackSecret is for.
curl -X POST https://twin-browser.com/api/v1/jobs \
-H "Authorization: Bearer $TWIN_API_KEY" \
-H "content-type: application/json" \
-d '{"url":"https://portal.example.com/reports",
"prompt":"download every statement for Q2",
"success":{"kind":"extracted"},
"callbackUrl":"https://your.app/hooks/twin",
"callbackSecret":"whsec_REPLACE_ME"}'
# → 202 { "jobId": "job_…" }
# The callback your endpoint receives:
# x-twin-event: job.completed
# x-twin-job-id: job_…
# x-twin-signature: sha256=<hex hmac of the raw body>- Submitdone
- Reserverunning
- Observequeued
- Settlequeued
What it costs, how to switch it on
Priced from the same rate card the API serves
Every credit figure on this page is read from the rate card behind GET /api/v1/pricing — it is not typed into the copy, so it cannot drift from what you are billed.
10-credit floor per job
A job is priced like a run: higher-of(10-credit floor, metered model + compute + egress), reserved at submit and settled once on the first terminal status. Failed and cancelled jobs are refunded in full. A crawl submitted as a job is priced per page instead (3 credits each), and a deep search per scraped page.
Turning it on
- 1Swap /run for /jobsThe body is the same. What changes is that you get an id instead of a result.
- 2Add a callbackcallbackUrl plus callbackSecret turns polling into a push. Always set the secret — without it you cannot authenticate the delivery.
- 3Verify the signatureHMAC-SHA256 the RAW request body with your secret and compare, in constant time, against the hex after `sha256=`.
- 4Handle the paused statusA sign-in job can come back paused. Keep the sessionId and resume it the same way you would a synchronous run.
At a glance
The contract, in the fewest rows that say it
| Property | Twin Browser |
|---|---|
| Submit | POST /api/v1/jobs → 202 { jobId } |
| Poll | GET /api/v1/jobs/{id} |
| Stream | GET /api/v1/jobs/{id}/stream (SSE) |
| Cancel | POST /api/v1/jobs/{id}/cancel (full refund) |
| Webhook headers | x-twin-event · x-twin-job-id · x-twin-signature |
| Signature | sha256=<hex HMAC of the raw body> |
Limits
Where it stops, and what it deliberately does not do
A capabilities page with no limits section is a brochure. These are the ceilings, the defaults that will surprise you, and the things this capability is not.
Limits and defaults
- Callback delivery is best-effort with a couple of retries; it is fire-and-forget from the job's perspective and never blocks completion.
- callbackSecret requires callbackUrl — a secret with nowhere to send is not a configuration.
- Billing settles once, on the first terminal status. A disconnected stream client settles on its next poll.
- Cancellation is best-effort against in-flight engine work: it stops the job and refunds, it does not undo side effects already performed on the target site.
What it does not do
- It does not queue indefinitely for you. A job is a background execution, not a scheduler — for recurring work, use a monitor.
- It does not sign a callback you did not give a secret for. Without callbackSecret there is no x-twin-signature header.
- It does not deliver partial results. The callback fires on a terminal status.
- It does not retry a failed run automatically. A failure is refunded and returned, not silently re-attempted.
FAQ
Questions about async jobs & webhooks
When should I use a job instead of a run?
How do I verify the completion webhook?
What does cancelling cost?
Can a job pause for a human?
Keep reading
The rest of the platform
The capabilities this one works with, the tools that expose it, the guides that use it end to end, and the vocabulary behind it.
Change monitoring
A monitor reads a value on a cadence, hashes it, compares it to last time, and posts an HMAC-signed webhook only when it actually moved.
Site mapping & crawl
Discover a site's URLs from its sitemap, robots and a shallow link scan for a flat fee — then run a bounded, resumable, robots-respecting crawl that can extract per page.
Live view & session video
POST /api/v1/live streams the browser back as Server-Sent Events while the agent works, and an opted-in run keeps a durable video you can fetch long afterwards.
Tools that expose it
Guides
Related reading
Put your agent to work. Keep the decision.
Start free. Hand your agent a goal on a site you authorize, set the guardrails, and let the first successful run compile the skill every run after it replays.