Drillr provides market data, SEC filings, and AI-generated analysis for informational purposes only. Third-party data is not guaranteed accurate. See Disclaimer.
Drillr External API — Developer Guide#
Access Drillr's AI-powered financial research and data feeds through MCP, REST API, or CLI.
Table of Contents#
- Authentication
- MCP Tools
- REST API
- CLI Tool
- Pricing
- Rate Limits
- Platform Setup Examples
- For AI Coding Agents
- Error Handling
Authentication#
MCP: browser sign-in (recommended)#
Modern MCP clients can connect without an API key. Configure only the Streamable HTTP URL:
https://gateway.drillr.ai/mcp/data
On first connection the client opens Drillr in your browser. Sign in, review the client name, and approve access. Drillr issues that client its own revocable external credential; your browser session and the credential itself are never shown or copied into configuration.
OAuth credentials can call only the public /mcp/data surface. They use the same wallet, pricing, rate limits, usage reporting, and revoke controls as API keys. Manage authorized clients at https://drillr.ai/developer/keys.
REST and fallback clients: API key#
REST endpoints require an API key. API keys also remain supported for MCP clients that do not implement browser OAuth. Create one at https://drillr.ai/developer/keys; it is shown exactly once, so store it in a secret manager.
Pass the key with either header:
# Use either one, not both.
Authorization: Bearer drl_xxx
# Alternative header:
X-API-Key: drl_xxx
For agent-assisted setup, open https://drillr.ai/developer/agent and copy the setup prompt for your client into Codex or Claude Code. The install guide lives at https://drillr.ai/developer/mcp-install.md.
MCP Tools#
Connect to https://gateway.drillr.ai/mcp/data via MCP Streamable HTTP transport.
Eight data tools are exposed on this MCP server. Per-call pricing is listed in Pricing.
| Tool | Purpose |
|---|---|
run_sql | Read-only PostgreSQL SELECT over financial + alternative-data tables |
get_table_schema | Column metadata for a specific table (use before crafting run_sql) |
list_tables | Browse altdata categories + their tables/columns |
news_search | Semantic search over news, market events, and attributed claims, grouped into storylines |
sec_report_list | List SEC filings (10-K / 10-Q / 8-K / S-4 / JP EDINET) by company + date |
sec_report_search | Vector + keyword search inside SEC filing narrative |
company_search | NL company / asset discovery — finds tickers matching a thematic prompt (e.g. "AI infra plays") |
ticker_lookup | Resolve a company name / brand / ticker substring to canonical ticker(s) with history |
Five-market company discovery#
company_search covers US, Japan, Hong Kong, China A-shares, and Korea. Its
optional market argument accepts one lowercase value or a list drawn from
us, jp, hk, cn, and kr. Omit market or pass [] to search all five
markets; list order does not express priority.
{
"query": "Hong Kong and China EV battery suppliers",
"market": ["hk", "cn"]
}
The REST endpoint POST /api/v1/data/company_search uses the same request body.
Existing clients that send a single value such as "market": "jp" remain valid.
Synchronous one-shot search is available as REST
POST /api/v1/search— see REST API.
Typical MCP flow#
1. list_tables({ categories: ["Macro & Trade"] })
→ Discover available tables + their columns
2. get_table_schema({ table_name: "financial_statements" })
→ Column list before crafting a SQL query
3. run_sql({ sql: "SELECT ... FROM financial_statements WHERE ticker = 'AAPL' ..." })
→ Structured rows
4. sec_report_search({ ticker: "AAPL", query: "AI capex guidance" })
→ Relevant filing passages with citations
REST API#
Base URL: https://gateway.drillr.ai
All endpoints are rooted at /api/v1/ and require an API key.
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1/search | Synchronous research agent (NL question → answer) |
| POST | /api/v1/data/run_sql | REST mirror of MCP run_sql |
| GET | /api/v1/data/get_table_schema | REST mirror of MCP get_table_schema |
| GET | /api/v1/data/list_tables | REST mirror of MCP list_tables |
| POST | /api/v1/data/news_search | REST mirror of MCP news_search |
| GET | /api/v1/data/sec_report_list | REST mirror of MCP sec_report_list |
| POST | /api/v1/data/sec_report_search | REST mirror of MCP sec_report_search |
| POST | /api/v1/data/company_search | REST mirror of MCP company_search |
| POST | /api/v1/data/ticker_lookup | REST mirror of MCP ticker_lookup |
The /api/v1/data/* endpoints mirror the 9 MCP tools above 1:1 — same inputs, same outputs, same pricing. Use them when you'd rather call HTTP directly than wire up an MCP client.
The one shape difference: news_search over MCP returns Markdown (to fit the MCP host's token cap), while the REST endpoint returns the structured JSON envelope — storylines with their events, plus a parallel claims array.
Renamed and retired endpoints (2026-07-14)#
ticker_resolve→ticker_lookup. The MCP tool name changed immediately. The old REST pathPOST /api/v1/data/ticker_resolvestill works as a deprecated alias for one release — migrate now, it will be removed.signal_list→news_search. This one is a replacement, not an alias:GET /api/v1/data/signal_listand the MCPsignal_listtool are gone, not deprecated.news_searchcovers the same feed with semantic retrieval and storyline grouping, but the parameters differ (ticker/theme/query/since/untilinstead oftickers/sector/from_date/to_date), and there is nosectorfilter.
POST /api/v1/search#
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| question | string | Yes | - | The question |
| context | string | No | - | Additional context |
| session_id | string | No | - | Continue a previous session |
| stream | boolean | No | true | SSE streaming or JSON response |
Streaming example:
curl -X POST https://gateway.drillr.ai/api/v1/search \
-H "Authorization: Bearer drl_xxx" \
-H "X-Drillr-Via: github" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{"question": "What is NVDA PE ratio?"}'
SSE events:
| Event | Description |
|---|---|
status | Connection established, includes session_id |
tool_call | Agent is calling a data source (user-friendly label) |
text_delta | Incremental text content |
done | Complete or failed. Payload: { status, session_id, sources, duration_ms, _credits: { charged, method }, error? }. _credits.charged is the string "0.0" on status: 'failed' (failed calls aren't billed). |
Non-streaming JSON:
curl -X POST https://gateway.drillr.ai/api/v1/search \
-H "Authorization: Bearer drl_xxx" \
-H "X-Drillr-Via: github" \
-H "Content-Type: application/json" \
-d '{"question": "AAPL market cap?", "stream": false}'
{
"data": {
"text": "Apple's market cap is approximately $3.4 trillion...",
"session_id": "uuid",
"sources": [{ "tool": "Looking up company info (AAPL)", "ticker": "AAPL" }],
"duration_ms": 12500,
},
"_credits": {
"charged": "4.0",
"method": "usage_based",
},
}
/api/v1/search uses the same envelope as /api/v1/data/* — see the Response envelope section under Pricing for the full schema (success + error). _credits.balance_after is not returned on this endpoint; check the Usage page for the latest balance.
For per-tool input/output shapes of the /api/v1/data/* endpoints, the description fields on each MCP tool are the source of truth — call once with sample inputs to inspect the response.
CLI Tool#
A first-party drillr CLI is coming soon — it'll wrap the same authentication, search, and data tools available through MCP and REST. Until then, please use the MCP or REST channels above.
Pricing#
Drillr Data API calls are billed in credits (cr). Each billable call deducts credits from your account balance. You can view per-call deductions on the Usage page.
Pricing modes#
Fixed — run_sql / sec_report_list / sec_report_search / news_search charge a flat per-call rate (see the table below).
Usage-based — tools powered by an AI agent (the research agent, NL company discovery) are billed by actual work, so the per-call charge varies. Typical ranges are listed in the per-tool table below; responses surface the exact charge as _credits.charged and _credits.method: "usage_based".
Free — schema / navigation utilities are not billed.
Per-tool rates#
| Tool / Endpoint | Per call | Mode |
|---|---|---|
run_sql | 0.1 cr | Fixed |
sec_report_list | 0.1 cr | Fixed |
sec_report_search | 0.1 cr | Fixed |
news_search | 0.2 cr | Fixed |
company_search | typical 3–5 cr | Usage-based |
POST /api/v1/search | typical 2–5 cr | Usage-based |
get_table_schema | 0 cr | Free |
list_tables | 0 cr | Free |
ticker_lookup | 0 cr | Free |
Notes#
- Same tool, same price across surfaces. A
run_sqlcall costs the same via MCP (/mcp/data) or REST (/api/v1/data/run_sql), and the same applies to every other data tool. run_sqlrow cap by plan. Each query returns up to 100 rows on Free/Plus and up to 500 rows on Ultra/Enterprise. An explicit largerLIMITis clamped to the cap; when a result is capped the response carriestruncated: trueand anotice.- Failed calls are not billed. Errors before tool execution (auth, validation, permission 403) don't deduct credits. Errors during execution (upstream timeout, etc.) are also not billed.
- Balance + usage are surfaced on the Developer dashboard.
/api/v1/searchreturns402 Payment Requiredwhen your balance is too low. Keep your balance positive to avoid interrupted calls.
Response envelope#
All nine /api/v1/data/* endpoints use a uniform envelope so clients can write a single response parser and balance check across the surface.
Success (2xx):
{
"data": {
/* tool-specific payload — see each endpoint's schema in the OpenAPI spec */
},
"_credits": {
"charged": "0.1", // 1-decimal cr string
"method": "per_call", // per_call | usage_based | free
"balance_after": "1842.0", // remaining credit balance, 1-decimal cr string
},
}
_credits.chargedand_credits.balance_afterare 1-decimal credit strings (e.g."0.1","0.2","499.9"), not numbers — per-call data tools cost fractional credits. Parse withparseFloat()if you need a number.
_credits.charged— credits deducted for this call as a 1-decimal cr string;"0.0"for free tools_credits.method— billing mode:per_call— fixed per-request chargeusage_based— variable charge, scales with the work donefree— no charge
_credits.balance_after— your credit balance after this call, as a 1-decimal cr string. Best-effort — may be omitted. For the authoritative balance, check the Usage page.
Error (4xx / 5xx):
{
"error": {
"code": "invalid_request", // stable machine-readable
"message": "Missing required query param: ticker", // human-readable, not stable
"retry_after_seconds": 30, // present on 429 only
"limit": 8, // present on 429 concurrency-limit only
},
}
Known error.code values: invalid_request, unauthenticated, forbidden, rate_limited. New codes may be added — treat unknown codes as opaque and fall back to error.message for the human detail.
Rate Limits#
| Limit | Value |
|---|---|
| Request rate | 30 / minute |
Rate limits apply per OAuth credential or API key. 429 responses include retry_after_seconds. For balance-related failures see Pricing.
Platform Setup Examples#
Use browser OAuth whenever the client supports it. The MCP URL alone is enough; do not add an
Authorizationheader or copy a key into the config.
Claude Code#
claude mcp add --scope user --transport http drillr-data \
https://gateway.drillr.ai/mcp/data
From a human-operated terminal, run claude mcp login drillr-data and complete the browser flow. If
Drillr first shows a sign-in page, sign in and then review the client name and click Allow. Start
or restart Claude Code after login so the new user-scoped server is loaded into the conversation.
When a coding agent performs setup inside an already-open Claude Code conversation, its Bash tool has no terminal and that conversation does not hot-load a new user-scoped entry. The agent install contract uses a pseudo-terminal around the native login command, waits for its callback, and runs the free verification in a clean one-shot Claude Code process.
Codex CLI#
codex mcp add drillr-data --url https://gateway.drillr.ai/mcp/data
Current Codex versions may open the Drillr consent page and complete OAuth during add. If add
reports a successful login, do not run another login command. Only when it finishes without
authenticating, or when an existing entry needs authentication, run:
codex mcp login drillr-data
Claude Desktop#
{
"mcpServers": {
"drillr-data": {
"type": "http",
"url": "https://gateway.drillr.ai/mcp/data"
}
}
}
Restart Claude Desktop after saving the file, then approve Drillr in the browser when prompted.
API-key fallback: Hermes Agent#
Use this only when the installed Hermes/OpenClaw version does not support MCP OAuth. Create the key at https://drillr.ai/developer/keys and store it as a secret.
mcp_servers:
drillr-data:
url: 'https://gateway.drillr.ai/mcp/data'
headers:
Authorization: 'Bearer drl_xxx'
X-Drillr-Via: 'github'
timeout: 120
API-key fallback: OpenClaw#
{
"mcp": {
"servers": {
"drillr-data": {
"url": "https://gateway.drillr.ai/mcp/data",
"headers": {
"Authorization": "Bearer drl_xxx",
"X-Drillr-Via": "github"
}
}
}
}
}
When your Hermes/OpenClaw build adds MCP OAuth login, remove the entire headers block and use its login command instead. Never configure OAuth and a static bearer header on the same server entry.
For AI Coding Agents#
Setup is one command per client, followed by a browser sign-in the user performs. The commands, the authorization step for each client, and troubleshooting are in the install guide at https://drillr.ai/developer/mcp-install.md.
Both Codex and Claude Code load MCP tools when a session starts, so a server added mid-session is absent from that session's tool list. That is expected: start a new session rather than reaching the server another way.
The copy-and-paste setup prompts are at https://drillr.ai/developer/agent.
Error Handling#
| HTTP Status | Meaning |
|---|---|
| 400 | Missing required parameter / malformed input |
| 401 | Invalid or missing credentials |
| 402 | Insufficient credits |
| 403 | Credential doesn't have access to this endpoint |
| 404 | Resource not found or inaccessible |
| 429 | Rate limit exceeded (see retry_after_seconds) |
| 502 | Upstream data source unavailable |
Error-code strings in the response body:
| Code | Meaning |
|---|---|
unauthenticated | No credentials provided |
key_invalid | API key not recognized |
key_revoked | API key was revoked (see revoked_at) |
key_expired | API key has passed its expiry |
insufficient_credits | Balance can't cover this call |
invalid_query | Query parameter validation failed |
invalid_body | Request body validation failed |
invalid_id | Malformed UUID or similar |
not_found | Resource not found or inaccessible |
upstream_error | Database or data-source call failed |