# List fixed workflows and country coverage
Source: https://docs.apiosk.com/api-reference/ask/list-fixed-workflows-and-country-coverage
/openapi/apiosk-api.json get /v2/ask/workflows
Free. Requires sources:read. Uses the same recipes as the App. Availability reflects planning, not paid result validation.
# Balance and key limits
Source: https://docs.apiosk.com/api-reference/balance-and-key-limits
/openapi/apiosk-api.json get /v2/balance
Free. Requires billing:read.
# Browse source endpoints
Source: https://docs.apiosk.com/api-reference/browse-source-endpoints
/openapi/apiosk-api.json get /v2/sources/{source_id}/endpoints
Compact, paginated endpoint index across one source or the Pulse Network group. A listed endpoint can be discovery-only; endpoint.planner_available marks runtime-accepted contracts. Requires sources:read.
# Call a source
Source: https://docs.apiosk.com/api-reference/call-a-source
/openapi/apiosk-api.json post /v1/execute/{source}/{operation}
Buy one call. The body is the operation's inputs. Requires sources:execute. Also available at /v2/execute/{source}/{operation}.
# Call a source (explicit form)
Source: https://docs.apiosk.com/api-reference/call-a-source-explicit-form
/openapi/apiosk-api.json post /v2/sources/{source_id}/run
The same call with a named envelope. Requires sources:execute.
# Call a source (v2 alias)
Source: https://docs.apiosk.com/api-reference/call-a-source-v2-alias
/openapi/apiosk-api.json post /v2/execute/{source}/{operation}
Buy one call. The body is the operation's inputs. Requires sources:execute. Also available at /v2/execute/{source}/{operation}.
# Continue a saved run
Source: https://docs.apiosk.com/api-reference/continue-a-saved-run
/openapi/apiosk-api.json post /v2/asks/{id}/continue
Requires ask:execute and the same key that created the task. Submit a returned select_entity or supply_input action with its signed state. Resumes existing approved work without buying the search twice. Never approves a new quote. Idempotency-Key is required; retry the same state, action and input unchanged.
# Discover the same API choices as the Ask page
Source: https://docs.apiosk.com/api-reference/discover-the-same-api-choices-as-the-ask-page
/openapi/apiosk-api.json post /v2/ask
Requires ask:create. A question uses the shared App interpreter/search and creates no task, approval or paid provider request. Explicit workflow objects retain their plan/auto behavior.
# Execute the API selected from Ask
Source: https://docs.apiosk.com/api-reference/execute-the-api-selected-from-ask
/openapi/apiosk-api.json post /v2/execute
Requires sources:execute. Uses the same selected preparation, authorization and balance executor as the App. Reusing the idempotency key with the same selection/input recovers the saved run. The existing signed App/MCP continuation body remains supported separately.
# Find fitting European source operations
Source: https://docs.apiosk.com/api-reference/find-fitting-european-source-operations
/openapi/apiosk-api.json post /v2/capabilities/resolve
Free endpoint routing for a structured European capability. Requires sources:read; no provider call or charge.
# Gateway health
Source: https://docs.apiosk.com/api-reference/gateway-health
/openapi/apiosk-api.json get /health
Public protocol and executor readiness; does not prove a paid source call.
# List sources
Source: https://docs.apiosk.com/api-reference/list-sources
/openapi/apiosk-api.json get /v2/sources
Free directory of verified sources, including discovery-only and restricted entries. Requires sources:read.
# Plan a question across sources
Source: https://docs.apiosk.com/api-reference/plan-a-question-across-sources
/openapi/apiosk-api.json post /v2/ask/plan
Plan across sources. Free in plan mode. Requires ask:create, and ask:execute for auto mode.
# Price a structured European capability
Source: https://docs.apiosk.com/api-reference/price-a-structured-european-capability
/openapi/apiosk-api.json post /v2/capabilities/plan
Save one total-price plan from fitting operations. Requires ask:create. Execution requires a separate POST /v2/asks/{id}/run with ask:execute.
# Public source readiness
Source: https://docs.apiosk.com/api-reference/public-source-readiness
/openapi/apiosk-api.json get /v1/source-readiness
Aggregate contract and recorded execution coverage, not an exhaustive live source test.
# Read a run
Source: https://docs.apiosk.com/api-reference/read-a-run
/openapi/apiosk-api.json get /v2/runs/{id}
Free. Also available at GET /v2/asks/{id}.
# Read an ask
Source: https://docs.apiosk.com/api-reference/read-an-ask
/openapi/apiosk-api.json get /v2/asks/{id}
Free. Also available at GET /v2/asks/{id}.
# Read one source
Source: https://docs.apiosk.com/api-reference/read-one-source
/openapi/apiosk-api.json get /v2/sources/{source_id}
Free. Currently executable operations, schemas and buyer prices. Discovery-only sources can return source_not_found. Requires sources:read.
# Run a plan
Source: https://docs.apiosk.com/api-reference/run-a-plan
/openapi/apiosk-api.json post /v2/asks/{id}/run
Approve the plan against this key's limits and run it. Running twice is the same run. Requires ask:execute.
# Usage for this key
Source: https://docs.apiosk.com/api-reference/usage-for-this-key
/openapi/apiosk-api.json get /v2/usage
Free. This month's spending and recent charges. Requires billing:read.
# Ask
Source: https://docs.apiosk.com/api/ask
Get the same API choices as the Ask page, then execute the selected API with your inputs.
## Discover APIs for a question
`POST /v2/ask` requires `ask:create`. It uses the Ask page's interpreter and
source searches, returning choices from Apiosk and Coinbase Bazaar. Discovery
makes no paid provider request and creates no plan or approval.
The two surfaces share the discovery implementation. Separate requests can
produce different wording or alternative providers because model interpretation
and directory listings vary; responses are not guaranteed to be identical.
```bash theme={null}
curl https://gateway.apiosk.com/v2/ask \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Find filed accounts for Mollie B.V."}'
```
The body contains `question` only: 1–16000 UTF-16 code units. The response has
`parsed_request`, `apis`, both origin results in `searches`, and `errors`.
`status` is `choices`, `needs_input` when no choices match, or `partial` if an
origin search is unavailable. Inspect every choice's `executable` flag.
| Choice field | Meaning |
| - | - |
| `api_id` | Opaque selection ID to copy into `/v2/execute`; do not construct it |
| `capability` | Exact operation for this selection; copy it alongside `api_id` |
| `name`, `source_slug`, `origin`, `url` | Source/provider identity and published URL |
| `executable` | The server has admitted an executable contract for this choice |
| `inputs` | Declared input fields, required flags and JSON schemas |
| `input_values` | Literal values bound from the question and declared defaults |
| `missing_inputs` | Required fields you must supply before execution |
| `outputs` | Declared output fields and schemas, or `null` if unpublished |
| `lookup` | Available native name lookup when a company identifier is missing |
| `buyer_price` | Current per-call buyer price in millionths of USDC (`buyer_atomic`) |
Output **values** arrive after execution. Discovery returns output contracts;
it does not fabricate source data. A directory-only choice has
`executable: false`. Even an executable choice may need additional inputs.
Review the fields and total spending cap; a native lookup can add steps and cost.
## Execute the selected API
`POST /v2/execute` requires `sources:execute`, `Idempotency-Key`, and `max_spend`.
It uses the same selected-source preparation, approval, executor and ledger as
the Ask page. It does not reinterpret the question or choose a replacement API.
```bash theme={null}
curl https://gateway.apiosk.com/v2/execute \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Idempotency-Key: my-selected-api-request-1" \
-H "Content-Type: application/json" \
-d '{
"api_id":"COPY_FROM_ASK",
"capability":"COPY_FROM_ASK",
"input":{"company.name":"Mollie B.V."},
"max_spend":"0.10",
"wait_seconds":25
}'
```
Replace the example `input` with the selected choice's `input_values`, plus any
missing fields. Preserve the exact field names. `max_spend` is the approved
**total** in USD, not an atomic amount. The current price, key limits and balance
are checked before purchase. Reuse the same idempotency key and selection/input
for retries; changed selection/input under that key returns `409`.
Registered APIs return `completed` with `results`/`data` and `usage`. External
providers return the saved purchase view: `succeeded`, `result`, `result_present`
and ledger-backed `billing`. Both return `id`; `running` uses HTTP `202`.
Read `GET /v2/runs/{id}` to recover progress and results. A successful payment
with `result_present: false` needs read-only recovery, never another purchase.
External execution is asynchronous; `wait_seconds` applies to registered APIs.
To verify a deployment, send the same question through Ask and this endpoint,
compare source IDs, capabilities, input/output contracts and prices, then run
one selected API within an approved cap. Repeat the identical execution request
and check that the run ID, saved output and ledger charge are unchanged.
### View saved annual accounts
The App presents supported structured annual accounts with named key figures,
balance-sheet and income-statement tables, and numbers formatted for the
browser's locale. The financial year and source dates remain visible. A currency
is shown only when supplied by the source; the billing currency does not establish
the currency of the accounts. The filing year may be older than the current year.
Opening the full result reuses the saved data without another provider purchase.
Choose **View full answer** to open it. On phones, pull down from the drawer's
handle or header to close it; a short pull settles back into place. The close
button remains available, and the answer scrolls between the fixed header and footer.
**Full source data** and JSON preserve the original response. CSV exports the
labelled financial fields and their source values. The HTTP API continues to
return source data rather than the App's display formatting.
## Optional multi-source planner
The previous question-to-plan contract is available at `/v2/ask/plan`. Move
clients that send `execution_mode`, `limit` or `wait_seconds` with a question
to that path. Its saved-run, approval and continuation endpoints are unchanged.
Explicit [workflow requests](/api/workflows) remain supported by `/v2/ask`.
```http theme={null}
POST /v2/ask/plan
```
Requires `ask:create`.
```bash theme={null}
curl https://gateway.apiosk.com/v2/ask/plan \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Idempotency-Key: intent-signals-2026-09-22" \
-H "Content-Type: application/json" \
-d '{"question":"Find the registered address and the latest filed accounts for Mollie B.V.","limit":5}'
```
| Field | Type | Default | Meaning |
| - | - | - | - |
| `question` | string, 1–4000 chars | required unless `workflow` is supplied | The question, in the user's own words |
| `execution_mode` | `"plan"` or `"auto"` | `"plan"` | `auto` runs the plan straight away when it fits `max_spend` |
| `max_spend` | decimal USD | none | Required with `auto`; the ceiling for the whole plan |
| `limit` | integer 1–50 | none | Cap the number of result documents returned |
| `wait_seconds` | integer 0–55 | 25 | With `auto`, how long to wait before answering `202` |
```json theme={null}
{
"id": "5c1f…",
"status": "requires_approval",
"question": "Find the registered address and the latest filed accounts for Mollie B.V.",
"plan": {
"quote_ref": "9ad2…",
"expires_at": "2026-09-22T18:40:00Z",
"steps": [
{ "source_id": "kvk-dutch-business-register", "operation": "company_registry.search", "name": "Company search",
"conditional": false,
"estimated_cost": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" } },
{ "source_id": "kvk-dutch-business-register", "operation": "company.financial-statements", "name": "Annual accounts",
"conditional": false,
"estimated_cost": { "amount": 0.115, "amount_micro_usd": "115000", "currency": "USD" } }
],
"estimated_total": { "amount": 0.138, "amount_micro_usd": "138000", "currency": "USD" }
},
"usage": { "sources": [], "cost": { "amount": 0, "amount_micro_usd": "0", "currency": "USD" } },
"errors": []
}
```
The plan and amounts above illustrate the response shape; read live source
details for current prices. Planning is free. estimated\_total is
the maximum the run may cost; you are charged what the sources actually cost,
which can be less.
### Run it later
```http theme={null}
POST /v2/asks/{id}/run
```
Requires `ask:execute`.
```bash theme={null}
curl https://gateway.apiosk.com/v2/asks/5c1f…/run \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Content-Type: application/json" \
-d '{"max_spend":1.00,"limit":5}'
```
Running an ask twice returns the same run. It never starts a second purchase.
## Run it immediately
```json theme={null}
{
"question": "Find the registered address and the latest filed accounts for Mollie B.V.",
"execution_mode": "auto",
"max_spend": 1.00,
"limit": 5
}
```
With `auto`, Apiosk runs the plan without a second call, but only when all four
hold: the plan's maximum cost is within `max_spend`, within the key's
per-request limit, within what the key may still spend this month, and within
the organisation's balance.
If the plan costs more than `max_spend`, you get the plan back, unrun and
unbilled:
```json theme={null}
{
"id": "5c1f…",
"status": "requires_approval",
"approval_required_reason": {
"code": "max_spend",
"message": "The plan's maximum cost is above max_spend, so it was not run. Nothing was charged."
},
"plan": { "estimated_total": { "amount": 1.44, "amount_micro_usd": "1440000", "currency": "USD" } }
}
```
## Clarify before buying
A needs\_input response may contain field schemas, a natural
language message, or both. Ask the person for the missing
context; never fill it in by guessing. A needs\_selection response
offers candidates, so ask which entity they meant.
When the response includes `continuation`, use
[`POST /v2/asks/{id}/continue`](/api/continue) to select a candidate or supply
the requested structured value on the same saved task. A paid search is not
repeated. Selection resumes the remaining work under the original valid
approval; a new quote created by supplied input requires an explicit `/run`.
A natural-language clarification without `continuation` still requires a new
clarified Ask. Inspect the earlier run's results and usage first; do not
automatically repeat a paid request. Document uploads use the App.
## Statuses
| `status` | Meaning | What to do |
| - | - | - |
| `requires_approval` | A priced plan is ready | `POST /v2/asks/{id}/run` |
| `running` | The plan is executing (HTTP `202`) | Poll `GET /v2/runs/{id}` |
| `completed` | Every step finished | Read `answer`, `results`, `usage` |
| `partial` | Some steps failed or were skipped | Read `errors` beside the results you did get |
| `needs_input` | The question is missing something | Use `continuation` for structured input, or read the clarification in `message` |
| `needs_selection` | Several entities match | Choose from `candidates` and continue the saved task through `/continue` |
| `unsupported` | No source can answer this | Nothing was charged |
| `failed` | The run failed (HTTP `502`) | `error` and `errors` say why; see `usage` for what was charged |
## Status codes
| Status | Code | Meaning |
| - | - | - |
| 200 | — | A plan, or a finished run |
| 202 | — | Still running after `wait_seconds` |
| 400 | `invalid_request` | `question` empty or over 4000 characters, or `auto` without `max_spend` |
| 401 | `invalid_api_key` | See [Authentication](/api/authentication) |
| 402 | `insufficient_balance` / `spend_limit_exceeded` | Nothing was charged |
| 403 | `insufficient_scope` | `ask:create`, and `ask:execute` for running |
| 409 | `idempotency_conflict` / `plan_expired` / `plan_not_ready` | Ask again for a fresh plan |
| 422 | `unsupported` | No source can answer the question |
| 429 | `rate_limit_exceeded` | Wait a minute, then retry with the same key |
| 502 | `source_error` | The run failed; read `usage` for what was charged |
# Authentication
Source: https://docs.apiosk.com/api/authentication
Organisation API keys: how to create one, what it may do, and what it spends.
The buyer HTTP API uses an organisation API key. The app and hosted MCP
server use account sign-in and connections.
```http theme={null}
Authorization: Bearer apk_org_live_…
```
Base URL: `https://gateway.apiosk.com`
## Create a key
[Sign up](https://app.apiosk.com/signup), choose a team account, and confirm
your email. An organisation owner or admin then creates keys in the app
under **Organisation → API keys**. A key has a name, an expiry date, a
per-request limit, a monthly limit and a set of permissions.
The secret is shown **once**, at creation. Apiosk stores only its hash and can
never show it again; if it is lost, revoke the key and create another.
A key belongs to the organisation, not to the person who created it. All keys
of one organisation spend from the same main balance, each within its own
limits. Revoking a key stops it immediately, including runs it has not started.
## Permissions
A key is created with the permissions it needs, and nothing else.
| Scope | Allows |
| - | - |
| `sources:read` | `GET /v2/sources`, `GET /v2/sources/{source_id}` |
| `sources:execute` | `POST /v2/execute` (selected API), `POST /v1/execute/{source}/{operation}`, `POST /v2/sources/{source_id}/run` |
| `ask:create` | `POST /v2/ask` discovery and `POST /v2/ask/plan` planning |
| `ask:execute` | `POST /v2/asks/{id}/run`, and `POST /v2/ask/plan` with `execution_mode: "auto"` |
| `billing:read` | `GET /v2/balance`, `GET /v2/usage` |
## Check that a key works
```bash theme={null}
curl https://gateway.apiosk.com/v2/balance \
-H "Authorization: Bearer $APIOSK_KEY"
```
```json theme={null}
{
"organisation_id": "0d2a…",
"balance": { "available": { "amount": 47.82, "amount_micro_usd": "47820000", "currency": "USD" } },
"key": {
"id": "8c41…",
"name": "Nomi Production",
"scopes": ["sources:read", "sources:execute", "ask:create", "ask:execute", "billing:read"],
"expires_at": "2027-09-22T16:41:08Z"
},
"limits": {
"per_request": { "amount": 2, "amount_micro_usd": "2000000", "currency": "USD" },
"monthly": { "amount": 100, "amount_micro_usd": "100000000", "currency": "USD" },
"month_spent": { "amount": 0.54, "amount_micro_usd": "540000", "currency": "USD" },
"month_remaining": { "amount": 99.46, "amount_micro_usd": "99460000", "currency": "USD" },
"month_start": "2026-09-01T00:00:00Z"
}
}
```
## Refusals
| Status | Code | Meaning |
| - | - | - |
| 401 | `invalid_api_key` | No key, or a key Apiosk does not know |
| 401 | `api_key_expired` | The key passed its expiry date |
| 401 | `api_key_revoked` | The key was revoked in the app |
| 403 | `insufficient_scope` | The key lacks the permission this endpoint needs; `required_scope` names it |
| 403 | `organisation_unavailable` | The organisation cannot spend from its main balance right now |
```json theme={null}
{
"error": {
"code": "insufficient_scope",
"message": "This API key does not have the permission this endpoint needs. An organisation admin can create a key that has it.",
"required_scope": "sources:execute"
}
}
```
## Handling keys
* **Keep the secret server-side.** It can spend the organisation's balance up to its limits.
* **One key per environment.** Production and staging get their own key, their own limits and their own usage line.
* **Rotate by creating and revoking.** Create the new key, deploy it, then revoke the old one; both work while you switch.
# Balance and usage
Source: https://docs.apiosk.com/api/billing
What a call costs, when money moves, and how to read a key's spending.
Amounts are in **USD**, the currency the ledger charges in. Every amount carries
a decimal `amount` and the exact integer `amount_micro_usd`, so you never have
to trust a rounding.
## What a call costs
The price in a source detail is the buyer total for that operation. There is no
separate charge to add to that quoted total. The sum of
usage.sources\[].cost equals usage.cost for every
run.
## How money moves
1. **Approve.** The plan's maximum cost is checked against the key's
per-request limit, its monthly limit and the organisation's balance.
2. **Reserve.** Before a source is called, its cost is reserved on the balance.
3. **Run.** The source is called.
4. **Settle.** The actual cost is charged and the remainder released.
A call that fails is refunded. A call whose outcome is unknown stays held until
it is reconciled, and is never charged twice. Because the reservation happens
before the provider is called, a balance can never go negative.
## Balance
```http theme={null}
GET /v2/balance
```
Requires `billing:read`.
```json theme={null}
{
"organisation_id": "0d2a…",
"balance": { "available": { "amount": 47.82, "amount_micro_usd": "47820000", "currency": "USD" } },
"key": { "id": "8c41…", "name": "Nomi Production", "scopes": ["sources:read"], "expires_at": "2027-09-22T16:41:08Z" },
"limits": {
"per_request": { "amount": 2, "amount_micro_usd": "2000000", "currency": "USD" },
"monthly": { "amount": 100, "amount_micro_usd": "100000000", "currency": "USD" },
"month_spent": { "amount": 0.54, "amount_micro_usd": "540000", "currency": "USD" },
"month_remaining": { "amount": 99.46, "amount_micro_usd": "99460000", "currency": "USD" },
"month_start": "2026-09-01T00:00:00Z"
}
}
```
The balance is the organisation's and is shared by all of its keys. The limits
are this key's alone.
## Usage
```http theme={null}
GET /v2/usage?limit=50
```
Requires `billing:read`. Returns what this key spent this month and its most
recent charges, newest first.
| Query parameter | Type | Default | Meaning |
| - | - | - | - |
| `limit` | integer 1–200 | 50 | How many charges to return |
```json theme={null}
{
"key_id": "8c41…",
"organisation_id": "0d2a…",
"month_start": "2026-09-01T00:00:00Z",
"month_spent": { "amount": 0.54, "amount_micro_usd": "540000", "currency": "USD" },
"charges": [
{
"id": "c19f…",
"status": "charged",
"cost": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" },
"created_at": "2026-09-22T16:58:11Z",
"source_id": "kvk-dutch-business-register",
"operation": "company_registry.search",
"name": "Company search",
"run_id": "6f0b…"
}
]
}
```
`charged` is settled money. `reserved` is held for a call in flight.
`refunded` was given back and counts against nothing.
The run that produced the charge; read it back with `GET /v2/runs/{id}`.
## Topping up
Balances are funded in the app, under **Organisation → Billing**. An
organisation's main balance is separate from any workspace budget: API keys
spend the main balance only.
| Status | Code | Meaning |
| - | - | - |
| 200 | — | The balance or usage |
| 401 | `invalid_api_key` | See [Authentication](/api/authentication) |
| 403 | `insufficient_scope` | The key lacks `billing:read` |
| 403 | `api_key_required` | `GET /v2/usage` is per key; people read usage in the app |
# Continue a run
Source: https://docs.apiosk.com/api/continue
Choose a company or supply missing input on the same saved task, without buying its search again.
An Ask can pause after a paid search because several companies match. Select
the intended company on that same run. Apiosk retains the paid search, the
original quote and its approval, and resumes the remaining work.
```http theme={null}
POST /v2/asks/{id}/continue
```
Requires `ask:execute` and the same API key that created the task.
`Idempotency-Key` is required: use a new key for each choice or supplied input,
and keep it unchanged on transport retries.
## Read the current continuation
`POST /v2/ask/plan`, `POST /v2/asks/{id}/run` and `GET /v2/runs/{id}` return
`continuation` when the task has a supported action:
* `select_entity`: choose an `entity_ref` from the returned `candidates`.
* `supply_input`: provide `value` matching the returned `input_schema`.
`continuation.state` is a signed snapshot. Copy the entire object unchanged;
do not construct its fields. `continuation.actions` supplies the action ID,
label and input schema. Never choose a company by array position alone.
## Select a company
The following uses the saved response `run` and an `entityRef` selected by
the caller from its candidates. Keep `body` and `idempotencyKey` for retries.
```javascript theme={null}
const action = run.continuation.actions.find(a => a.kind === "select_entity");
const body = {
state: run.continuation.state,
action_id: action.action_id,
input: { entity_ref: entityRef },
wait_seconds: 25
};
const idempotencyKey = crypto.randomUUID();
const response = await fetch(`https://gateway.apiosk.com/v2/asks/${run.id}/continue`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey
},
body: JSON.stringify(body)
});
const updatedRun = await response.json();
```
For a `supply_input` action, send `input: { value: suppliedValue }`. The
value can be a string, number or other type specified by its schema.
| Body field | Required | Meaning |
| - | - | - |
| `state` | Yes | Exact `continuation.state` from this run |
| `action_id` | Yes | ID of the returned selection or input action |
| `input` | Yes | Object matching that action's `input_schema` |
| `wait_seconds` | No | Wait up to 55 seconds; default 25 |
| `limit` | No | Return at most 1–50 result documents |
## Approval and recovery
The response is the usual [run object](/api/runs), with the same `id`, saved
results and cumulative usage. `202` means the worker is still running;
poll `GET /v2/runs/{id}`. A successful selection under a valid approval needs
no second `/run` call. The endpoint cannot approve a plan or raise a budget.
If supplied input produces a new quote, the response is `requires_approval`.
Review its ceiling and call `/run` explicitly. An expired original quote is
refused with `409 plan_expired`; its saved results remain readable.
After a timeout, retry the exact same state, action, input and
`Idempotency-Key`. Even after the action was consumed, its saved receipt
returns the current run without selecting or buying twice. `limit` and
`wait_seconds` only affect presentation and may change between retries.
After `409 continuation_changed`, read the run again. If it still offers an
action, review it and submit its current state with a new idempotency key.
Do not start a replacement Ask to recover an uncertain continuation.
Natural-language clarifications without a `continuation` and document
uploads are outside this endpoint. See [Ask](/api/ask#clarify-before-buying).
## Status codes
| Status | Code | Meaning |
| - | - | - |
| 200 / 202 | — | Updated run or execution still running |
| 400 | `invalid_request` / `invalid_continuation_state` | Missing key, invalid fields, mismatched task or altered signed state |
| 401 / 403 | Authentication / scope error | Use the task's key with `ask:execute` |
| 404 | `run_not_found` | Task unavailable to this key |
| 409 | `continuation_changed` | Expired state, consumed action or concurrent update; read the run |
| 409 | `idempotency_conflict` / `request_in_progress` | Changed input under the same key, or first request still running |
| 409 | `run_cancelled` / `plan_expired` | Saved run cannot resume under this quote |
| 422 | `invalid_continuation_input` | Candidate is not offered or value violates the schema |
| 429 / 503 | Availability error | Recover the saved run; retry unchanged when appropriate |
| 502 | `source_error` | A resumed source step failed; inspect results and usage |
# Errors
Source: https://docs.apiosk.com/api/errors
One error shape, one code per reason, and whether money moved.
Buyer API refusals use the error shape below. The shared source-list route
can return the Gateway v2 envelope with an errors array for
a request without a key or with an invalid query. Failed runs return the
run object with an embedded error and usage, so
you can see what was charged. Read the run errors and usage together; a
provider failure does not by itself mean the whole run was free.
```json theme={null}
{
"error": {
"code": "insufficient_balance",
"message": "The balance is too low for this plan's maximum cost. Top up in Apiosk > Balance. Nothing was charged.",
"required": { "amount": 0.42, "amount_micro_usd": "420000", "currency": "USD" },
"available": { "amount": 0.17, "amount_micro_usd": "170000", "currency": "USD" }
}
}
```
`code` is stable and safe to branch on. `message` is written for a person
reading a log. Extra fields depend on the code and are listed below.
## Buyer API and shared directory codes
| Status | Code | Extra fields | Meaning |
| - | - | - | - |
| 400 | `invalid_request` | — | Malformed body, `max_spend`, `limit` or `Idempotency-Key` |
| 400 | invalid\_query | — | Invalid directory or endpoint-index filter |
| 400 | `invalid_workspace` | — | Organisation keys do not take a workspace header |
| 400 | `invalid_continuation_state` | — | Copy the signed continuation state unchanged from the run |
| 401 | `invalid_api_key` | — | Missing or unknown key |
| 401 | `api_key_expired` | — | Past its expiry date; create a new key |
| 401 | `api_key_revoked` | — | Revoked in the app |
| 402 | `insufficient_balance` | `required`, `available` | Top up the organisation's balance |
| 402 | `spend_limit_exceeded` | `limit`, `required`, `available` | `limit` is `per_request`, `monthly` or `max_spend` |
| 403 | `insufficient_scope` | `required_scope` | The key lacks that permission |
| 403 | `organisation_unavailable` | — | The organisation cannot spend from its main balance right now |
| 403 | `spending_not_permitted` | — | This caller may not spend in this workspace |
| 404 | `source_not_found` | — | No purchasable source with this id or name |
| 404 | `operation_not_found` | `operations` | The source has no such operation |
| 404 | `run_not_found` | — | No run with this id belongs to this key |
| 409 | `idempotency_conflict` | — | Same `Idempotency-Key`, different body |
| 409 | `ambiguous_operation` | `sources` | Two sources in a group offer this operation; call one by id |
| 409 | `request_in_progress` | `retry_after_ms` | The first request with this key is still running |
| 409 | `plan_not_ready` | — | The ask has no priced plan yet |
| 409 | `plan_expired` | — | The plan's price expired; ask again |
| 409 | `plan_changed` | — | The plan changed while it was being approved |
| 409 | `continuation_changed` | — | Read the run and review its current continuation; do not repeat a paid Ask |
| 409 | `run_cancelled` | — | The run was cancelled and is not restarted |
| 422 | `invalid_source_input` | `field`, `expected`, `missing`, `schema` | An input is unknown, missing or malformed |
| 422 | `invalid_continuation_input` | — | Use an offered candidate or a value matching the action schema |
| 422 | `unsupported` | — | No source can answer this question |
| 429 | busy | — | Shared directory concurrency limit; retry shortly |
| 429 | `rate_limit_exceeded` | — | Too many requests; wait and retry with the same key |
| 502 | `source_error` | — | The source could not complete the run |
| 503 | planner\_unavailable | — | The question could not be interpreted right now |
| 503 | catalog\_unavailable | — | Source directory unavailable; retry shortly |
| 503 | `source_unavailable` | — | The source is temporarily unreachable |
| 503 | `service_unavailable` | — | Apiosk could not complete the request; retry with the same key |
| 503 | `approval_unconfirmed` | — | Read the run's status before retrying; do not start a new request |
| 504 | `source_timeout` | — | The source did not answer in time |
## Did money move?
* **Authorization, validation and budget refusals before dispatch** do
not start a purchase. A failed run can arrive after a source was called;
inspect its usage.
* **A failed run** returns HTTP 502 with the run body: usage
shows what was charged, and anything undelivered was refunded or is held
until reconciled.
* **When in doubt, read the run.** GET /v2/runs/ is free
and authoritative.
## Retrying
| Code | Retry? |
| - | - |
| `rate_limit_exceeded`, `service_unavailable`, `source_unavailable`, `source_timeout` | Yes, with the same `Idempotency-Key` |
| `request_in_progress` | Yes, after `retry_after_ms` |
| `approval_unconfirmed` | Read the run first; do not start a new request |
| `continuation_changed` | Read the run, then use its current action/state and a new key if input is still needed |
| `insufficient_balance`, `spend_limit_exceeded` | Only after topping up or raising the limit |
| `invalid_source_input`, `insufficient_scope`, `idempotency_conflict` | No; fix the request |
# Call a source
Source: https://docs.apiosk.com/api/execute
Buy one call from one source: the path names what to run, the body carries the inputs.
This is the shortest paid call Apiosk has. No model interprets anything: you
name the source and the operation, and Apiosk runs exactly that.
Requires `sources:execute`.
## Execute an Ask choice
Use `POST /v2/execute` with `api_id`, `capability`, `input`, and `max_spend` from
the [Ask choice flow](/api/ask#execute-the-selected-api). This form requires
`Idempotency-Key` and uses the same selected-source execution as the Ask page.
The source/operation paths below remain available.
## Request
```http theme={null}
POST /v1/execute/{source}/{operation}
POST /v2/execute/{source}/{operation}
```
Both paths are the same endpoint. The body is the operation's inputs and
nothing else:
```bash theme={null}
curl https://gateway.apiosk.com/v1/execute/kvk-dutch-business-register/company_registry.search \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Idempotency-Key: nomi-request-983472" \
-H "Content-Type: application/json" \
-d '{"company.name":"Mollie B.V."}'
```
| Query parameter | Type | Default | Meaning |
| - | - | - | - |
| `max_spend` | decimal USD | none | Refuse before paying if the plan's maximum cost is higher |
| `wait_seconds` | integer 0–55 | 25 | How long to wait for the result before answering `202` |
| `limit` | integer 1–50 | none | Cap the number of result documents returned |
The `Idempotency-Key` header is optional and strongly recommended; see
[Idempotency](/api/idempotency).
### What the path accepts
The source must have a currently executable operation in its source detail. A discovery-only directory entry cannot be called.
* **Source**: its id, its name, or a provider that groups several sources
(`pulsenetwork`), case-insensitive. For a group, the call runs on the member
that offers the operation; if two members offer it, you get `409
ambiguous_operation` naming them, and call one by its own id.
* **Operation**: its capability (`company_registry.search`), its endpoint id, or its name.
* **Variants**: some operations have several variants with different inputs —
a KVK lookup by KVK number or by branch number. The call runs the variant
whose inputs you supply; if none fits, `422` lists what each variant needs.
### What the body accepts
Each input may be named three ways, so you can use whichever you have:
| Form | Example |
| - | - |
| The fact type, as `GET /v2/sources/{id}` lists it | `{"company.name": "Mollie B.V."}` |
| The name the source's own API uses | `{"naam": "Mollie B.V."}` |
| The last word, when it is unambiguous for that operation | `{"name": "Mollie B.V."}` |
## Response
The amounts below illustrate the response shape, not a current KVK quote. Read the source detail for the current buyer price before running.
`200` with the finished run:
```json theme={null}
{
"id": "6f0b…",
"status": "completed",
"question": "Run company_registry.search on kvk-dutch-business-register",
"plan": {
"quote_ref": "b41c…",
"expires_at": "2026-09-22T18:12:04Z",
"steps": [
{
"source_id": "kvk-dutch-business-register",
"operation": "company_registry.search",
"name": "Company search",
"conditional": false,
"estimated_cost": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" }
}
],
"estimated_total": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" }
},
"answer": null,
"data": {},
"results": [
{
"result_ref": "a72e…",
"source": { "provider": "kvk-dutch-business-register", "name": "KVK Business Register" },
"data": {}
}
],
"usage": {
"sources": [
{ "source_id": "kvk-dutch-business-register", "operation": "company_registry.search", "calls": 1,
"cost": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" } }
],
"cost": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" },
"held": { "amount": 0, "amount_micro_usd": "0", "currency": "USD" }
},
"balance": { "remaining": { "amount": 47.797, "amount_micro_usd": "47797000", "currency": "USD" } },
"errors": []
}
```
The source's own document, present when the run produced exactly one — which a
direct call normally does. The same document is in `results[0].data`.
Where the result came from: source, operation, retrieval time, the source's
page, the record's own links, subject, identifiers such as a KVK number, and cost. Present on every entry of
`results`, and at the top level when there is one. See
[Sales signals](/api/sales-signals#what-every-result-carries).
What the ledger actually charged. It equals the sum of `usage.sources[].cost`.
Money reserved for a call that has not settled yet. It is released or charged
when the call resolves.
The organisation's balance after this run.
## Status codes
| Status | Code | Meaning |
| - | - | - |
| 200 | — | The run finished; read `status` for `completed`, `partial`, `unsupported` or `needs_input` |
| 202 | — | Still running after `wait_seconds`; poll `GET /v2/runs/{id}` |
| 400 | `invalid_request` | Malformed body, `max_spend`, `limit` or `Idempotency-Key` |
| 401 | `invalid_api_key` | See [Authentication](/api/authentication) |
| 402 | `insufficient_balance` | Top up the organisation's balance |
| 402 | `spend_limit_exceeded` | `limit` says which ceiling: `per_request`, `monthly` or `max_spend` |
| 403 | `insufficient_scope` | The key lacks `sources:execute` |
| 404 | `source_not_found` | No purchasable source has this id or name |
| 404 | `operation_not_found` | The source has no such operation; `operations` lists what it has |
| 409 | `idempotency_conflict` | The same key with a different body |
| 409 | `ambiguous_operation` | Two sources in a group offer this operation; `sources` names them |
| 422 | `invalid_source_input` | A field is unknown, missing, or does not match its schema |
| 429 | `rate_limit_exceeded` | Wait, then retry with the same `Idempotency-Key` |
| 502 | `source_error` | The source could not complete the run |
Everything that refuses before a purchase says so: **nothing was charged**.
```json theme={null}
{
"error": {
"code": "invalid_source_input",
"message": "Required inputs are missing. Nothing was charged.",
"missing": ["company.name"]
}
}
```
A direct call buys only the named source. If an operation needs an input that
only another source can supply, Apiosk refuses with `422` rather than buying
that other source for you. Supply the input, or use [Ask](/api/ask).
## The explicit form
```http theme={null}
POST /v2/sources/{source_id}/run
```
```json theme={null}
{
"operation": "company_registry.search",
"input": { "company.name": "Mollie B.V." },
"max_spend": 1.00,
"wait_seconds": 25
}
```
Same engine, price and response. Use it when a client builds requests from the
catalogue and prefers a named envelope over a path.
# Idempotency
Source: https://docs.apiosk.com/api/idempotency
Retry a paid call safely: the same key pays once.
A timeout is not an answer. Send an `Idempotency-Key` on every paid call, and a
retry returns the first result instead of buying it again.
```http theme={null}
Idempotency-Key: nomi-request-983472
```
1–255 visible ASCII characters. Use one value per intent — a request id from
your own system is ideal.
## What it guarantees
| You send | Apiosk does |
| - | - |
| The same key, the same body | Returns the same run. Pays at most once. |
| The same key, a different body | `409 idempotency_conflict`. Nothing is charged. |
| No key | Every call is a new request, and a retry is a second purchase. |
Keys are scoped to the calling API key and the logical operation. Two keys,
or two different source operations, can use the same string without
colliding. The v1 and v2 direct-call path aliases identify the same logical
operation.
## Where it applies
| Endpoint | Behaviour |
| - | - |
| `POST /v1/execute/{source}/{operation}` | Honours `Idempotency-Key` |
| `POST /v2/sources/{source_id}/run` | Honours `Idempotency-Key` |
| `POST /v2/ask` (question) | Free discovery; retries may reflect a refreshed catalogue |
| `POST /v2/execute` (selected API) | Requires `Idempotency-Key`; same selection/input recovers one purchase |
| `POST /v2/ask/plan` and workflow Ask | Honours `Idempotency-Key`; a retry returns the same plan or run |
| `POST /v2/asks/{id}/run` | Idempotent by itself — an ask runs once, key or no key |
| `POST /v2/asks/{id}/continue` | Requires `Idempotency-Key`; same state/action/input resumes the same run. `limit` and `wait_seconds` may change. |
Continuations without a key are refused. Their keys are scoped to the calling
key and task. Keep the original signed state when retrying the same choice;
use a new idempotency key for a newly reviewed action.
## Retrying in practice
```bash theme={null}
key="nomi-request-983472"
curl https://gateway.apiosk.com/v1/execute/kvk-dutch-business-register/company_registry.search \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Idempotency-Key: $key" \
-H "Content-Type: application/json" \
-d '{"company.name":"Mollie B.V."}'
```
If that call times out on your side, send it again **unchanged**. You get the
same run id, the same result and the same single charge.
While the first request is still running, a retry answers `409
request_in_progress` with a `retry_after_ms`. Wait that long and retry; it is
not an error, and nothing was charged twice.
## Runs already in flight
A run that is still executing answers `202` with its id. Polling
`GET /v2/runs/{id}` is always free and never starts anything new.
# Limits
Source: https://docs.apiosk.com/api/limits
What bounds a key: money, rate and lifetime.
## Spending
| Limit | Set where | Checked |
| - | - | - |
| **Per request** | On the key, in the app | Against the maximum cost of a whole call or plan |
| **Monthly** | On the key, in the app | Against everything the key spent this calendar month (UTC) |
| **`max_spend`** | Per request, by you | Against the plan's maximum cost, before anything is paid |
| **Balance** | Organisation's main balance | Before each source call is made |
Limits are checked twice: when a plan is approved, and again under a lock when
each call reserves its money. Parallel requests cannot overspend a limit
between them — twenty calls at once queue on the same ledger lock.
Reservations count against the monthly limit while they are held. A refunded
call counts for nothing.
The month resets on the first of the calendar month, UTC. `GET /v2/balance`
returns `month_spent`, `month_remaining` and `month_start`.
## Rate
* **60 requests per minute per organisation.** All keys of one organisation share it.
* **A bounded number of requests execute at once.** Over that, Apiosk answers
`429 rate_limit_exceeded`; wait and retry with the same `Idempotency-Key`.
## Keys
* **25 active keys per organisation.** Revoke one to create another.
* **Expiry options in the app: 30, 90, 180, 365 or 730 days**, chosen at creation. An expired key answers
`401 api_key_expired`; nothing else changes.
## Waiting
For a direct call, an automatic Ask and a plan run, wait\_seconds
defaults to 25 and is capped at 55. A run still executing answers HTTP 202
with its id. A status read at GET /v2/runs/ returns
immediately by default; pass wait\_seconds if you want it to
wait. Status reads are free.
## Sizes
* Request bodies up to 64 KB.
* `limit` on results: 1 to 50 documents.
* `Idempotency-Key`: 1 to 255 visible ASCII characters.
# Runs
Source: https://docs.apiosk.com/api/runs
Read a run: its status, its results, what it cost and what is left.
Every paid call — direct or Ask — produces a run with the same shape. A run's
id is the `id` of the ask or call that created it.
## Read a run
```http theme={null}
GET /v2/runs/{id}
GET /v2/asks/{id}
```
Both are the same endpoint. Only the key that created a run can read it.
```bash theme={null}
curl "https://gateway.apiosk.com/v2/runs/5c1f…?wait_seconds=10" \
-H "Authorization: Bearer $APIOSK_KEY"
```
| Query parameter | Type | Default | Meaning |
| - | - | - | - |
| `wait_seconds` | integer 0–55 | 0 | Wait for a running run to finish before answering |
| `limit` | integer 1–50 | none | Cap the number of result documents returned |
An approved run whose worker stopped — a deploy, a crash — is resumed from its
saved journal when you read it. Nothing is paid twice: work already paid for is
never re-dispatched.
## The run object
```json theme={null}
{
"id": "5c1f…",
"status": "completed",
"question": "…",
"plan": { "quote_ref": "9ad2…", "expires_at": "…", "steps": [], "estimated_total": {} },
"answer": {
"status": "completed",
"observations": [{ "text": "The registry lists KVK number 30204462.", "evidence": [{ "result_ref": "a72e…", "pointer": "/data/companies/0/kvkNummer" }] }],
"limitations": []
},
"results": [{ "result_ref": "a72e…", "source": { "provider": "kvk-dutch-business-register", "name": "KVK Business Register" }, "data": {} }],
"usage": {
"sources": [{ "source_id": "kvk-dutch-business-register", "operation": "company_registry.search", "calls": 1, "cost": {} }],
"cost": { "amount": 0.023, "amount_micro_usd": "23000", "currency": "USD" },
"held": { "amount": 0, "amount_micro_usd": "0", "currency": "USD" }
},
"balance": { "remaining": { "amount": 47.797, "amount_micro_usd": "47797000", "currency": "USD" } },
"errors": []
}
```
Apiosk's reading of the results, with a pointer into the document behind every
observation. Present when the question asked for one; `null` for a direct call.
The source documents themselves, each with the source that produced it and a
`result_ref` you can quote in support tickets.
Per-step problems, each with a code and a message. A `partial` run has both
results and errors.
Present when a paused run accepts a company selection or structured input.
Contains the signed `state` and permitted `actions`, including their input
schemas. [Continue the saved task](/api/continue) using the same API key.
## Status codes
| Status | Code | Meaning |
| - | - | - |
| 200 | — | The run, in whatever state it is |
| 202 | — | Still running |
| 401 | `invalid_api_key` | See [Authentication](/api/authentication) |
| 404 | `run_not_found` | No run with this id belongs to this key |
| 502 | `source_error` | The run failed; `usage` shows what was charged |
# Sales signals
Source: https://docs.apiosk.com/api/sales-signals
Find current tenders, funding leads, news and company records.
Apiosk can combine several kinds of source data for a sales or research
question. Source availability, exact inputs and prices can change. Browse
the live directory before building a fixed integration.
## Find relevant sources
Search the source directory for terms such as tenders,
funding, news and
company registry:
```bash theme={null}
curl -G https://gateway.apiosk.com/v2/sources \
-H "Authorization: Bearer $APIOSK_KEY" \
--data-urlencode "search=tenders"
```
Inspect available\_in\_v2,
executable\_capabilities and readiness.
Then call GET /v2/sources/ for the operations,
input schemas and current prices that the runtime accepts. A registered
endpoint or advertised capability alone is not an execution promise.
Pulse Network is one source group with multiple services. Search for
Pulse Network to see matching services; inspect its source
detail to see the currently runnable operations and each operation's
underlying source\_id.
## Let Ask combine sources
For a question involving several signal types, request a free plan first:
```bash theme={null}
curl https://gateway.apiosk.com/v2/ask/plan \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Find recent tenders and company news for Dutch cybersecurity companies","execution_mode":"plan","limit":10}'
```
The response may ask for a country, company, period or other detail, or it
may return a priced plan. Answer a clarification before buying. Review the
plan's exact source steps and total ceiling; then run that saved plan with
POST /v2/asks//run if it answers the intended question.
## Read the evidence
Every returned document has its source, retrieval time and result reference.
Its metadata can include a source URL, links present in the
source record, subject identifiers, operation and actual charge. Missing
records or partial coverage should be reported as such; they are not evidence
that no tender, funding event or news item exists elsewhere.
# Sources
Source: https://docs.apiosk.com/api/sources
Browse the directory and inspect currently executable operations.
Browsing is free. The directory covers verified listings; it does not imply
that every upstream endpoint has an accepted execution contract.
## List sources
```http theme={null}
GET /v2/sources
```
Requires sources:read.
| Query | Type | Meaning |
| - | - | - |
| search | String, at most 200 characters | Name, description, category, tags, sectors and capabilities |
| category | String | Exact returned category |
| tag | String | Exact returned tag |
| sector | String | Exact returned sector |
| capability | String | Sources advertising that capability; check execution availability separately |
| offset | Integer | Page start; continue with next\_offset |
| limit | Integer 1–50 | Page size, default 20 |
```bash theme={null}
curl -G https://gateway.apiosk.com/v2/sources \
-H "Authorization: Bearer $APIOSK_KEY" \
--data-urlencode "search=company registry"
```
The response has sources, total for this
filter, catalog\_total for the entire directory and
next\_offset for pagination. Counts are live and can change.
Each provider group is counted once. Pulse Network can contain many nested
services; service\_count is the full number and
services contains the matching services in this query.
For each row:
* endpoint\_count counts registered endpoints, including
endpoints that cannot currently run.
* capabilities can include advertised capabilities.
* executable\_capabilities lists capabilities accepted by the
current runtime.
* available\_in\_v2 is true when at least one operation in the
source group can run.
* readiness describes contract and evidence coverage. An
unmeasured endpoint is not proof of reliable execution.
## Read one executable source
```http theme={null}
GET /v2/sources/{source_id}
```
Requires sources:read. Use a source's returned slug, for
example:
```bash theme={null}
curl https://gateway.apiosk.com/v2/sources/kvk-dutch-business-register \
-H "Authorization: Bearer $APIOSK_KEY"
```
The response lists only currently executable operations.
Each operation includes its id, source\_id,
input fields and schemas, outputs, current buyer price and optional
variants. For a provider group, each operation names the member service
that actually runs it. Use that operation and its inputs in
[Call a source](/api/execute).
A directory entry with no accepted operation can return
404 source\_not\_found on this detail route. It remains
discoverable so you can see its published metadata; it cannot be bought
through the buyer API until a contract is accepted.
## Resolve a European capability to fitting sources
```http theme={null}
POST /v2/capabilities/resolve
```
Requires sources:read. This read-only route accepts one of
eu.company.profile, eu.tenders.search or
eu.statistics.query, an optional two-letter country, and
structured input using the fact-type names returned by source detail.
An optional operation narrows the response to one metric or
lookup operation within the capability.
```bash theme={null}
curl https://gateway.apiosk.com/v2/capabilities/resolve \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Content-Type: application/json" \
-d '{"capability":"eu.company.profile","country":"NL","input":{"company.name":"Mollie B.V."}}'
```
The response returns primary and supplementary sources with only their
active, accepted operations. Each operation names its exact endpoint,
required and missing inputs, output fields, freshness interval, current
price, and run\_url. ready means the supplied
inputs fit that operation's schema; it is not evidence that the upstream
source has a record for the subject. ready\_source\_count
counts sources with at least one ready operation. No provider is called and
no balance is charged by resolution.
For Eurostat data, send a dataset code in
eurostat.input.dataset and a country. Apiosk fills the
eurostat.input.geo endpoint parameter from that country, including
Eurostat's EL and UK codes for Greece and the United
Kingdom. It does not choose a dataset or statistical measure on your behalf.
To let Apiosk choose source operations from the structured input, create one
priced plan:
```http theme={null}
POST /v2/capabilities/plan
```
This route requires ask:create and accepts the same body as
resolution. It returns the saved plan with one total ceiling and no purchase.
Review the exact steps, then call POST /v2/asks//run with
ask:execute and max\_spend to approve it once. The
ordinary worker executes the selected sources and returns saved, sourced
results. Capability plans and runs also return normalized\_records:
contract-extracted facts grouped by subject, with observed and expiry times.
Subjects with the same country-specific or globally unique identifier are
combined; identical facts retain all source references. Source documents
remain in results for inspection; subjects are never merged by
name alone. The API accepts an Idempotency-Key for safe plan
retries.
For a direct, single-source call, use
POST /v2/sources//run with the returned
operation and that operation's input. This uses the
same pricing, key spending limits, ledger and result metadata. It executes
immediately within the key's spending limits.
For CBS observation tables with no required parameters, specify the exact
operation when planning, such as
statistics.cbs-company-counts. The planner does not guess a
statistical metric from a country alone. General questions can use
POST /v2/ask/plan to get a model-built plan.
The tender group currently offers TenderNed public-contract browsing and
organisation-based TED matches. It does not expose general TED Search API
queries through Apiosk yet. EU Funding & Tenders provides funding calls,
not procurement notices, so it is outside eu.tenders.search.
Likewise PDOK location data is outside eu.statistics.query.
## Browse endpoints inside a source
The compact endpoint index is useful when a provider publishes many services:
```http theme={null}
GET /v2/sources/{source_id}/endpoints?search=filings&limit=40&offset=0
```
Requires sources:read. The response contains
total, items and
next\_offset. Each item names the service
slug and listing, then a compact endpoint
with its id, method, path, description, category, tags and use cases.
endpoint.planner\_available tells you whether that exact
endpoint has a runtime-accepted planner contract. A listed endpoint
without that flag cannot be quoted or executed through the buyer API.
Search and paginate rather than downloading every endpoint at once.
For Pulse Network, use pulsenetwork as the source id to
browse endpoints across its nested services.
## Check readiness without a key
GET /v1/source-readiness returns aggregate, public contract
coverage and recorded execution outcomes. It is a diagnostic snapshot,
not a live test of every endpoint or a guarantee about source data.
# European company and tender dossiers
Source: https://docs.apiosk.com/api/workflows
Fixed source plans for identity, screening, filings and tender counterparties, with explicit country coverage.
## Discover current coverage
`GET /v2/ask/workflows` requires `sources:read` and is free. It returns the same fixed recipes used by the App, their input fields, source steps, limitations and `country_coverage`. Each country has its own `available` and `unavailable_reason`. Availability means the gateway can build that plan; records still depend on the company, source and reporting period.
| Workflow | Country coverage | Included |
| - | - | - |
| `european-company-dossier` | NL, GB, FR, BE, FI, NO, LV, EE, SE, DK, SK | Registered identity, screening of the registry-returned name, available accounts or filing records |
| `tender-company-dossier` | NL, FR counterparties | Company dossier plus bounded public-contract or notice links |
The Netherlands uses KVK profiles and the supported XBRL account subset. Great Britain uses Companies House profiles and filing-history metadata. France uses Sirenic profiles and available annual financial figures. The other listed countries use Sirenic national-registry profiles and country-specific account/deposit records. Filing references are not downloaded documents.
Screening uses OpenSanctions and the legal name returned by the registered profile, with a country hint. A possible match requires review. Missing matches do not certify compliance. Owners, directors and subsidiaries are not screened individually.
The Dutch tender dossier adds TenderNed name mentions and TED numeric identifier matches; the identifier scheme and legal-entity link remain unconfirmed. The French dossier adds Sirenic French public-contract records and European notice links for the French company. This is not exhaustive Europe-wide tender discovery, an awards ledger or automatic screening of every party in a tender list.
## Prepare one dossier
`POST /v2/ask` requires `ask:create`. Supply `workflow` instead of `question`:
```json theme={null}
{
"workflow": {
"slug": "tender-company-dossier",
"input": {
"name": "Mollie B.V.",
"country": "NL",
"registration": "30204462"
}
},
"execution_mode": "plan"
}
```
Send a stable `Idempotency-Key`. The gateway validates the fields and country, saves one task and quotes the full source plan. No purchase occurs during planning. Unknown countries, missing sources and malformed identifiers are refused rather than silently dropping a check.
The returned run uses the standard [Ask response](/api/ask). Approve it with `POST /v2/asks/{id}/run` and a total `max_spend`. Fixed workflows use the existing 20% workflow fee, included in the quote. Source results and actual charges remain on the saved run. Polling or replaying the approved run does not buy it again.
`execution_mode: "auto"` also works with a required `max_spend`, subject to the same source-verification and spending checks as free-text Ask. [Continue](/api/continue) any returned structured input or selection on the same task.
## App and MCP
The App exposes both dossiers through its existing Workflows and Ask routes. In MCP, `apiosk_discover` accepts the same `workflow` object instead of `question`; it returns the normal approval card and saved task. Continue through `apiosk_execute` and `apiosk_status`. Never invent a registration number to fill the form: resolve the company first when the identifier is unknown.
# API keys
Source: https://docs.apiosk.com/app/api-keys
Create, limit and revoke the keys your servers use.
Organisation API keys live in the app, under **Organisation → API keys**. An
owner or an admin manages them; a key belongs to the organisation, not to the
person who made it.
## Create one
| Field | What it does |
| - | - |
| **Name** | Shown in the list and in usage, for example `Nomi Production` |
| **Expires after** | 30 to 730 days. The key stops working on that date |
| **Per-request limit** | The most one call or one plan may cost |
| **Monthly limit** | The most this key may spend in a calendar month (UTC) |
| **Permissions** | Discover sources, run sources, plan with Ask, run Ask plans, read balance and usage |
The secret appears **once**, right after creation:
```
apk_org_live_…
```
Copy it into your secret store then. Apiosk keeps only a hash of it and can
never show it again. Lost a secret? Revoke the key and create another.
Anyone holding the secret can spend the organisation's balance up to that key's
limits. Keep it server-side: never in a browser bundle, a mobile app or a
public repository.
## What the list shows
Per key: its prefix (`apk_org_live_1a2b3c4d…`), its permissions, the
per-request limit, what it has spent this month against its monthly limit, when
it expires, and when it was last used. A key that has never been used says so.
## Limits
Both ceilings are enforced twice: when a plan is approved and again when each
call reserves its money, under a lock. Parallel calls cannot overspend between
them.
* **Per request** rejects a call whose maximum cost is too high, before paying.
* **Monthly** counts every charge of this key this calendar month; reservations
count while held, refunds count for nothing.
* **The balance** is the organisation's main balance, shared by all its keys.
A refusal arrives as `402 spend_limit_exceeded`, naming which ceiling, and
nothing is charged.
## Revoke
Revoking is immediate and cannot be undone. Requests with that key stop at
once, including runs it had started but not dispatched. Other keys are
unaffected. Revoked keys stay in the list, marked, so usage history keeps its
name.
## Good practice
* **One key per environment.** Production and staging get separate keys, limits and usage lines.
* **Rotate by overlap.** Create the new key, deploy it, then revoke the old one.
* **Set a monthly limit you would be comfortable losing.** It is the ceiling on a mistake.
* **Read usage per key** with `GET /v2/usage`, which is scoped to the calling key.
Next: [authenticate with it](/api/authentication) and [make a call](/api/execute).
# Connections
Source: https://docs.apiosk.com/app/connections
How an assistant comes to hold a credential that can spend, and what bounds it.
A connection lets an AI client — ChatGPT, Claude, an agent runtime — act for one
person's Apiosk account, within limits that person set.
The rule behind the whole flow: **a person is the authority on money; software
is the authority on nothing.** The assistant does the typing; the person makes
the decision.
## The flow
1. **Invitation.** In the app, under **Integrations**, the person starts a
connection. They get a short invitation to paste into the assistant.
2. **Intent.** The assistant registers what it is and what it wants to be
called, and receives a verification link to hand back.
3. **Approval.** The person opens that link, signs in, and sets the two
ceilings: per request and per day. A short code confirms the approval.
4. **Tokens.** The assistant exchanges the code for its own access and refresh
tokens. The secret itself never passes through the assistant's prompt.
Connecting through a client that supports OAuth — the [MCP server](/mcp/overview)
— collapses steps 1 to 4 into the client's own consent screen.
## What a connection may do
| | |
| - | - |
| **Spends from** | The person's own balance |
| **Per-request ceiling** | Set at approval, changeable in the app |
| **Daily ceiling** | Rolling 24 hours, set at approval |
| **Revocation** | Immediate, from **Integrations**; every token dies with it |
| **Scope** | Optionally bound to one workspace, so it spends that workspace's budget |
Each call is checked against the ceilings at the moment it reserves money, so a
burst of parallel calls cannot slip past them.
## Connections or API keys?
| | Connection | [Organisation API key](/app/api-keys) |
| - | - | - |
| Belongs to | A person | An organisation |
| Created by | Approving a client | An owner or admin, in the app |
| Spends | That person's balance | The organisation's main balance |
| Limits | Per request, per day | Per request, per month |
| Used by | ChatGPT, Claude, agent clients | Your own servers, over HTTPS |
Use a connection when a person is in the loop. Use an API key when a server
runs on its own.
# Organisations and workspaces
Source: https://docs.apiosk.com/app/organisations
Who can spend what: members, workspaces, budgets and the main balance.
An organisation owns the money. Everything else — people, workspaces, keys —
spends within what the organisation allows. To create one yourself,
[sign up](https://app.apiosk.com/signup), choose a team account, and
confirm your email.
```
Organisation
├── Main balance funds API keys, and feeds workspace budgets
├── Members owner, admin, member
├── Workspaces each with its own budget and members
└── API keys machine credentials, main balance
```
## Members
| Role | Can |
| - | - |
| **Owner** | Everything, including transferring ownership and managing admins |
| **Admin** | Manage workspaces, members, budgets and API keys |
| **Member** | Work in the workspaces they belong to |
An organisation always has at least one owner. Admins are invited by email from
**Organisation → Members**.
## Workspaces
A workspace is a team's own space, with its own balance and its own members.
Workspace roles are separate from organisation roles:
| Workspace role | Can |
| - | - |
| **Admin** | Manage the workspace, its members and its settings |
| **Member** | Spend the workspace budget |
| **Viewer** | See activity, spend nothing |
## Money
* **The main balance** is topped up under **Organisation → Billing**. It funds
API keys directly.
* **A workspace budget** is allocated from the main balance and returned to it
the same way. Money moves between them; it is never created by moving.
* **Reserved funds** — a purchase in flight — cannot be allocated away until
the purchase settles.
## What spends from where
| Spender | Spends |
| - | - |
| A person in a workspace | That workspace's budget |
| A person outside any workspace | Their own balance |
| A [connection](/app/connections) bound to a workspace | That workspace's budget |
| An [API key](/app/api-keys) | The organisation's main balance |
API keys never spend a workspace budget. That is deliberate: a machine
credential has one funding source, and it is the one an admin controls.
# MCP clients
Source: https://docs.apiosk.com/guides/mcp-clients
Connect the hosted Apiosk MCP server to an assistant.
The hosted MCP URL is:
```
https://mcp.apiosk.com/mcp
```
## ChatGPT
Add the URL as a remote MCP connector. Complete the Apiosk sign-in and
connection consent when ChatGPT prompts you. If the client cached an older
tool list, refresh the connector or start a new chat.
## Claude Code
```bash theme={null}
claude mcp add --transport http apiosk https://mcp.apiosk.com/mcp
```
Then complete the account sign-in when the client opens it. The hosted
server exposes the four buyer tools described in [MCP server](/mcp/overview).
## Another MCP client
Configure a Streamable HTTP server with URL
[https://mcp.apiosk.com/mcp](https://mcp.apiosk.com/mcp) and let the client complete OAuth.
Create an Apiosk account at [app.apiosk.com/signup](https://app.apiosk.com/signup)
if you do not have one.
Browsing and planning do not charge your balance. For a paid request,
review and approve the plan's total ceiling in the interactive card. The
Gateway then runs it and saves the result. If a question lacks context,
answer the clarification rather than approving a different request.
For a backend that needs an organisation-owned credential, follow the
[API quickstart](/overview/quickstart) instead.
# Apiosk
Source: https://docs.apiosk.com/index
Ask a question, review the price, and get sourced data.
Apiosk finds data sources for a question, shows one total price before a
purchase, and returns the source documents with the actual charge. Start in
the app, connect an assistant through MCP, or use the buyer API from your
server.
Create a team, ask questions, manage its balance and read saved results.
Create an organisation key, browse sources and run a priced request.
Connect ChatGPT or Claude, review a plan and approve in the chat card.
## Self-service setup
1. [Sign up](https://app.apiosk.com/signup) and choose a team account.
2. Confirm your email, then open **Organisation → API keys** as an owner or
admin.
3. Set the key's permissions and spending limits. The secret is shown once.
4. [Follow the API quickstart](/overview/quickstart), or connect an
[MCP client](/guides/mcp-clients).
## A direct call
Read the source's current operations and price before executing. For example,
the KVK company search uses this path and input:
```bash theme={null}
curl https://gateway.apiosk.com/v1/execute/kvk-dutch-business-register/company_registry.search \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Idempotency-Key: my-request-1" \
-H "Content-Type: application/json" \
-d '{"company.name":"Mollie B.V."}'
```
The key identifies who pays; the path identifies one operation. To let
Apiosk select and price several operations, use [Ask](/api/ask).
## What the catalogue means
The directory lists verified sources, including entries that are currently
discovery-only or restricted. A source's available\_in\_v2,
readiness and executable\_capabilities show what
can be planned now. The App, MCP server and API share executable contracts
and the same price and saved-run ledger. See [Sources](/api/sources).
# MCP server
Source: https://docs.apiosk.com/mcp/overview
Connect an assistant, review one price, and receive saved source results.
Use the hosted MCP endpoint in ChatGPT, Claude or another compatible client:
```
https://mcp.apiosk.com/mcp
```
It uses Streamable HTTP and account OAuth. [Create an account](https://app.apiosk.com/signup)
first if needed. When the client requests a protected action, complete
sign-in and approve the connection and its spending limits in the app.
Connection approval sets limits; it does not approve a future data purchase.
## Tools the assistant sees
| Tool | Purpose | Can buy data? |
| - | - | - |
| apiosk\_sources | Browse and filter the source directory | No |
| apiosk\_discover | Plan a question, price it or ask for missing context | No |
| apiosk\_execute | Continue a saved task using a returned action | Only after purchase approval |
| apiosk\_status | Read saved status, results and charges | No |
The interactive card has a separate approval action that the person uses
to approve the displayed total price ceiling. The assistant must not
approve for the person. After approval the Gateway runs the task and saves
the results; the assistant should read that state instead of starting
another purchase.
## When information is missing
The card or assistant asks a clarifying question for
needs\_input, or presents candidates for
needs\_selection. Answer with the missing fact or choose
the intended entity. The saved task continues with the offered action;
there is no need to start a new purchase merely to clarify.
Browsing the directory does not promise that every published endpoint is
runnable. Check the returned availability and let
apiosk\_discover verify whether the exact question has a
priced plan.
## Spending and recovery
A connection has a per-request and daily limit. The person can change or
revoke it in the app under **Integrations**. A workspace-bound connection
spends that workspace's budget; otherwise it uses the person's balance.
Use apiosk\_status and the saved task reference for a
follow-up or interrupted response. Status reads do not buy data.
For setup commands, see [MCP clients](/guides/mcp-clients). Server
integrations without a person in the loop use an
[organisation API key](/api/authentication).
# Changelog
Source: https://docs.apiosk.com/overview/changelog
Changes to the buyer-facing App, API, and MCP contract.
## 2026-09-30
* The [Ask API](/api/ask) returns selectable API contracts; selected execution
preserves the chosen API and inputs under one total spending cap.
* Saved structured annual accounts now show readable key figures and aligned
financial tables in the App, with the original response available as JSON.
Reopening results does not buy the data again.
* **View full answer** opens the complete saved result. Mobile result drawers
support pulling down to dismiss, with a fixed header and download footer.
## 2026-09-23
* Buyer docs now follow the self-service path from team signup to an
organisation API key, source discovery, a priced plan and a saved result.
* Source discovery distinguishes listed sources from executable operations.
Use available\_in\_v2, readiness,
executable\_capabilities and the per-source operation detail.
* The hosted MCP guide describes its four assistant-visible tools and the
separate approval action in the interactive card.
## 2026-09-22
* Organisation owners and admins can create keys with permissions, expiry,
a per-request limit and a monthly limit. Keys spend the organisation's
main balance. See [API keys](/app/api-keys).
* The buyer API exposes source browsing, direct execution, Ask plans, saved
runs, balance and usage. See [Quickstart](/overview/quickstart).
# FAQ
Source: https://docs.apiosk.com/overview/faq
Answers for teams integrating the App, buyer API, or MCP server.
## Can our team create its own account and API key?
Yes. Sign up at [app.apiosk.com/signup](https://app.apiosk.com/signup), choose
a team account, and confirm your email. The owner or an admin can then open
**Organisation → API keys** to create a key with permissions and spending
limits. Keep the secret on your server; it is displayed once.
## Do API calls need a key?
The buyer API in these docs uses an organisation key sent as
Authorization: Bearer apk\_org\_live\_…. Browse sources with
GET /v2/sources, inspect executable operations with
GET /v2/sources/, and use [Ask](/api/ask) when the
source is not known. The hosted [MCP server](/mcp/overview) uses a person's
account connection instead of an organisation API key.
## Does seeing a source mean every endpoint is ready to buy?
No. The directory includes entries that are still discovery-only or
restricted. Check available\_in\_v2, readiness, and
executable\_capabilities; then read one source for the currently
executable operations, exact inputs, and prices. Do not infer availability
from a source name or its raw endpoint count.
## When does a question cost money?
Browsing and planning are free. A purchase starts only after the plan is
authorized within its displayed total ceiling. The result includes actual
charges, any amount still held, and source references. See
[Prices and balance](/overview/payment-model).
## What if the question needs more context?
An Ask response can return needs\_input with a clarifying
message, or needs\_selection with candidates. Ask
the person for the missing fact or the right entity. In the app or MCP card,
continue the saved task using its offered action. In the buyer HTTP API,
submit a new clarified question; it has no input-continuation endpoint.
## What if a run takes longer than the request timeout?
HTTP 202 includes the run id. Read GET /v2/runs/ to resume
from the saved state. Retry a paid request with the same
Idempotency-Key.
## Can an API key spend a workspace budget?
No. Organisation keys spend the main balance. People and assistant
connections can spend a workspace budget when operating in that workspace.
# Prices and balance
Source: https://docs.apiosk.com/overview/payment-model
What buyers see, approve, and are charged.
Apiosk shows a price before a data purchase. The displayed total is the most
the request may cost. You approve that ceiling once; the finished run reports
the actual charge and the source behind it.
## The buying flow
1. Browse sources or ask a question. Browsing and planning are free.
2. Review the plan and its total price ceiling.
3. Approve the plan in the app or MCP card. With the API, send
max\_spend to authorize an automatic run or call the plan's run
endpoint.
4. Apiosk reserves each source call before dispatching it. Settled charges and
any funds still held appear separately in the run's usage.
5. Read the sourced result and final charge. Unused reserved money is released.
A call that did not deliver data is refunded or held for reconciliation if
its outcome is still unknown.
Prices and balances are shown in USD. API amounts include both a decimal
amount and an exact amount\_micro\_usd. The catalogue's
price is the buyer total for that operation; there is no extra fee to add to
the displayed quote.
## Which balance pays?
| Caller | Balance |
| - | - |
| Organisation API key | The organisation's main balance |
| Person in a workspace | That workspace's budget |
| Person outside a workspace | Their personal balance |
| Assistant connection | The balance of the person or workspace that approved it |
An API key also has its own per-request and monthly limits. An assistant
connection has a per-request and daily limit. A limit or balance refusal means
the purchase did not start. In the buyer API, HTTP 402 with
insufficient\_balance or spend\_limit\_exceeded asks you
to fund the balance or change the relevant limit.
For exact fields, see [Balance and usage](/api/billing),
[Ask](/api/ask), and [Runs](/api/runs).
# Quickstart
Source: https://docs.apiosk.com/overview/quickstart
Create a team key, inspect a source, and make a bounded call.
## 1. Create a team account
[Sign up in the app](https://app.apiosk.com/signup), choose a team account,
and confirm your email. This creates an organisation. An owner or admin can
open **Organisation → API keys**. Fund the organisation's main balance before
making a paid call; creating a key and browsing sources do not charge it.
## 2. Create an API key
Give the key a name, expiry, per-request limit, monthly limit and the
permissions it needs. Copy the secret when it appears; it is shown once.
Keep it on your server.
```bash theme={null}
export APIOSK_KEY="apk_org_live_…"
```
For this guide, enable sources:read,
sources:execute and billing:read. Add
ask:create and ask:execute to run questions
through Ask.
## 3. Check the key and browse
```bash theme={null}
curl https://gateway.apiosk.com/v2/balance \
-H "Authorization: Bearer $APIOSK_KEY"
curl -G https://gateway.apiosk.com/v2/sources \
-H "Authorization: Bearer $APIOSK_KEY" \
--data-urlencode "search=company registry"
```
The directory includes sources that cannot currently run. Choose a row with
available\_in\_v2: true, then inspect its executable operations,
exact inputs and current prices:
```bash theme={null}
curl https://gateway.apiosk.com/v2/sources/kvk-dutch-business-register \
-H "Authorization: Bearer $APIOSK_KEY"
```
## 4. Run one operation
Use an operation and input returned by the source detail. Set a unique
Idempotency-Key for this purchase:
```bash theme={null}
curl https://gateway.apiosk.com/v1/execute/kvk-dutch-business-register/company_registry.search \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Idempotency-Key: quickstart-1" \
-H "Content-Type: application/json" \
-d '{"company.name":"Mollie B.V."}'
```
A completed response includes data,
results\[].metadata, usage.cost,
usage.held and balance.remaining. If it
returns HTTP 202, read the saved run at GET /v2/runs/.
This is a paid operation; do not run the example simply to test a key.
## When you do not know the source
Ask for a free priced plan:
```bash theme={null}
curl https://gateway.apiosk.com/v2/ask \
-H "Authorization: Bearer $APIOSK_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Registered address and filed accounts for Mollie B.V."}'
```
If the response needs input or an entity selection, ask the person for the
missing detail and submit a clarified question. If a plan is ready, review
its total ceiling before calling POST /v2/asks//run.
See [Ask](/api/ask) and [Prices and balance](/overview/payment-model).
# Terminology
Source: https://docs.apiosk.com/overview/terminology
The terms used by the App, buyer API, and hosted MCP server.
## Source
A provider or source group in GET /v2/sources. A directory entry
can be discovery-only. available\_in\_v2 and
readiness show whether at least one operation is currently
executable.
## Service and operation
A provider may publish several services, each with several endpoints. A
currently executable endpoint appears as an operation in
GET /v2/sources/, with its input fields, capability
and price. Pulse Network is one provider group with nested services.
## Ask, plan, and run
An **Ask** is a question in a person's words. A **plan** shows source steps
and one total price ceiling before purchase. A **run** is the saved execution,
including results, charges, held funds and errors. Planning is free; a
plan's quote expires.
## Organisation and workspace
An **organisation** has members, a main balance and API keys. A **workspace**
is a team area with its own members and budget. Organisation API keys spend
the main balance; people and assistant connections can spend a workspace
budget.
## API key and connection
An **API key** (apk\_org\_live\_…) is a server credential with
permissions, expiry, a per-request limit and a monthly limit. A
**connection** is consent granted by a person to an assistant, with a
per-request and daily limit.
## Micro-USD
One millionth of a US dollar. API money objects carry a decimal
amount and an exact integer string
amount\_micro\_usd.