Run your first paid job
Check your balance, inspect an endpoint, run a job over the CLI, MCP or REST, read the result and the receipt, and retry safely with an idempotency key.
This page walks through one paid run, start to end. You need a token with the runs.execute scope and
a balance above the run’s price. A new workspace starts at $0, so top up before your first run.
Check your balance
looot balance// call the balance toolA new workspace starts at $0 and there is no trial credit. If the output shows a top-up line, add at least the minimum it names first, then come back. See Before your first run.
Inspect the endpoint or job
Inspect an endpoint id your search returned. The answer has its exact input schema, output schema,
price formula and estimated maximum cost. looot inspect job:<id> is not supported yet; run
the job directly and read requestedJob on the result to see which endpoint was picked.
Run it
looot run job:people.email.verify --input '{"email":"jane.doe@example.com"}' --wait{
"endpointId": "job:people.email.verify",
"input": { "email": "jane.doe@example.com" },
"idempotencyKey": "<new unique key>",
"wait": 20
}curl -X POST "https://api.looot.ai/v1/runs?wait=20" \
-H "Authorization: Bearer $LOOOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"endpointId":"job:people.email.verify","input":{"email":"jane.doe@example.com"},"idempotencyKey":"<key>"}'endpointId: "job:<job id>" runs the job: looot picks the first provider that can run for
your workspace and accepts your input, and reports the pick and why in requestedJob. You can
also run a specific endpoint id directly. wait (CLI: --wait, REST: ?wait=) blocks until
the run finishes, up to 60 seconds, and returns the finished run inline; past the window, or
with wait omitted, you get the queued or running run back and follow it with runs get.
idempotencyKey is required on REST; the CLI makes one for you (looot-<uuid>) and prints it
on stderr if you don’t pass one.
Read the run
looot runs get <run-id>
looot runs list// runs_get { "runId": "<run-id>" }
// runs_list { "limit": 20 }A run reports looot’s own status separately from the provider’s own response status.
runs list (CLI) and runs_list (MCP) take a status filter and page with a cursor.
Read the receipt
looot runs evidence <run-id>// runs_evidence { "runId": "<run-id>" }Every attempt made for the run: its status, the provider’s response status, latency, the receipt id and the cost. Raw provider headers and bodies are never included.
Run statuses
| Status | Meaning |
|---|---|
queued, running |
Still in progress. Check again with runs get. |
pending_provider |
The provider is still working on a long job. The hold stays open until it finishes. |
completed |
Done. result holds the data and actualCost what you were charged. |
failed |
The call failed. error says why. |
blocked |
Refused before it ran, for example insufficient_balance. Nothing was charged. |
stopped |
You cancelled it. |
reconciliation_pending |
The outcome is uncertain. The hold stays reserved until it is resolved. |
looot run exits with code 1 when the finished run is failed or blocked, so a script can rely
on the exit code.
What you pay
- Hold. When the run is admitted, looot reserves the endpoint’s estimated cost from your
balance. You see it under
reservedinlooot balance. - Settle. When the provider answers, the hold closes. A completed call is charged its actual
cost and any unused part of the hold goes back to your balance. For a flat per-call price, the
charge equals the price
inspectshowed. - Failure. A call that fails at the provider is charged $0 and the hold is released.
- Refusal. A run refused before it starts (not enough balance, bad input, a disabled endpoint) never takes a hold and costs nothing.
Prices that scale with the number of results reserve for an upper bound on results. The charge is the actual cost of what came back, never more than three times the hold. See Before your first run.
Idempotency keys: retry without paying twice
Every run needs an idempotency key: idempotencyKey in the body, or the Idempotency-Key
header. The CLI makes one for you if you don’t pass one.
- Running again with the same key and the same input returns the original run, marked
replayed: true. It never starts a second run and never charges twice, even while the first one is still in flight. - The same key with a different input is refused with
409 idempotency_conflict. - After a network error or timeout, retry with the same key: if the first request did reach the gateway, you get that run back and no new run starts.
After a run is refused for insufficient_balance, top up and retry with a new key. The old
key stays attached to the refused run.