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#

Create and manage API keys yourself at the Developer Portal: https://drillr.ai/developer/keys. Keys follow the format drl_xxxxxxxx_xxx... (45 characters) and are shown exactly once at creation — store them in your secret manager immediately.

Two ways to pass the key (both permanently supported):

# Recommended
Authorization: Bearer drl_xxx

# Also supported
X-API-Key: drl_xxx

API key is the recommended way to connect. If you have an AI coding agent (Claude Code, Cursor, etc.), just say:

Please configure the Drillr MCP per https://drillr.ai/developer/docs and save the setup rules to memory.

Your agent will follow the For AI Coding Agents recipe below — one-shot config plus persistent rules so the next session keeps the API-key approach. Otherwise, paste the Claude Code config snippet into your client and replace the placeholder with the key you generated on the Developer Portal.


MCP Tools#

Connect to https://gateway.drillr.ai/mcp/data via MCP Streamable HTTP transport.

Nine data tools are exposed on this MCP server. Per-call pricing is listed in Pricing.

ToolPurpose
run_sqlRead-only PostgreSQL SELECT over financial + alternative-data tables
get_table_schemaColumn metadata for a specific table (use before crafting run_sql)
fiscal_utilityConvert calendar dates ↔ fiscal periods for a ticker
list_tablesBrowse altdata categories + their tables/columns
signal_listHigh-score news / market-event feed
sec_report_listList SEC filings (10-K / 10-Q / 8-K / S-4 / JP EDINET) by company + date
sec_report_searchVector + keyword search inside SEC filing narrative
company_searchNL company / asset discovery — finds tickers matching a thematic prompt (e.g. "AI infra plays")
ticker_resolveResolve a company name / brand / ticker substring to canonical ticker(s) with history

Synchronous one-shot search is available as REST POST /api/v1/search — see REST API.

Typical MCP flow#

1. list_tables({ categories: ["macro_indicators"] })
   → Discover available tables + their columns

2. get_table_schema({ table: "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.

MethodPathPurpose
POST/api/v1/searchSynchronous research agent (NL question → answer)
POST/api/v1/data/run_sqlREST mirror of MCP run_sql
GET/api/v1/data/get_table_schemaREST mirror of MCP get_table_schema
GET/api/v1/data/fiscal_utilityREST mirror of MCP fiscal_utility
GET/api/v1/data/list_tablesREST mirror of MCP list_tables
GET/api/v1/data/signal_listREST mirror of MCP signal_list
GET/api/v1/data/sec_report_listREST mirror of MCP sec_report_list
POST/api/v1/data/sec_report_searchREST mirror of MCP sec_report_search
POST/api/v1/data/company_searchREST mirror of MCP company_search
POST/api/v1/data/ticker_resolveREST mirror of MCP ticker_resolve

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.

POST /api/v1/search#

ParameterTypeRequiredDefaultDescription
questionstringYes-The question
contextstringNo-Additional context
session_idstringNo-Continue a previous session
streambooleanNotrueSSE streaming or JSON response

Streaming example:

curl -X POST https://gateway.drillr.ai/api/v1/search \
  -H "Authorization: Bearer drl_xxx" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"question": "What is NVDA PE ratio?"}'

SSE events:

EventDescription
statusConnection established, includes session_id
tool_callAgent is calling a data source (user-friendly label)
text_deltaIncremental text content
doneComplete or failed. Payload: { status, session_id, sources, duration_ms, _credits: { charged, method }, error? }. _credits.charged is 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 "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,
    "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#

Fixedrun_sql / sec_report_list / sec_report_search / signal_list 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 / EndpointPer callMode
run_sql1 crFixed
sec_report_list1 crFixed
sec_report_search1 crFixed
signal_list2 crFixed
company_searchtypical 3–5 crUsage-based
POST /api/v1/searchtypical 2–5 crUsage-based
get_table_schema0 crFree
fiscal_utility0 crFree
list_tables0 crFree
ticker_resolve0 crFree

Notes#

  • Same tool, same price across surfaces. A run_sql call costs the same via MCP (/mcp/data) or REST (/api/v1/data/run_sql), and the same applies to every other data tool.
  • 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/search returns 402 Payment Required when 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": 5,
    "method": "per_call", // per_call | usage_based | free
    "balance_after": 1842, // remaining credit balance
  },
}
  • _credits.charged — credits deducted for this call; 0 for free tools
  • _credits.method — billing mode:
    • per_call — fixed per-request charge
    • usage_based — variable charge, scales with the work done
    • free — no charge
  • _credits.balance_after — your credit balance after this call. 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#

LimitValue
Request rate30 / minute

Rate limits apply per API key. 429 responses include retry_after_seconds. For balance-related failures see Pricing.


Platform Setup Examples#

Use the API key method below. It's the simplest path for every user. If you're not a developer, send the snippet to your agent (e.g. Claude Code) and follow its prompts; paste in the key you generated on the Developer Portal when asked.

Claude Code#

{
  "mcpServers": {
    "drillr": {
      "type": "http",
      "url": "https://gateway.drillr.ai/mcp/data",
      "headers": { "Authorization": "Bearer ${DRILLR_API_KEY}" }
    }
  }
}

Hermes Agent#

mcp_servers:
  drillr:
    url: 'https://gateway.drillr.ai/mcp/data'
    headers:
      Authorization: 'Bearer drl_xxx'
    timeout: 120

OpenClaw#

{
  "mcp": {
    "servers": {
      "drillr": {
        "url": "https://gateway.drillr.ai/mcp/data",
        "headers": { "Authorization": "Bearer drl_xxx" }
      }
    }
  }
}

Advanced: browser-based sign-in#

If you prefer not to manage an API key, MCP clients that support OAuth can sign in via Google in the browser instead — just omit the headers block from the snippets above and your client will prompt for sign-in on first connection.


For AI Coding Agents#

If you are an AI coding agent (Claude Code, Cursor, etc.) configuring Drillr for a user, follow these steps in order. The order matters: memory must be in place before the client restart so the rules survive into the next session.

1. Save the auth rules to your memory first#

Drillr's MCP server at gateway.drillr.ai/mcp/data accepts either an Authorization: Bearer <key> header or an OAuth flow — never both on the same connection. Once a user has chosen the API-key path, OAuth is not the right fix for any error. Record this so a future session (after the restart in step 3) does not relapse to OAuth on a transient failure.

If your runtime supports persistent memory (e.g. Claude Code's auto-memory under ~/.claude/projects/<project>/memory/), write two entries:

  • drillr-mcp-auth (type: reference) — "Drillr MCP https://gateway.drillr.ai/mcp/data uses static API key auth via Authorization: Bearer <key>. Do not attempt OAuth on this endpoint when a Bearer header is configured. Docs: https://drillr.ai/developer/docs. Key management: https://drillr.ai/developer/keys."
  • drillr-mcp-troubleshooting (type: feedback) — "When drillr MCP calls fail, never suggest OAuth re-authorization. Diagnose in order: (1) claude mcp list shows the server connected, (2) inspect the client's MCP config to confirm the Authorization header is present and non-empty, (3) curl -H 'Authorization: Bearer <key>' https://gateway.drillr.ai/api/v1/data/list_tables returns 200, (4) regenerate the key at https://drillr.ai/developer/keys if rejected."

If your runtime has no memory system, surface these rules to the user as setup notes they can paste back into a future session.

2. Configure the MCP server#

Ask the user for their API key (or have them generate one at https://drillr.ai/developer/keys), then run:

claude mcp add --scope user --transport http drillr \
  https://gateway.drillr.ai/mcp/data \
  --header "Authorization: Bearer <paste the user's key here>"

Substitute the literal key into the command. Do not store ${DRILLR_API_KEY} as a literal string in the header — it will not be interpolated at request time.

3. Ask the user to restart their client#

MCP servers only attach at client startup. Tell the user:

Please fully quit and reopen your MCP client (e.g. Claude Code). After restart, the drillr server's tools will be available.

4. After restart, verify#

In the new session, the memory entries from step 1 will keep you on the API-key path. Confirm the connection with a free smoke test:

list_tables({ categories: ["macro_indicators"] })

A successful response means the connection is healthy. A 401 means the key is wrong — regenerate at https://drillr.ai/developer/keys. Do not retry with OAuth.


Error Handling#

HTTP StatusMeaning
400Missing required parameter / malformed input
401Invalid or missing credentials
402Insufficient credits
403API key doesn't have access to this endpoint
404Resource not found or inaccessible
429Rate limit exceeded (see retry_after_seconds)
502Upstream data source unavailable

Error-code strings in the response body:

CodeMeaning
unauthenticatedNo credentials provided
key_invalidAPI key not recognized
key_revokedAPI key was revoked (see revoked_at)
key_expiredAPI key has passed its expiry
insufficient_creditsBalance can't cover this call
invalid_queryQuery parameter validation failed
invalid_bodyRequest body validation failed
invalid_idMalformed UUID or similar
not_foundResource not found or inaccessible
upstream_errorDatabase or data-source call failed