# Discover and run tools

Browse Tools or search with POST /apis/v1/discover. Use public IDs such as exa/contents; do not use internal provider namespaces. Discovery and inspection are free.

```sh
curl https://keepbal.com/apis/v1/discover \
  -H "Authorization: Bearer $KEEPBAL_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"query":"exa"}'
```

Example discovery result (excerpt). Carry publicId unchanged through inspect and run:

```json
{
  "data": [
    {
      "publicId": "exa/contents",
      "path": "exa/contents"
    }
  ]
}
```

Inspect returns pricing metadata and known input fields; it does not calculate an input-specific quote. Fixed tools show the per-call price. Variable tools are billed at provider price + 35%.

```sh
curl https://keepbal.com/apis/v1/inspect \
  -H "Authorization: Bearer $KEEPBAL_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"publicId":"exa/contents"}'
```

Run the same publicId with input.body, input.queryParams, and input.pathParams. Supply the fields required by the selected tool; unused buckets can be empty.

```sh
curl https://keepbal.com/apis/v1/run \
  -H "Authorization: Bearer $KEEPBAL_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"publicId":"exa/contents","input":{"body":{"urls":["https://example.com"],"text":true},"queryParams":{},"pathParams":{}},"max_cost_usd":"0.10"}'
```

Catalog tool spend caps: REST top-level max_cost_usd, MCP input.max_cost_usd, or the X-KeepBal-Max-Cost-USD header. Caps must cover the estimate and fit your available balance; they persist through async completion. Costs above the cap fail without charge. Some variable tools require a cap or quantity.

A direct public tool URL accepts the tool JSON body; it does not require a provider/endpoint/input envelope.

```sh
curl https://keepbal.com/apis/v1/exa/contents \
  -H "Authorization: Bearer $KEEPBAL_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"urls":["https://example.com"],"text":true}'
```

MCP uses search_tools, inspect_tool, run_tool and get_run. Inspect first; run_tool takes tool and input. For pending results use get_run with run_id instead of starting another execution.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "run_tool",
    "arguments": {
      "tool": "exa/contents",
      "input": {
        "body": {
          "urls": [
            "https://example.com"
          ],
          "text": true
        },
        "queryParams": {},
        "pathParams": {},
        "max_cost_usd": "0.10"
      }
    }
  }
}
```

REST may return downloads or streams when the selected tool supports them; check Content-Type and the tool schema. MCP JSON results can be truncated and unsupported downloads include a do-not-retry notice. Use the documented REST result route when needed.

[Exa contents](/tools/exa/contents) · [Search and extraction](/tools/category/search-and-extraction) · [MCP reference](/docs/mcp)

[Docs](/docs)

[Quickstart](/docs/quickstart) · [Authentication](/docs/authentication) · [Billing](/docs/billing) · [Tools](/docs/tools) · [Models](/docs/models) · [MCP](/docs/mcp) · [Errors](/docs/errors) · [Rate limits and budgets](/docs/rate-limits-and-budgets)

[Previous: Billing](/docs/billing) · [Next: Models](/docs/models)
