Docs
From zero to your first call
Pick a route, run a free tool, and read how requests, errors, retries and spend limits work. The free tools need no key.

Choose a route
MCP, the REST API and the SDKs reach every tool. x402 reaches the tools that accept it. MCP and the REST API run the free tools without a key.
- MCPAdd Strale’s MCP server to Claude Desktop, Claude Code, Cursor or any MCP client. The agent searches and calls tools itself.
- REST APIOne endpoint,
POST /v1/do, from any language. One API key and one wallet balance cover every tool. - SDKsTypeScript and Python clients, and packages for LangChain, CrewAI and Composio.
- x402No account and no key. Your agent pays in USDC per request on 275 eligible tools and 89 eligible bundled checks.
Make your first call
The first call runs IBAN Validation, a free tool. The API and MCP calls need no key. Without a key you get 300 free calls a month per IP address, across all free tools. The SDK calls take an API key, and a free tool costs nothing with one.
# Free tool: works without a key, within a monthly allowance. Add your key for more.
curl -X POST https://api.strale.io/v1/do \
-H 'Content-Type: application/json' \
-d '{
"capability_slug": "iban-validate",
"inputs": {
"iban": "SE4550000000058398257466"
},
"max_price_cents": 5
}' {
"tool": "strale_execute",
"arguments": {
"slug": "iban-validate",
"inputs": {
"iban": "SE4550000000058398257466"
},
"max_price_cents": 5
}
} import { Strale } from "straleio";
const strale = new Strale({ apiKey: process.env.STRALE_API_KEY! });
const result = await strale.do({
capability_slug: "iban-validate",
inputs: {
"iban": "SE4550000000058398257466"
},
max_price_cents: 5,
}); import os
from straleio import Strale, DoRequest
strale = Strale(api_key=os.environ["STRALE_API_KEY"])
result = strale.do(DoRequest(
capability_slug="iban-validate",
inputs={
"iban": "SE4550000000058398257466",
},
max_price_cents=5,
)) {
"bban": "50000000058398257466",
"valid": true,
"bank_code": "500",
"branch_code": null,
"check_digits": "45",
"country_code": "SE",
"expected_length": 24
} The output above is the tool’s published example. A live call returns the same fields for your input. More free tools: free tools. For a key, sign up.
Request and response
Every tool runs through POST https://api.strale.io/v1/do. Send a JSON body. With a key, add Authorization: Bearer $STRALE_API_KEY.
| Field | Type | Meaning |
|---|---|---|
capability_slug | string | The tool to run, for example iban-validate. Send this or task. |
task | string | Describe the job in words and Strale picks the tool. Use capability_slug when you know the tool. |
inputs | object | The tool’s inputs. Each tool page lists them. |
max_price_cents | integer | The most you will pay for this call, in euro cents, from 1 to 2000 (€20.00). Required with an API key. Optional without one, where only free tools run. |
timeout_seconds | integer | How long to wait for the tool. Default 30, maximum 60. |
dry_run | boolean | Returns the tool that would run and its price. Nothing runs and nothing is charged. |
A successful call
A success is HTTP 200 with a result and a meta block. Types are shown as words; output is the tool’s own example.
{
"result": {
"transaction_id": "string",
"status": "completed",
"capability_used": "iban-validate",
"price_cents": "integer",
"latency_ms": "integer",
"wallet_balance_cents": "integer",
"output": {
"bban": "50000000058398257466",
"valid": true,
"bank_code": "500",
"branch_code": null,
"check_digits": "45",
"country_code": "SE",
"expected_length": 24
},
"provenance": {
"source": "string",
"fetched_at": "ISO 8601 timestamp"
}
},
"meta": {
"audit": {
"…": "audit record"
}
}
} price_centsis what this call cost, in euro cents. It is0for free tools.wallet_balance_centsis your balance after the call. Calls without a key do not carry it; they carryfree_tier: trueand ausageblock with the calls used this month, the monthly limit and when it resets.provenancenames the source that answered and when it was fetched.meta.auditis the audit record for the call.
A failed call
A failure is a non-200 status with error_code, message and, where there is more to say, details. Branch on error_code; the codes are stable.
{
"error_code": "budget_exceeded",
"message": "Capability 'address-geocode' costs €0.02 (2 cents) which exceeds your max_price_cents of 1.",
"details": {
"capability_slug": "address-geocode",
"actual_price_cents": 2,
"max_price_cents": 1
}
} Slow tools
Tools that take longer than 10 seconds run in the background. The call returns HTTP 202 with status: "executing", the transaction_id and meta.audit.poll_url. Poll GET /v1/transactions/{transaction_id} until status is completed or failed. The SDKs poll for you.
Handle errors and retries
You are charged when a call succeeds. A call that fails is not charged, and a bundled check that fails in every step is refunded. A bundled check that returns results for some steps is charged in full.
error_code | HTTP | What happened | What to do |
|---|---|---|---|
invalid_request | 400 | The body is missing a field or a value is out of range, or the Idempotency-Key is longer than 255 characters. | Fix the request. Do not retry it unchanged. |
unauthorized | 401 | The key is missing or wrong, or the tool needs a key and the call had none. A paid tool that accepts x402 answers a keyless call with a 402 price quote instead. | Send Authorization: Bearer with a valid key, or pay over x402. |
insufficient_balance | 402 | The wallet holds less than the tool costs. details has wallet_balance_cents and required_cents. | Top up with POST /v1/wallet/topup (minimum €10.00), then retry. |
budget_exceeded | 402 | The tool costs more than max_price_cents. details.actual_price_cents has the price. | Raise max_price_cents if the price is acceptable. |
no_matching_capability | 404 | No tool matches the task or slug within the budget. | Check the slug on the tools page, or rephrase the task. |
rate_limited | 429 | A key may send 10 requests a second. Without a key, free tools allow 300 calls a month per IP address. | Wait for the Retry-After seconds, then retry. After the monthly allowance, use a key. |
spend_cap_exceeded | 429 | The call would take the account past its hourly spend limit. details has spent_cents, requested_cents and limit_cents. | Wait for the hour to roll over, or ask for a higher limit. |
execution_failed | 500 | The tool ran and failed, usually because its source did not answer. details.error says why. Not charged. | Retry with backoff. If the same input fails again, the input is the cause. |
capability_unavailable | 503 | The tool is switched off for now. Not charged. | Retry later, or use another tool for the job. |
timeout_exceeded | 503 | The call ran past its time limit, or waited too long on a busy wallet. Not charged. | Retry with backoff. |
idempotency_key_reused | 409 | The Idempotency-Key was already used for a different request. | Send a new key. |
Retry only 429, 500 and 503 responses, and wait a little longer after each: one second, then two, then four. Never retry a 400 without changing the request.
Retry safely and cap spend
Idempotency
Send an Idempotency-Key header on POST /v1/do to make a retry safe. If a call times out on your side, send it again with the same key. Strale returns the first result with meta.idempotency_replay: true and does not run or charge the call twice. Keys work on calls made with an API key, up to 255 characters. Use a new key for a new call, and for a deliberate second attempt after a failure.
curl -X POST https://api.strale.io/v1/do \
-H "Authorization: Bearer $STRALE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{"capability_slug": "iban-validate", "inputs": {"iban":"SE4550000000058398257466"}, "max_price_cents": 1}' The SDKs take the same value as idempotency_key.
Spend caps
- Per call.
max_price_centsis a ceiling on one call. A tool that costs more is refused withbudget_exceededbefore it runs. - Per hour. Each account has an hourly spend limit, €100.00 by default. Calls past it are refused with
spend_cap_exceeded. To change it, write to petter@strale.io. - Your balance. Calls are paid from a prepaid wallet. When it is empty, calls are refused with
insufficient_balance. - Preview a price. Add
"dry_run": trueto see which tool would run and what it costs.
Retrieve a past call
Every call made with an API key has a transaction_id. Fetch the record with it.
curl https://api.strale.io/v1/transactions/$TRANSACTION_ID \
-H "Authorization: Bearer $STRALE_API_KEY" const record = await strale.transaction(transactionId); record = strale.transaction(transaction_id) {
"tool": "strale_transaction",
"arguments": {
"transaction_id": "<transaction_id>"
}
} - The record has the status, the input and output, the price, the latency, the provenance and the audit record.
- Input, output, error and audit content are cleared 90 days after the call. The record of the call itself stays.
GET /v1/transactionslists your most recent calls.- Calls made without a key can be looked up by anyone with the ID, with the content left out.
- x402 responses carry no transaction ID. The payment details are in
_meta.paymentof the response.
API reference
The full machine-readable reference is the OpenAPI document at https://api.strale.io/openapi.json. Send Accept: text/markdown for a readable version. It also lists the x402 endpoints.
GET https://api.strale.io/v1/capabilitieslists every tool with its inputs, outputs and price.- Each tool page shows the inputs, output fields, price and limits for one tool.
GET https://api.strale.io/v1/wallet/balancereturns your balance in euro cents.