# StackResolve documentation > Web intelligence and resolution for AI agents. > Full docs in reading order. Get a free key at https://stackresolve.dev/developers. ======================================================================== # Quickstart Source: https://stackresolve.dev/docs > Software intelligence and resolution for AI agents. Discover and resolve which software to use, and get structured company research in one call. StackResolve is software intelligence and resolution for AI agents. It does two things. First, it helps an agent discover, evaluate, compare, and resolve which software to use. The [AgentReady Score](/methodology) rates how ready a tool is for agents, the [registry](/registry) lists scored tools, and `find_tools_for_task` returns ranked candidates for a job. See [Find tools](/find-tools), [Audit](/audit), and [Registry](/registry). Second, it compresses expensive web research into simple, structured API calls. Instead of running your own search, crawl, read, extract, and normalize loop for every question, you call one primitive and get a typed, cited, freshness-aware answer. Results are cached and refreshed per field, so repeat calls are fast and cheap. ## One API, one MCP, one CLI family | Surface | Base | Auth | | --- | --- | --- | | REST | `https://api.stackresolve.dev` | `x-api-key` header | | MCP (hosted) | `https://mcp.stackresolve.dev/mcp` | `x-api-key` header | | CLI | `stackresolve` | `STACKRESOLVE_API_KEY` | ## Primitives and tools | Call | Returns | | --- | --- | | `find_tools_for_task(task)` | Ranked tools for a job, filtered by capability | | `search_tools(query, requirements)` | Capability-filtered tool discovery | | `audit(domain)` | AgentReady Score and the four pillar sub-scores | | `compare_products(slugs)` | Structured side-by-side of registry products | | `get_company(domain)` | Description, products, categories, funding, technology, news | | `get_pricing(domain)` | Normalized tiers, free tier, self-serve | | `find_competitors(domain)` | Real competing companies | | `compare_companies(domains)` | Structured side-by-side of companies | | `research_company(domain, question)` | A grounded, cited answer | ## Your first call The company primitive needs a key or falls under the small anonymous trial. Get a free key at [app.stackresolve.dev](https://app.stackresolve.dev), then set it in your shell: ```bash export STACKRESOLVE_API_KEY=sk_live_... ``` ```bash REST curl "https://api.stackresolve.dev/v1/company?domain=resend.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```bash CLI stackresolve company resend.com ``` ```json Response (trimmed) { "name": "Resend", "domain": "resend.com", "description": "Email platform for developers to deliver transactional and marketing emails at scale.", "products": ["Email API", "Transactional emails", "Marketing campaigns/Broadcasts", "Webhooks"], "categories": ["Email service", "Developer tools", "SaaS", "API"], "technology": ["Node.js", "Next.js", "Python", "Ruby", "Go", "REST API", "MCP (Model Context Protocol)"], "recent_news": { "mcp_server_launch": "Resend launched an MCP server for agentic email automation." }, "freshness": { "description": { "observedAt": "2026-08-20T08:02:33.979Z", "stale": false } }, "cached": false } ``` Every value carries a source and an `observedAt` timestamp, so you can tell fresh facts from stale ones. See [Freshness](/reference/freshness) and [Sources](/reference/sources). ## Use it from anywhere - [REST](/rest) for any language. - [MCP](/mcp) to call it as a tool from an agent. - [CLI](/cli) for scripts and the terminal. - Editors: [Claude Code](/editors/claude-code), [Codex](/editors/codex), [Cursor](/editors/cursor). Free to start. Anonymous calls to the metered endpoints have a small hourly limit; an API key raises it and unlocks the account and billing endpoints. See [Authentication](/authentication) and [Rate Limits](/reference/rate-limits). ======================================================================== # Authentication Source: https://stackresolve.dev/docs/authentication > API keys, the x-api-key header, and how keyed and anonymous calls differ. StackResolve uses one credential everywhere: a StackResolve API key tied to a workspace. The same key works for the [REST API](/rest), the hosted [MCP server](/mcp), and the [CLI](/cli). ## Get a key Create a key in two ways. - Dashboard: sign in at [app.stackresolve.dev](https://app.stackresolve.dev) and create a key. The key is shown once. Save it. - CLI: `npx stackresolve keys create "my agent"` mints a key and a workspace and prints the key once. A key is shown only at creation time. Store it in a secret manager or an environment variable. If you lose it, create a new one and revoke the old one. ## Send your key ```bash REST curl "https://api.stackresolve.dev/v1/audit?domain=stripe.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```json MCP (header on POST /mcp) { "x-api-key": "sk_live_..." } ``` ```bash CLI (environment variable) export STACKRESOLVE_API_KEY=sk_live_... npx stackresolve audit stripe.com ``` The REST API and the hosted MCP both read the key from the `x-api-key` header. The CLI reads it from the `STACKRESOLVE_API_KEY` environment variable. The older `AGENTREADY_API_KEY` variable still works as a fallback in the CLI. ## What a key unlocks | Call type | Anonymous | Keyed | | --- | --- | --- | | Open reads: registry, profile, categories, search, compare, badge | Yes | Yes | | Metered primitives: audit, company, pricing, competitors, compare-companies, research, find-tools | Small IP trial (8 / hour) | Billed against your plan | | Account and billing: usage, entitlements, limits, billing, invoices | No | Yes | | Vendor claim: claim, claim/verify | No | Yes | | Hosted MCP (`POST /mcp`) | No | Yes (required) | The metered primitives run a billing entitlement check for keyed callers and record a usage event. See [Rate Limits](/reference/rate-limits) and [Billing & metering](/reference/billing). The hosted MCP server always requires a valid key. Every MCP tool call resolves a workspace from the `x-api-key` header first. A missing or invalid key returns a JSON-RPC error with code `-32001`. ## Workspaces A key belongs to one workspace. Usage, entitlements, limits, and invoices are all scoped to that workspace. Create separate keys for separate workspaces when you want separate usage and billing. Read your current workspace usage with `GET /v1/usage` or `npx stackresolve usage`. ## Revoke or rotate Rotate a key by creating a new one and updating your environment, then revoking the old one from the dashboard. Revoking a key takes effect immediately: calls with that key start returning `401`. ## Related - [REST reference](/rest) - [MCP](/mcp) - [Errors](/reference/errors) - [Billing & metering](/reference/billing) ======================================================================== # REST API Source: https://stackresolve.dev/docs/rest > The HTTP API. JSON in, JSON out, any language. Base URL: `https://api.stackresolve.dev`. Send your key in the `x-api-key` header. Reads are open. The money-spending primitives need a key or fall under a small anonymous trial limit ([Rate Limits](/reference/rate-limits)). Account and billing endpoints always need a key ([Authentication](/authentication)). All responses are JSON. Errors return `{ "error": "..." }` with an HTTP status ([Errors](/reference/errors)). ## Official SDKs A typed TypeScript client wraps the API. It is published on npm as `stackresolve`. ```bash npm i stackresolve ``` ```ts import { StackResolve } from 'stackresolve' const sr = new StackResolve({ apiKey: process.env.STACKRESOLVE_API_KEY }) const report = await sr.audit('stripe.com') console.log(report.scores.agentready, report.issues) const company = await sr.getCompany('vercel.com') ``` A Python client (`pip install stackresolve`) ships next. ## Descriptors Open, no key. Agents use these to discover the service. | Method | Path | What it returns | | --- | --- | --- | | GET | `/health` | `{ "ok": true }` | | GET | `/llms.txt` | Plain-text capability summary for agents | | GET | `/openapi.json` | OpenAPI 3.0 description of the `/v1` surface | | GET | `/badge/{slug}.svg` | Embeddable AgentReady badge (SVG) | ```bash curl https://api.stackresolve.dev/health # {"ok":true} ``` ## Discovery and readiness | Method | Path | Metered | Docs | | --- | --- | --- | --- | | GET | `/v1/audit?domain=` | Yes (`audit_run`) | [Audit](/audit) | | GET | `/v1/registry?category=&minScore=&limit=` | No | [Registry](/registry) | | GET | `/v1/profile/{slug}` | No | [Registry](/registry) | | GET | `/v1/categories` | No | [Categories](/categories) | | GET | `/v1/categories/{slug}` | No | [Categories](/categories) | | POST | `/v1/search` | No | [Find tools](/find-tools) | | POST | `/v1/find-tools` | Yes (`agent_discovery_check`) | [Find tools](/find-tools) | | POST | `/v1/compare` | No | [Registry](/registry) | ### GET /v1/audit The domain to score, for example `stripe.com`. A bare slug also works. ```bash curl "https://api.stackresolve.dev/v1/audit?domain=stripe.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```json Response (trimmed) { "slug": "stripe", "domain": "stripe.com", "name": "Stripe", "scores": { "agentready": 74, "discovery": 58, "understanding": 83, "adoption": 88, "operability": 67 }, "issues": ["No OpenAPI spec: publish one so agents can generate a client."], "signals": { "mcpAvailable": true, "cliAvailable": true, "llmsTxt": true, "openapi": false, "sdkLanguages": ["go", "typescript", "python"] } } ``` ### POST /v1/search Free-text query matched against name, slug, and company description or categories. Hard capability filters, all optional booleans: `api`, `mcp`, `self_serve`, `openapi`, `cli`. A product missing a required capability is dropped from results. ```bash curl https://api.stackresolve.dev/v1/search \ -H "content-type: application/json" \ -d '{"query": "payments", "requirements": {"api": true, "mcp": true}}' ``` ```json Response [ { "slug": "paddle", "name": "Paddle", "domain": "paddle.com", "agentready": 83 }, { "slug": "stripe", "name": "Stripe", "domain": "stripe.com", "agentready": 74 } ] ``` ### POST /v1/find-tools A plain-English task. One model call parses it into search terms plus requirements, then the registry is searched and ranked by AgentReady Score. ```bash curl https://api.stackresolve.dev/v1/find-tools \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"task": "send transactional email from an agent"}' ``` ```json Response { "task": "send transactional email from an agent", "intent": { "searchTerms": "send transactional email", "requirements": {} }, "results": [{ "slug": "resend", "name": "Resend", "domain": "resend.com", "agentready": 98 }] } ``` ### POST /v1/compare Two or more registry slugs to line up. Get slugs from the registry, search, or find-tools. ```bash curl https://api.stackresolve.dev/v1/compare \ -H "content-type: application/json" \ -d '{"slugs": ["stripe", "paddle"]}' ``` ```json Response (trimmed) { "fields": ["agentready", "discovery", "understanding", "adoption", "operability", "agent_capability.api", "agent_capability.mcp_available"], "rows": [ { "slug": "stripe", "name": "Stripe", "values": { "agentready": 74, "agent_capability.mcp_available": true } }, { "slug": "paddle", "name": "Paddle", "values": { "agentready": 83, "agent_capability.mcp_available": true } } ] } ``` ## Research primitives | Method | Path | Metered | Docs | | --- | --- | --- | --- | | GET | `/v1/company?domain=` | Yes (`workflow_execution`) | [get_company](/primitives/company) | | GET | `/v1/pricing?domain=` | Yes (`workflow_execution`) | [get_pricing](/primitives/pricing) | | GET | `/v1/competitors?domain=&limit=` | Yes (`workflow_execution`) | [find_competitors](/primitives/competitors) | | POST | `/v1/compare-companies` | Yes (`workflow_execution`) | [compare_companies](/primitives/compare) | | POST | `/v1/research` | Yes (`workflow_execution`) | [research_company](/primitives/research) | ```bash Company curl "https://api.stackresolve.dev/v1/company?domain=resend.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```bash Research curl https://api.stackresolve.dev/v1/research \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"domain": "resend.com", "question": "does it support batch sending?"}' ``` See each primitive page for full parameter tables and response shapes. ## Account and billing Every endpoint below needs a valid key. See [Billing & metering](/reference/billing) for the full parameter tables and response shapes. | Method | Path | What it does | | --- | --- | --- | | GET | `/v1/usage` | Usage this billing period, per meter | | GET | `/v1/entitlements` | Included, used, and remaining per event type | | GET | `/v1/usage/events` | Raw usage events, filterable | | GET | `/v1/limits` | Your spend and usage limits | | PATCH | `/v1/limits` | Set budget, warning, and hard limits | | GET | `/v1/billing` | Plan, spend, and estimated upcoming charge | | POST | `/v1/billing/checkout` | Start a Stripe checkout to enable metered billing | | POST | `/v1/billing/portal` | Open the Stripe customer portal | | GET | `/v1/billing/invoices` | List invoices | ## Vendor claim | Method | Path | What it does | | --- | --- | --- | | POST | `/v1/claim` | Start a domain claim (DNS TXT or meta tag) | | POST | `/v1/claim/verify` | Verify a pending claim | ```bash curl https://api.stackresolve.dev/v1/claim \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"slug": "stripe", "email": "owner@stripe.com", "method": "dns"}' ``` ```json Response { "claimId": "b1c2...", "token": "agentready-verify=9f8e...", "instructions": "Add a DNS TXT record on stripe.com: \"agentready-verify=9f8e...\", then verify." } ``` Add the DNS TXT record (or homepage meta tag), then call `POST /v1/claim/verify` with `{ "slug": "stripe" }`. A verified claim turns registry links from nofollow into canonical followed links. ## Conventions - Every fact carries provenance and a timestamp ([Sources](/reference/sources), [Freshness](/reference/freshness)). - `cached: true` on a research response means the answer came from stored facts, not a fresh crawl ([Caching](/reference/caching)). - Pass an `idempotency-key` header on a metered request to make retries safe; a repeat with the same key is not double-billed. ======================================================================== # MCP Source: https://stackresolve.dev/docs/mcp > Call StackResolve as a tool from any MCP client, hosted or stdio. StackResolve runs one hosted MCP server. It serves both toolsets, discovery plus research, from a single endpoint. There is no separate server to add per product. - Endpoint: `https://mcp.stackresolve.dev/mcp` - Transport: streamable HTTP, stateless. Send a JSON-RPC request with `POST /mcp`. - Auth: send your key in the `x-api-key` header. The hosted server requires a valid key for every call. The hosted MCP always needs a key. A missing or invalid key returns a JSON-RPC error with code `-32001` and message "a valid StackResolve API key is required (x-api-key header)". Get a key at [app.stackresolve.dev](https://app.stackresolve.dev). ## Add the server The fastest path is the Claude Code CLI: ```bash claude mcp add --transport http stackresolve https://mcp.stackresolve.dev/mcp ``` For other clients, point them at `https://mcp.stackresolve.dev/mcp` and set the `x-api-key` header. See the editor guides for [Claude Code](/editors/claude-code), [Codex](/editors/codex), and [Cursor](/editors/cursor). ## Tools Ten tools. The cheap reads run on any valid key. The expensive tools (`audit`, `get_company`, `get_pricing`, `research_company`, `find_tools_for_task`) run a billing entitlement check and record a usage event for your workspace. | Tool | Input | Metered | Docs | | --- | --- | --- | --- | | `find_tools_for_task` | `{ task: string }` | `agent_discovery_check` | [Find tools](/find-tools) | | `search_tools` | `{ query: string, api?, mcp?, self_serve?, openapi?, cli? }` | No | [Find tools](/find-tools) | | `compare_products` | `{ slugs: string[] }` | No | [Registry](/registry) | | `get_profile` | `{ slug: string }` | No | [Registry](/registry) | | `list_registry` | `{ category?: string, minScore?: number, limit?: number }` | No | [Registry](/registry) | | `audit` | `{ domain: string }` | `audit_run` | [Audit](/audit) | | `get_company` | `{ domain: string }` | `workflow_execution` | [Company](/primitives/company) | | `get_pricing` | `{ domain: string }` | `workflow_execution` | [Pricing](/primitives/pricing) | | `research_company` | `{ domain: string, question?: string }` | `workflow_execution` | [Research](/primitives/research) | | `get_usage` | `{}` | No | [Billing & metering](/reference/billing) | `search_tools` takes the capability filters as flat booleans on the input, not as a nested `requirements` object. The REST `/v1/search` endpoint nests them under `requirements`. Same filters, different shape. The competitor and company-comparison primitives (`find_competitors`, `compare_companies`) are available over [REST](/rest) and the [CLI](/cli), not as MCP tools. ## Example call A raw JSON-RPC `tools/call` over the hosted transport: ```bash curl https://mcp.stackresolve.dev/mcp \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -H "accept: application/json, text/event-stream" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "find_tools_for_task", "arguments": { "task": "send transactional email" } } }' ``` The tool result comes back as a text content block holding the JSON response: ```json { "content": [ { "type": "text", "text": "{ \"task\": \"send transactional email\", \"results\": [ { \"slug\": \"resend\", \"name\": \"Resend\", \"agentready\": 98 } ] }" } ] } ``` In practice you never build this by hand. Your MCP client (Claude Code, Codex, Cursor) handles the JSON-RPC and shows the tools to the agent. ## Local stdio Prefer to run a server on your own machine, for example to point at a local API during development? The CLI packages ship the same engine functions. Wrap them in a small stdio MCP server, or just use the [CLI](/cli) directly. For most agents the hosted server is the right default: it is one line to add and always current. One server serves every tool. Let the agent first pick a tool with `find_tools_for_task`, then dig into a vendor with `research_company`, without adding a second server. ======================================================================== # CLI Source: https://stackresolve.dev/docs/cli > StackResolve from the terminal and scripts. Two binaries over one platform. StackResolve ships two CLIs. Both read the same fact database and bill against the same workspace. - `stackresolve` (binary `stackresolve`): discovery, readiness, and your account. - The same `stackresolve` binary also runs the research primitives (company, pricing, research). ## Install ```bash npm i -g stackresolve ``` Or run without installing: ```bash npx stackresolve audit stripe.com stackresolve company stripe.com ``` Set your key for higher limits and account access: ```bash export STACKRESOLVE_API_KEY=sk_live_... ``` The older `AGENTREADY_API_KEY` variable still works as a fallback. Runs are billed to the workspace behind your key. Without a key, discovery and research still run locally, but account commands need a key. ## stackresolve: discovery and readiness ```bash stackresolve [args] [--json] ``` | Command | What it does | Metered | | --- | --- | --- | | `find ` | Rank tools for a natural-language task | `agent_discovery_check` | | `search ` | Search the registry | No | | `audit ` | Score a product for agent-readiness (0-100) | `audit_run` | | `profile ` | Full registry profile (scores, capabilities, sources) | No | | `compare ...` | Structured side-by-side of products | No | | `registry` | List the registry, highest score first | No | | `keys create [label]` | Mint an API key and workspace (shown once) | No | | `usage` | Your usage this billing period | No | | `entitlements` | Per-meter included, used, remaining | No | | `limits` | Your spend and usage limits | No | | `billing` | Plan, spend, estimated charges | No | The account commands (`usage`, `entitlements`, `limits`, `billing`) need `STACKRESOLVE_API_KEY` set. ```bash Examples stackresolve find "scrape JavaScript sites from Claude Code" stackresolve audit firecrawl.dev stackresolve compare firecrawl exa --json stackresolve keys create "my agent" ``` `audit` prints a readable score card by default: ```text AgentReady: 74/100 Stripe (stripe.com) Discoverability ██████░░░░ 58 Understandability ████████░░ 83 Adoptability █████████░ 88 Operability ███████░░░ 67 llms.txt yes openapi no api yes mcp yes cli yes sdks go/typescript/python gh:stripe ``` Add `--json` to any command for raw JSON you can pipe into `jq`. ## companydata: research primitives ```bash companydata [args] [--json] ``` | Command | What it does | | --- | --- | | `company ` | Normalized company record with per-field freshness | | `pricing ` | Normalized pricing (tiers, free_tier, self_serve) | | `competitors ` | Real competing companies, not listicles | | `compare ...` | Structured side-by-side of companies | | `research [question]` | Grounded, cited answer to a question | ```bash Examples companydata company stripe.com companydata pricing vercel.com companydata competitors firecrawl.dev companydata compare stripe.com adyen.com checkout.com companydata research anthropic.com "what models does it offer?" ``` Output is JSON, so pipe it into `jq` or your own tooling. ## Exit codes | Code | Meaning | | --- | --- | | `0` | Success | | `1` | Error (bad arguments, network, or engine failure) | | `2` | Usage or billing blocked (the `stackresolve` CLI, when a plan limit is reached) | ## Related - [Authentication](/authentication) - [REST API](/rest) - [Billing & metering](/reference/billing) ======================================================================== # Claude Code Source: https://stackresolve.dev/docs/editors/claude-code > Add StackResolve to Claude Code as an MCP server. Claude Code talks to StackResolve over the hosted MCP server. One command adds every tool. ## Add the server ```bash claude mcp add --transport http stackresolve https://mcp.stackresolve.dev/mcp ``` Add `--scope user` to make it available in every project, or `--scope project` to write it into the repo's `.mcp.json` so your team shares it: ```bash claude mcp add --transport http --scope user stackresolve https://mcp.stackresolve.dev/mcp ``` ## Set your key The hosted MCP requires a valid key in the `x-api-key` header. Pass it as a header when you add the server: ```bash claude mcp add --transport http stackresolve https://mcp.stackresolve.dev/mcp \ --header "x-api-key: $STACKRESOLVE_API_KEY" ``` Get a free key at [app.stackresolve.dev](https://app.stackresolve.dev). See [Authentication](/authentication). ## Verify ```bash claude mcp list ``` You should see `stackresolve` connected. Inside Claude Code, run `/mcp` to inspect the tools. ## Use it Ask Claude in plain language and it calls the right tool: - "Find tools for sending transactional email from an agent." (`find_tools_for_task`) - "Audit stripe.com for agent-readiness." (`audit`) - "Research resend.com and tell me if it supports batch sending." (`research_company`) - "Compare stripe and paddle." (`compare_products`) One server serves both toolsets. Claude can first pick the right tool with `find_tools_for_task`, then research the vendor with `research_company`, without adding a second server. ## Remove it ```bash claude mcp remove stackresolve ``` See [MCP](/mcp) for the full tool list and [Rate Limits](/reference/rate-limits) for the keyed and anonymous limits. ======================================================================== # Codex Source: https://stackresolve.dev/docs/editors/codex > Add StackResolve to Codex as an MCP server. Point Codex at the hosted StackResolve endpoint. It is one server for every tool. ## Configure Add StackResolve to your Codex MCP configuration (`~/.codex/config.toml`): ```toml [mcp_servers.stackresolve] url = "https://mcp.stackresolve.dev/mcp" [mcp_servers.stackresolve.headers] x-api-key = "sk_live_..." ``` If your Codex version uses JSON config, the equivalent is: ```json { "mcpServers": { "stackresolve": { "url": "https://mcp.stackresolve.dev/mcp", "headers": { "x-api-key": "sk_live_..." } } } } ``` ## Set your key The hosted MCP requires a valid key in the `x-api-key` header. Get one at [app.stackresolve.dev](https://app.stackresolve.dev). See [Authentication](/authentication). ## Use it Once connected, every StackResolve tool is available to the agent: - Discovery and readiness: `find_tools_for_task`, `search_tools`, `compare_products`, `get_profile`, `list_registry`, `audit`. - Research: `get_company`, `get_pricing`, `research_company`, `get_usage`. Ask Codex to find a tool for a task, audit a vendor, or research and compare companies, and it calls the tools directly with cited, structured results instead of raw search output. See [MCP](/mcp) for the full tool signatures and [Rate Limits](/reference/rate-limits) for the keyed and anonymous limits. ======================================================================== # Cursor Source: https://stackresolve.dev/docs/editors/cursor > Add StackResolve to Cursor as an MCP server. Add StackResolve to Cursor and every tool appears in the agent's tool list. ## Configure Add StackResolve to `~/.cursor/mcp.json` (global) or the project `.cursor/mcp.json`: ```json { "mcpServers": { "stackresolve": { "url": "https://mcp.stackresolve.dev/mcp", "headers": { "x-api-key": "sk_live_..." } } } } ``` Reload Cursor. Open Settings, then MCP, and confirm `stackresolve` shows as connected. ## Set your key The hosted MCP requires a valid key in the `x-api-key` header. Get one at [app.stackresolve.dev](https://app.stackresolve.dev). See [Authentication](/authentication). ## Use it Every StackResolve tool appears in the agent's tool list: the discovery tools (`find_tools_for_task`, `search_tools`, `compare_products`, `get_profile`, `list_registry`, `audit`) and the research tools (`get_company`, `get_pricing`, `research_company`, `get_usage`). Ask the agent to find a tool for a task, audit a vendor, or research and compare companies, and it calls the tools directly with cited, structured results instead of raw search output. Keep your key out of a shared repo. For a project-scoped `.cursor/mcp.json` that you commit, reference an environment variable rather than pasting the literal key. See [MCP](/mcp) for the full tool signatures and [Rate Limits](/reference/rate-limits) for the keyed and anonymous limits. ======================================================================== # Audit Source: https://stackresolve.dev/docs/audit > The AgentReady Score for a tool, with four pillar sub-scores and the fixes. `audit` rates how ready a tool is for AI agents. It returns the AgentReady Score, a single number from 0 to 100, plus a sub-score for each of the four pillars, the facts behind the score, the raw discovery signals, and a ranked list of fixes. Use `audit` to check one tool you already have in mind. Use [find_tools_for_task](/find-tools) when you want ranked candidates for a job. For how the number is computed, see [Methodology](/methodology). ## The four pillars | Pillar | Score key | What it measures | | --- | --- | --- | | DISCOVER | `discovery` | Can an agent find the tool and know what it does? | | UNDERSTAND | `understanding` | Are the docs, schemas, and capabilities clear to an agent? | | ADOPT | `adoption` | Can an agent sign up, get a key, and install without a human? | | OPERATE | `operability` | Can an agent run it as a primitive: API, MCP, SDKs? | The headline `agentready` score is the average of the four pillar scores. ## Call it ```bash REST curl "https://api.stackresolve.dev/v1/audit?domain=stripe.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```text MCP audit({ domain: "stripe.com" }) ``` ```bash CLI stackresolve audit stripe.com ``` ## Parameters The domain to score, for example `stripe.com`. A bare slug also works; the audit derives the domain and slug from your input. ## Response ```json Response (trimmed) { "slug": "stripe", "domain": "stripe.com", "name": "Stripe", "scores": { "agentready": 74, "discovery": 58, "understanding": 83, "adoption": 88, "operability": 67 }, "facts": { "agent_capability.api": true, "agent_capability.mcp_available": true, "agent_capability.llms_txt": true, "agent_capability.sdks": ["go", "typescript", "ruby", "python", "php", "csharp", "java"], "pricing.self_serve": true, "pricing.free_tier": false }, "issues": [ "No OpenAPI spec: publish one so agents can generate a client.", "No AGENTS.md skill file: publish one so coding agents get install, config, and usage context.", "No markdown mirror: serve text/markdown so agents get clean content, not HTML." ], "refreshed": { "company": ["description", "products", "categories", "technology", "recent_news"], "agent_capability": ["api", "cli"] }, "signals": { "mcpAvailable": true, "cliAvailable": true, "apiLikely": true, "openapi": false, "llmsTxt": true, "sdkLanguages": ["go", "typescript", "ruby", "python", "php", "csharp", "java"], "npmPackages": ["stripe"], "pypiPackages": ["stripe"], "robotsAiAllowed": true, "sitemap": false, "agentsMd": false, "githubOrg": "stripe", "evidence": ["GitHub org: github.com/stripe", "An MCP server repository exists on GitHub.", "An llms.txt file is served."] } } ``` ## Response fields `agentready` plus the four pillar sub-scores (`discovery`, `understanding`, `adoption`, `operability`), each 0 to 100. See [Methodology](/methodology). A flat map of the scored facts, keyed `namespace.key`, for example `agent_capability.mcp_available`. These are the values the score is derived from. See [Schemas](/reference/schemas). The highest-value missing signals, ordered by impact. This is the fix list a vendor works through to raise the score. The deterministic discovery signals gathered from GitHub, npm, PyPI, `llms.txt`, and OpenAPI probes, plus an `evidence` array of human-readable notes. High-confidence facts that do not depend on marketing copy. Which fields were re-fetched on this run, grouped by namespace. An audit spends money: it crawls pages, searches, and runs extraction models. It is metered as one `audit_run` event. Keyed callers are billed against their plan; anonymous callers fall under the [trial limit](/reference/rate-limits). ## Related - [Methodology](/methodology): how the score is computed. - [Registry](/registry): browse tools already scored. - [Find tools](/find-tools): ranked candidates for a task. ======================================================================== # Methodology Source: https://stackresolve.dev/docs/methodology > How the AgentReady Score is computed. Four pillars, weighted signals, deterministic. The AgentReady Score measures how ready a product is for AI agents to discover, understand, adopt, and operate. It is deterministic. The score is derived from stored facts, not from a model's opinion, so the same facts always produce the same number and every point is traceable to a signal. ## The framework: DISCOVER, UNDERSTAND, ADOPT, OPERATE | Pillar | Score key | The agent question it answers | | --- | --- | --- | | DISCOVER | `discovery` | Can an agent find you and know you exist? | | UNDERSTAND | `understanding` | Can an agent tell what you do, your pricing, and when to use you? | | ADOPT | `adoption` | Can an agent sign up, get a key, and install without a human? | | OPERATE | `operability` | Can an agent actually use you as a primitive? | ## How the number is built Each pillar holds a set of weighted signals. A signal is either present or not. A pillar score is the sum of the weights of the present signals, divided by the total possible weight for that pillar, times 100. The headline `agentready` score is the average of the four pillar scores. Every score is rounded to a whole number. ```text pillar = round( sum(weights of present signals) / sum(all weights) * 100 ) agentready = round( (discovery + understanding + adoption + operability) / 4 ) ``` ## DISCOVER signals | Signal (`namespace.key`) | Weight | Present when | | --- | --- | --- | | `agent_capability.llms_txt` | 3 | An `/llms.txt` file is served | | `agent_capability.openapi` | 2 | An OpenAPI spec is served | | `agent_capability.api` | 2 | A public API is detected | | `company.categories` | 1 | Categories are populated | | `readability.robots_ai_allowed` | 1 | `robots.txt` does not block AI crawlers | | `readability.sitemap` | 1 | A `sitemap.xml` is served | | `readability.agents_md` | 2 | An `AGENTS.md`, `CLAUDE.md`, or `llms-full.txt` file is served | ## UNDERSTAND signals | Signal (`namespace.key`) | Weight | Present when | | --- | --- | --- | | `company.description` | 2 | A description is populated | | `pricing.pricing` or `pricing.free_tier` | 2 | Pricing or a free-tier flag is known | | `company.products` | 2 | Products are populated | | `company.categories` | 1 | Categories are populated | | `agent_capability.authentication` | 1 | An auth method is documented | | `readability.meta_description` | 1 | The homepage has a meta description | | `readability.json_ld` | 1 | The homepage has Schema.org JSON-LD | | `readability.canonical` | 1 | The homepage has a canonical link | | `readability.markdown_mirror` | 1 | A `text/markdown` mirror is served | ## ADOPT signals | Signal (`namespace.key`) | Weight | Present when | | --- | --- | --- | | `pricing.self_serve` | 3 | An agent can sign up and pay without a human | | `agent_capability.sdks` | 2 | Official SDKs are detected | | `agent_capability.cli` | 1 | A CLI is detected | | `agent_capability.api` | 1 | A public API is detected | | `agent_capability.openapi` | 1 | An OpenAPI spec is served | ## OPERATE signals | Signal (`namespace.key`) | Weight | Present when | | --- | --- | --- | | `agent_capability.mcp_available` | 3 | An MCP server exists | | `agent_capability.api` | 2 | A public API is detected | | `agent_capability.sdks` | 1 | Official SDKs are detected | | `agent_capability.claude_compatible` | 1 | Documented Claude Code compatibility | | `agent_capability.codex_compatible` | 1 | Documented Codex compatibility | | `agent_capability.cursor_compatible` | 1 | Documented Cursor compatibility | ## Where the signals come from The audit does not trust marketing copy for capability claims. The homepage rarely states whether a vendor has SDKs, a CLI, or an MCP server, so the audit looks where the truth lives and writes deterministic, high-confidence facts: - GitHub org repositories: an `*-mcp` repo means an MCP server exists, a `*-cli` repo means a CLI exists, SDK and client repos reveal SDK languages. - npm and PyPI: a published package confirms an SDK and its language. - Direct probes: `/llms.txt`, `/openapi.json`, `robots.txt`, `sitemap.xml`, and `AGENTS.md` on the apex and the `docs.` subdomain. - Homepage HTML: canonical link, meta description, JSON-LD, and a markdown mirror link. Hard evidence overrides the model. If the GitHub org has an MCP repo, `mcp_available` is set true regardless of what the copy says. Each fact carries a confidence and a timestamp. See [Sources](/reference/sources) and [Freshness](/reference/freshness). ## Reading a score A score in the 90s means an agent can find, understand, adopt, and operate the product with almost no human help. A score in the 50s usually means the product is usable by a developer but leaves gaps for an agent: no `llms.txt`, no MCP server, no OpenAPI spec, or no self-serve signup. The [audit](/audit) `issues` array lists the specific fixes, ordered by how much they would raise the score. ## Related - [Audit](/audit): score one product and get the fix list. - [Registry](/registry): browse products already scored. - [Schemas](/reference/schemas): the fact namespaces behind every signal. ======================================================================== # Registry Source: https://stackresolve.dev/docs/registry > Browse scored tools, read a full profile, compare products, and embed a badge. The registry lists tools that carry an [AgentReady Score](/methodology). Filter it by category and minimum score, read a full profile for any one tool, compare products side-by-side, or embed a badge on a vendor page. Registry reads are open and free. ## List the registry Returns scored tools as a JSON array, highest AgentReady Score first. ```bash REST curl "https://api.stackresolve.dev/v1/registry?category=payments&minScore=70&limit=10" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```text MCP list_registry({ category: "payments", minScore: 70, limit: 10 }) ``` ```bash CLI stackresolve registry ``` Filter to one category slug, for example `payments`. See [Categories](/categories). Only return products with an AgentReady Score at or above this value. Maximum rows to return. ```json Response [ { "slug": "cloudflare", "name": "Cloudflare", "domain": "cloudflare.com", "agentready": 98, "discovery": 100, "understanding": 92, "adoption": 100, "operability": 100 }, { "slug": "parallel", "name": "Parallel", "domain": "parallel.ai", "agentready": 98, "discovery": 100, "understanding": 92, "adoption": 100, "operability": 100 } ] ``` Each row carries the headline score and the four pillar sub-scores. ## Read a profile Returns the full profile for one tool by slug: the scores plus every current fact grouped by namespace, each with a confidence and a timestamp. ```bash REST curl "https://api.stackresolve.dev/v1/profile/stripe" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```text MCP get_profile({ slug: "stripe" }) ``` ```bash CLI stackresolve profile stripe ``` The product slug, for example `stripe`. ```json Response (trimmed) { "slug": "stripe", "name": "Stripe", "domain": "stripe.com", "scores": { "agentready": 74, "discovery": 58, "understanding": 83, "adoption": 88, "operability": 67 }, "facts": { "agent_capability": { "mcp_available": { "value": true, "confidence": 0.95, "observedAt": "2026-08-20T08:47:13.253Z", "stale": false }, "sdks": { "value": ["go", "typescript", "python"], "confidence": 0.92, "observedAt": "2026-08-20T08:47:13.253Z", "stale": false } }, "pricing": { "self_serve": { "value": true, "confidence": 0.9, "observedAt": "2026-08-20T08:47:12.972Z", "stale": false } } }, "claimed": false, "lastChecked": "2026-08-20T08:47:13.253Z" } ``` Every current fact, grouped by namespace then key. Each entry carries `value`, `confidence` (0 to 1), `observedAt`, and `stale`. See [Schemas](/reference/schemas) and [Sources](/reference/sources). Whether the vendor has verified ownership of the domain. See the claim flow in the [REST reference](/rest). The newest `observedAt` across all facts. ## Compare products Lines up two or more registry products across a fixed set of score and capability fields. ```bash REST curl https://api.stackresolve.dev/v1/compare \ -H "content-type: application/json" \ -d '{"slugs": ["stripe", "paddle"]}' ``` ```text MCP compare_products({ slugs: ["stripe", "paddle"] }) ``` ```bash CLI stackresolve compare stripe paddle ``` ```json Response (trimmed) { "fields": ["agentready", "discovery", "understanding", "adoption", "operability", "agent_capability.api", "agent_capability.mcp_available", "agent_capability.openapi", "agent_capability.cli", "agent_capability.llms_txt", "pricing.self_serve", "pricing.free_tier"], "rows": [ { "slug": "stripe", "name": "Stripe", "values": { "agentready": 74, "agent_capability.openapi": null, "pricing.free_tier": false } }, { "slug": "paddle", "name": "Paddle", "values": { "agentready": 83, "agent_capability.openapi": true, "pricing.free_tier": true } } ] } ``` A `null` value means the fact is unknown for that product, not false. ## Embed a badge Every profile has a badge you can put on a vendor page. It shows the current AgentReady Score and links back to the profile. The badge is open and cached for an hour. ```html AgentReady Score ``` The badge color follows the score: green at 80 and above, amber from 50 to 79, red below 50, and gray when the product has no score yet. Registry reads, profiles, comparisons, and badges are free and not metered. Only the [audit](/audit) and the [research primitives](/primitives/company) spend money. See [Rate Limits](/reference/rate-limits). ======================================================================== # Categories Source: https://stackresolve.dev/docs/categories > The category taxonomy behind the registry, and the tools in each one. Every registry product is filed under one or more categories. Each category names an agent task ("Charge customers, subscriptions, metering") so an agent can browse by the job it needs done, not by vendor marketing. Category reads are open and free. ## List categories Returns the full taxonomy with a product count per category. ```bash REST curl "https://api.stackresolve.dev/v1/categories" ``` ```text MCP list_registry({ category: "payments" }) ``` The MCP surface has no dedicated categories tool; use `list_registry` with a `category` filter, or the REST endpoints here. ```json Response (trimmed) { "categories": [ { "slug": "web-search", "name": "Web Search & Research", "agent_task": "Find current information on the web", "count": 4 }, { "slug": "ai-models", "name": "AI Models & Inference", "agent_task": "Generate and reason with LLMs and multimodal models", "count": 5 }, { "slug": "payments", "name": "Payments & Billing", "agent_task": "Charge customers, subscriptions, metering", "count": 4 }, { "slug": "email", "name": "Email", "agent_task": "Send, receive, and manage email", "count": 1 } ] } ``` The category id used to filter the [registry](/registry) and to fetch one category. The job an agent is trying to do, in plain language. How many scored products are filed under the category. ## Get one category Returns the category plus its products, highest AgentReady Score first. ```bash curl "https://api.stackresolve.dev/v1/categories/payments" ``` The category slug, for example `payments`. ```json Response { "category": { "slug": "payments", "name": "Payments & Billing", "agent_task": "Charge customers, subscriptions, metering" }, "products": [ { "slug": "paddle", "name": "Paddle", "domain": "paddle.com", "agentready": 83 }, { "slug": "mercury", "name": "Mercury", "domain": "mercury.com", "agentready": 81 }, { "slug": "stripe", "name": "Stripe", "domain": "stripe.com", "agentready": 74 }, { "slug": "ramp", "name": "Ramp", "domain": "ramp.com", "agentready": 64 } ] } ``` ## Browse a category in the registry To page or filter within a category, hit the registry with a `category` filter: ```bash curl "https://api.stackresolve.dev/v1/registry?category=payments&minScore=80&limit=10" ``` ## Related - [Registry](/registry): list, profile, compare, badge. - [Find tools](/find-tools): ranked candidates for a plain-English task. ======================================================================== # Find tools Source: https://stackresolve.dev/docs/find-tools > Ranked tool candidates for a task, filtered by capability. Give StackResolve a task or a query and it returns ranked tools that can do the job. Every candidate carries its [AgentReady Score](/methodology), so an agent can pick a tool it can actually adopt and operate. There are two entry points: `find_tools_for_task` for a plain-English task, and `search_tools` for a query plus hard capability filters. ## Find tools for a task `find_tools_for_task` takes a plain-English task. One model call parses it into search terms plus requirements, then the registry is searched and ranked by AgentReady Score. ```bash REST curl https://api.stackresolve.dev/v1/find-tools \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"task": "send transactional email from an agent"}' ``` ```text MCP find_tools_for_task({ task: "send transactional email from an agent" }) ``` ```bash CLI stackresolve find "send transactional email from an agent" ``` A plain-English description of the job to be done. ```json Response { "task": "send transactional email from an agent", "intent": { "searchTerms": "send transactional email", "requirements": {} }, "results": [ { "slug": "resend", "name": "Resend", "domain": "resend.com", "agentready": 98 } ] } ``` How the model read your task: the `searchTerms` it searched for and the hard `requirements` it inferred (any of `api`, `mcp`, `self_serve`, `openapi`, `cli`). Ranked candidates, highest AgentReady Score first. Each is `{ slug, name, domain, agentready }`. ## Search with requirements `search_tools` filters discovery by required capabilities. It is a hard filter: a product that lacks a required capability is dropped, not just ranked lower. Supported capability filters: `api`, `mcp`, `self_serve`, `openapi`, `cli`. ```bash REST curl https://api.stackresolve.dev/v1/search \ -H "content-type: application/json" \ -d '{"query": "payments", "requirements": {"api": true, "mcp": true}}' ``` ```text MCP search_tools({ query: "payments", api: true, mcp: true }) ``` ```bash CLI stackresolve search payments ``` Free-text query matched against name, slug, and company description or categories. Optional hard filters over `api`, `mcp`, `self_serve`, `openapi`, `cli`. On REST, nest them under `requirements`. On MCP, pass them as flat booleans on the tool input. ```json Response [ { "slug": "paddle", "name": "Paddle", "domain": "paddle.com", "agentready": 83 }, { "slug": "stripe", "name": "Stripe", "domain": "stripe.com", "agentready": 74 } ] ``` `search_tools` is a free, unmetered read. `find_tools_for_task` runs a model call and is metered as `agent_discovery_check`. Use search when you already know the requirements; use find-tools when you have a task in plain language. Feed a candidate's `slug` into [get_profile](/registry) for full detail, or [audit](/audit) for a fresh score. Feed a domain into [get_company](/primitives/company) for research. ======================================================================== # get_company Source: https://stackresolve.dev/docs/primitives/company > A normalized company record from a domain, with per-field freshness. `get_company` returns a structured record for a company: description, products, categories, technology, recent news, and, when available, executives and funding. Every field carries a freshness stamp. Use it when you need a snapshot of what a company is and does, without running your own search-crawl-extract loop. ## Call it ```bash REST curl "https://api.stackresolve.dev/v1/company?domain=resend.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```text MCP get_company({ domain: "resend.com" }) ``` ```bash CLI companydata company resend.com ``` ## Parameters The company domain, for example `resend.com`. A bare slug also works. ## Response ```json Response (trimmed) { "name": "Resend", "domain": "resend.com", "description": "Email platform for developers to deliver transactional and marketing emails at scale.", "products": ["Email API", "Transactional emails", "Marketing campaigns/Broadcasts", "Webhooks", "React Email (open source component library)", "MCP server"], "categories": ["Email service", "Developer tools", "SaaS", "API", "Marketing automation"], "technology": ["Node.js", "Next.js", "Python", "Ruby", "Go", "REST API", "SMTP", "React", "MCP (Model Context Protocol)"], "recent_news": { "mcp_server_launch": "Resend launched an MCP server for agentic email automation." }, "freshness": { "description": { "observedAt": "2026-08-20T08:02:33.979Z", "stale": false }, "products": { "observedAt": "2026-08-20T08:02:34.117Z", "stale": false }, "recent_news": { "observedAt": "2026-08-20T08:02:34.548Z", "stale": false } }, "cached": false } ``` ## Response fields What the company does, one to three sentences. Named products and features. The categories the company sits in. Languages, frameworks, and protocols in use. Recent, dated developments. The fastest-moving field. Key people, when known. Omitted when not found. Funding rounds and investors, when known. Omitted when not found. One entry per returned field, each `{ observedAt, stale }`. See [Freshness](/reference/freshness). `true` means every field was served from stored facts. `false` means at least one field was refreshed on this call. See [Caching](/reference/caching). ## Freshness Field TTLs vary by how fast the value changes ([Freshness](/reference/freshness)): `description` and `categories` about 30 days, `products`, `funding`, `technology`, and `executives` about 7 days, `recent_news` about 1 hour. A field past its TTL is refreshed on your next call; fresh fields are served from cache. See the full field list per namespace in [Schemas](/reference/schemas). Metered as one `workflow_execution` event. Keyed callers are billed against their plan; anonymous callers fall under the [trial limit](/reference/rate-limits). ## Related - [get_pricing](/primitives/pricing): pricing tiers and self-serve. - [find_competitors](/primitives/competitors): real competing companies. - [compare_companies](/primitives/compare): line several companies up. ======================================================================== # get_pricing Source: https://stackresolve.dev/docs/primitives/pricing > Normalized pricing for a company: tiers, free tier, and self-serve. `get_pricing` returns normalized pricing signals: the pricing structure, whether there is a free tier, and whether signup is self-serve. Use it to answer "what does this cost, and can an agent sign up without a human?" in one call. ## Call it ```bash REST curl "https://api.stackresolve.dev/v1/pricing?domain=resend.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```text MCP get_pricing({ domain: "resend.com" }) ``` ```bash CLI companydata pricing resend.com ``` ## Parameters The company domain, for example `resend.com`. A bare slug also works. ## Response ```json Response (trimmed) { "domain": "resend.com", "pricing": { "free": { "monthly_cost": 0, "emails_per_month": 3000, "daily_limit": 100 }, "pro": { "monthly_cost": 20, "emails_per_month": 50000, "overage_rate": 0.9, "overage_unit": "per 1000 emails" }, "scale": { "monthly_cost": 90, "emails_per_month": 100000 }, "enterprise": { "monthly_cost": "custom" } }, "free_tier": true, "self_serve": true, "freshness": { "pricing": { "observedAt": "2026-08-20T05:29:20.854Z", "stale": false }, "free_tier": { "observedAt": "2026-08-20T05:29:20.995Z", "stale": false }, "self_serve": { "observedAt": "2026-08-20T08:02:36.094Z", "stale": false } }, "cached": true } ``` ## Response fields The normalized tier structure. Shape varies by company: plans, per-unit rates, add-ons, and custom or enterprise tiers where they exist. Whether a free tier exists. Whether an agent can sign up and start without a human or a sales call. One entry per field, each `{ observedAt, stale }`. See [Freshness](/reference/freshness). `true` when served from stored facts, `false` when a field was refreshed on this call. ## Freshness Pricing changes often, so its TTL is short (about 1 day). If the stored value is older than that, the call refreshes it before returning. See [Freshness](/reference/freshness) and [Caching](/reference/caching). Metered as one `workflow_execution` event. Keyed callers are billed against their plan; anonymous callers fall under the [trial limit](/reference/rate-limits). ## Related - [get_company](/primitives/company): the full company record. - [compare_companies](/primitives/compare): line pricing up across companies. ======================================================================== # find_competitors Source: https://stackresolve.dev/docs/primitives/competitors > Real competing companies for a domain, not listicles. `find_competitors` returns actual competing companies and products, not the review articles and "top 10 alternatives" listicles a raw search surfaces. It searches, then extracts the real competitors from the results with a model, dropping news sites and blogs. ## Call it ```bash REST curl "https://api.stackresolve.dev/v1/competitors?domain=resend.com&limit=8" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```text MCP Not available over MCP. Use REST or the CLI. ``` ```bash CLI companydata competitors resend.com ``` `find_competitors` is a REST and CLI primitive. It is not one of the hosted [MCP](/mcp) tools. ## Parameters The company domain, for example `resend.com`. A bare slug also works. Maximum competitors to return. ## Response ```json Response { "domain": "resend.com", "competitors": [ { "name": "Amazon SES", "domain": "aws.amazon.com/ses" }, { "name": "Mailgun", "domain": "mailgun.com" }, { "name": "Postmark", "domain": "postmarkapp.com" }, { "name": "SendGrid", "domain": "sendgrid.com" } ] } ``` ## Response fields Real competing companies, each `{ name, domain? }`. The company itself is excluded. Feed the resulting domains straight into [compare_companies](/primitives/compare) for a side-by-side, or [get_company](/primitives/company) for depth on any one. ## Related - [compare_companies](/primitives/compare) - [get_company](/primitives/company) - [research_company](/primitives/research) ======================================================================== # compare_companies Source: https://stackresolve.dev/docs/primitives/compare > Structured side-by-side of several companies. `compare_companies` returns a structured comparison of several companies across the fields you pick. Each company is resolved through [get_company](/primitives/company), so the values are cached facts with provenance, not a fresh essay. ## Call it ```bash REST curl https://api.stackresolve.dev/v1/compare-companies \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"domains": ["resend.com", "sendgrid.com"]}' ``` ```text MCP Not available over MCP. Use REST or the CLI. ``` ```bash CLI companydata compare resend.com sendgrid.com ``` `compare_companies` is a REST and CLI primitive. It is not one of the hosted [MCP](/mcp) tools. ## Parameters Two or more company domains to line up. Which fields to compare. Omit for the default set: `description`, `products`, `categories`, `funding`, `technology`. ## Response ```json Response (trimmed) { "fields": ["description", "products", "categories", "funding", "technology"], "rows": [ { "domain": "resend.com", "name": "Resend", "values": { "description": "Email platform for developers to deliver transactional and marketing emails at scale.", "products": ["Email API", "Transactional emails", "Webhooks"], "categories": ["Email service", "Developer tools", "API"], "funding": null, "technology": ["Node.js", "Python", "REST API", "MCP (Model Context Protocol)"] } }, { "domain": "sendgrid.com", "name": "Sendgrid", "values": { "description": "Email delivery platform offering API and marketing campaign solutions, now part of Twilio.", "products": ["SendGrid Email API", "SMTP service", "Marketing Campaigns"], "categories": ["email", "email API", "email marketing"], "funding": null, "technology": ["Email API", "SMTP", "AI assistant"] } } ] } ``` ## Response fields The fields compared, in column order. One row per company: `{ domain, name, values }`, where `values` holds the chosen fields. A `null` value means the fact is unknown for that company. Metered as one `workflow_execution` event. Resolving each company can refresh stale fields, which warms the cache for later [get_company](/primitives/company) calls. ## Related - [get_company](/primitives/company) - [find_competitors](/primitives/competitors) - [Compare products](/registry) for registry products (scores and capabilities). ======================================================================== # research_company Source: https://stackresolve.dev/docs/primitives/research > A grounded, cited answer to a question about a company. `research_company` answers a specific question about a company, grounded only in real sources. It searches for the question, synthesizes a short answer from the excerpts, and returns the source URLs. Use it when a snapshot is not enough and you need synthesis with citations you can check. ## Call it ```bash REST curl https://api.stackresolve.dev/v1/research \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"domain": "resend.com", "question": "does it support batch sending?"}' ``` ```text MCP research_company({ domain: "resend.com", question: "does it support batch sending?" }) ``` ```bash CLI companydata research resend.com "does it support batch sending?" ``` ## Parameters The company domain, for example `resend.com`. The question to answer. Omit it for a general overview (products, funding, recent news). ## Response ```json Response (trimmed) { "domain": "resend.com", "question": "Resend: does it support batch sending?", "answer": "Yes, Resend supports batch sending. You can send up to 100 emails in a single API call using their batching endpoint. Each email in the batch can have different recipients, subjects, and content, and the response returns an array of email IDs in request order.", "sources": [ "https://resend.com/docs/api-reference/emails/send-batch-emails", "https://resend.com/docs/dashboard/emails/batch-sending", "https://resend.com/blog/introducing-the-batch-emails-api" ] } ``` ## Response fields A short, grounded answer, typically three to six sentences. It is grounded strictly in the returned `sources`. If the sources do not support a claim, it is not made. The exact URLs behind the answer. Cite them or open them to verify. Ask narrow questions. "Does it support marketplaces and payouts?" beats "tell me about this company". A narrow question returns tighter sources and a sharper answer. ## Related - [get_company](/primitives/company): the structured snapshot. - [Sources](/reference/sources): how provenance works. ======================================================================== # Schemas Source: https://stackresolve.dev/docs/reference/schemas > The normalized fields behind every answer. StackResolve does not return prose blobs. It stores atomic, typed facts grouped into namespaces, and every primitive reads from them. This is what keeps the output normalized and reusable rather than a free-text report. Each field has a type and a time-to-live (TTL) that drives [Freshness](/reference/freshness). ## company The record behind [get_company](/primitives/company). | Field | Type | TTL | | --- | --- | --- | | `description` | string | 30 days | | `products` | string[] | 7 days | | `categories` | string[] | 30 days | | `executives` | object | 7 days | | `funding` | object | 7 days | | `technology` | string[] | 7 days | | `recent_news` | object | 1 hour | ## pricing The record behind [get_pricing](/primitives/pricing). | Field | Type | TTL | | --- | --- | --- | | `pricing` | object | 1 day | | `free_tier` | bool | 1 day | | `self_serve` | bool | 1 day | ## agent_capability The capability facts the [AgentReady Score](/methodology) reads. | Field | Type | TTL | | --- | --- | --- | | `api` | bool | 7 days | | `openapi` | bool | 7 days | | `mcp_available` | bool | 1 day | | `cli` | bool | 7 days | | `sdks` | string[] | 7 days | | `llms_txt` | bool | 7 days | | `authentication` | string | 7 days | | `claude_compatible` | bool | 1 day | | `codex_compatible` | bool | 1 day | | `cursor_compatible` | bool | 1 day | ## readability Agent-readability signals, aligned with the Vercel agent-readability spec. | Field | Type | TTL | | --- | --- | --- | | `robots_ai_allowed` | bool | 7 days | | `sitemap` | bool | 7 days | | `agents_md` | bool | 7 days | | `canonical` | bool | 7 days | | `meta_description` | bool | 7 days | | `json_ld` | bool | 7 days | | `markdown_mirror` | bool | 7 days | ## Category specialization Some categories carry their own fields so the output is genuinely normalized, not generic. - **payments**: `cards`, `ach`, `marketplaces`, `stablecoins`, `subscriptions`, `payouts`, `merchant_of_record`, `countries`. - **database**: `engine`, `serverless`, `branching`, `vector`, `regions`. - **crm**: `contacts`, `pipelines`, `api_first`, `native_integrations`. More categories gain their own fields over time. Each field's TTL drives [Freshness](/reference/freshness). Values are typed: a bool is a real boolean, a list is a real array, an object is a nested structure. ## Related - [Freshness](/reference/freshness): the TTLs in action. - [Sources](/reference/sources): where each fact came from. ======================================================================== # Sources Source: https://stackresolve.dev/docs/reference/sources > Every fact is auditable to where it came from. Every fact carries provenance. Nothing is asserted without a source, and each answer traces back to the page it came from, when it was fetched, and how strongly the source supports it. ## What a fact carries Every current fact, as returned by a [profile](/registry), carries: | Field | Meaning | | --- | --- | | `value` | The typed value (bool, string, list, or object) | | `confidence` | 0 to 1, how strongly the source supports the fact | | `observedAt` | When it was fetched | | `stale` | Whether it is past its freshness TTL | Behind each fact is a source record with the exact URL it came from, the time it was fetched, and how strongly that source supports the value. ## Confidence Confidence reflects how the fact was established, not a vote. - Deterministic signals are high confidence. A published npm package, a `*-mcp` GitHub repo, or a served `llms.txt` file set their facts at 0.9 and above, because the evidence is hard. See [Methodology](/methodology). - Vendor-verified facts are high confidence, after a domain [claim](/rest). - A single-source model extraction is medium. - An inferred value is lower. ## Citations you can check [research_company](/primitives/research) returns its `sources` array directly, so you can open or cite the exact URLs behind the answer. The answer is grounded strictly in those sources: if a source does not support a claim, the claim is not made. ## Related - [Freshness](/reference/freshness): the `stale` flag and TTLs. - [Schemas](/reference/schemas): the fields each source populates. ======================================================================== # Freshness Source: https://stackresolve.dev/docs/reference/freshness > Every field knows how stale it is allowed to be. Each field has a time-to-live (TTL) based on how fast it changes. When you call a primitive, any field older than its TTL is refreshed before the answer is returned; fresh fields are served from cache. You do not get silently stale data, and you do not pay to re-fetch something that is still current. ## How it works Every fact is stored with an `expires_at` set from its namespace and key TTL. A fact past that time is marked `is_stale`. On the next call, the engine triages the requested fields into missing, stale, and fresh, then refreshes only the missing and stale ones. A refresh writes a new fact row and supersedes the old one, keeping the confidence and the source. ## TTLs | Field group | Fields | TTL | | --- | --- | --- | | Fast-moving | `recent_news` | 1 hour | | Daily | `pricing`, `free_tier`, `self_serve`, `mcp_available`, `claude_compatible`, `codex_compatible`, `cursor_compatible` | 1 day | | Weekly | `products`, `funding`, `technology`, `executives`, `api`, `openapi`, `cli`, `sdks`, `llms_txt`, and the `readability` signals | 7 days | | Slow-moving | `description`, `categories` | 30 days | See [Schemas](/reference/schemas) for the per-field TTL table. ## In the response Every research response carries a `freshness` block, one entry per returned field: ```json "freshness": { "description": { "observedAt": "2026-08-20T08:02:33.979Z", "stale": false }, "recent_news": { "observedAt": "2026-08-20T08:02:34.548Z", "stale": false } } ``` A [profile](/registry) reports the same per-fact, with `observedAt` and `stale` on each fact, plus a top-level `lastChecked`. ## cached vs stale The `cached` flag on a research response tells you whether the whole answer came from stored facts (`true`) or at least one field was refreshed on this call (`false`). The per-field `stale` flag tells you the freshness state of that field. See [Caching](/reference/caching) for how repeat calls stay fast and cheap. ======================================================================== # Caching Source: https://stackresolve.dev/docs/reference/caching > Why the 500th call is almost free. The first call for a company is expensive: it gathers the underlying evidence and runs a model to extract and normalize the facts. Every call after that reads stored facts from the database, so it is fast and nearly free, right up until a field crosses its [freshness](/reference/freshness) TTL and gets refreshed on its own. ```text First call: gather + extract + normalize ($) Later calls: stored facts (~free) Stale field: refresh only that field (partial $) ``` The `cached` flag on a research response tells you which case you got. `cached: true` means every returned field came from storage. `cached: false` means at least one field was missing or stale and got refreshed on this call. ## One shared fact store Inside StackResolve, the readiness system and the research primitives share one fact store. Research done anywhere warms the cache for everyone. A tool scored by an [audit](/audit) is already partly populated when you call [get_company](/primitives/company), and a company you have researched is already partly populated when you audit it. ## Metering and cache Metering is per call, not per refresh. A metered primitive records one usage event whether the answer came from cache or a fresh gather. Your charge is governed by your plan and the metered event, not by how much work the call did under the hood. See [Billing & metering](/reference/billing). ## Related - [Freshness](/reference/freshness): the per-field TTLs. - [Schemas](/reference/schemas): the fields and their TTLs. ======================================================================== # Errors Source: https://stackresolve.dev/docs/reference/errors > Error format, HTTP status codes, and the entitlement reason codes. Errors return a JSON body with an `error` message and an appropriate HTTP status. ```json { "error": "a valid API key is required for this endpoint" } ``` ## Status codes | Status | Meaning | Typical body | Fix | | --- | --- | --- | --- | | `400` | Malformed request | `{ "error": "missing stripe-signature" }` | Check the body, query params, and headers | | `401` | Missing or invalid API key | `{ "error": "a valid API key is required for this endpoint" }` | Send a valid `x-api-key` ([Authentication](/authentication)) | | `402` | Plan limit reached (metered call) | `{ "error": "USAGE_LIMIT_REACHED", "entitlement": { ... } }` | Enable metered billing or raise limits ([Billing](/reference/billing)) | | `404` | Unknown route or entity | `{ "error": "not found" }` or `{ "error": "unknown product" }` | Check the path or slug | | `429` | Anonymous trial limit reached | `{ "error": "anonymous trial limit reached (8/hour). Get a free API key for more." }` | Get a free key ([Rate Limits](/reference/rate-limits)) | | `500` | Internal error | `{ "error": "..." }` | Retry with backoff; report if it persists | | `503` | Billing not configured | `{ "error": "..." }` | Only on checkout or portal when Stripe is not set up | ## Entitlement reason codes A `402` on a metered primitive carries an `entitlement` object with a `reason`. The reason tells you why the call was blocked. | Reason | Meaning | | --- | --- | | `OK` | Allowed. Not an error. | | `USAGE_LIMIT_REACHED` | The plan's included quantity for this event type is used up and overage is off | | `HARD_LIMIT_REACHED` | A hard usage cap on this event type was reached | | `SPEND_LIMIT_REACHED` | Your monthly spend hard limit was reached ([Limits](/reference/billing)) | The `entitlement` object also reports `included`, `used`, `remaining`, and `meteredEnabled`, so an agent can decide whether to enable billing or wait for the next period. ## MCP errors The hosted [MCP](/mcp) speaks JSON-RPC. A missing or invalid key returns: ```json { "jsonrpc": "2.0", "error": { "code": -32001, "message": "a valid StackResolve API key is required (x-api-key header)" }, "id": null } ``` A blocked metered tool call returns a tool error whose message names the reason and your used-versus-included counts. ## Resilience The research primitives are built to degrade, not fail. If a scrape or a single source fails, the call still returns the facts it could gather rather than erroring out, and the `freshness` block shows what it could and could not refresh. ## Related - [Rate Limits](/reference/rate-limits) - [Billing & metering](/reference/billing) - [Authentication](/authentication) ======================================================================== # Rate Limits Source: https://stackresolve.dev/docs/reference/rate-limits > Free to try, more with a key, governed by your plan. Reads are open. The primitives that spend money are gated so a public endpoint cannot be abused. How they are gated depends on whether you send a key. ## The two paths | Caller | How metered calls are gated | | --- | --- | | Anonymous (by IP) | A small hourly trial: 8 requests per hour per IP | | With an API key | Your plan's included quantity per event type, per billing period | Anonymous callers share one IP bucket across all metered primitives. When the bucket is empty you get `429`. Keyed callers do not hit the hourly IP limit; instead each metered call runs a billing entitlement check against your plan. When the included quantity is used up and overage is off, you get `402`. See [Billing & metering](/reference/billing) and [Errors](/reference/errors). ## Which calls are metered Metered (need a key or fall under the trial): - `/v1/audit` (`audit_run`) - `/v1/company`, `/v1/pricing`, `/v1/competitors`, `/v1/compare-companies`, `/v1/research` (`workflow_execution`) - `/v1/find-tools` (`agent_discovery_check`) Open and never rate limited: - `/v1/registry`, `/v1/profile/{slug}`, `/v1/categories`, `/v1/categories/{slug}` - `/v1/search`, `/v1/compare` - `/health`, `/llms.txt`, `/openapi.json`, `/badge/{slug}.svg` ## Sending your key ```bash curl "https://api.stackresolve.dev/v1/company?domain=stripe.com" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` For MCP and CLI, set `STACKRESOLVE_API_KEY` in the environment (MCP clients send it as the `x-api-key` header). See [Authentication](/authentication). ## Handling limits - On `429` (anonymous), [get a free key](https://app.stackresolve.dev) to move off the IP trial, or back off and retry after the hour rolls over. - On `402` (keyed), read the `entitlement` object to see `used` versus `included`, then enable metered billing or wait for the next period. - Pass an `idempotency-key` header on metered requests so a retry is not double-counted. Free reads (the registry, profiles, categories, search, compare, badges) are never rate limited. Only the money-spending primitives are. ======================================================================== # Billing & metering Source: https://stackresolve.dev/docs/reference/billing > Event types, usage, entitlements, limits, and the billing endpoints. StackResolve bills usage, not seats. Each expensive call records one usage event against your workspace. Cheap reads are free. All endpoints on this page need a valid key ([Authentication](/authentication)). ## Plans | Plan | Price | Included per month | | --- | --- | --- | | Starter | Free | Unlimited registry reads, 100 audits, 1,000 research calls, 1,000 tool-finds. No card. Usage stops at the limit. | | Usage | Pay as you go | No monthly fee, no minimums. Per-call rates below. Set your own spend limits. | | Scale | Custom | Volume rates, annual invoicing, SLAs. [Talk to us](/developers). | ## Per-call rates | Operation | Event type | Per call | Per 1k | | --- | --- | --- | --- | | Registry read (list, profile, search, compare) | none | Free | Free | | Find tools for a task | `agent_discovery_check` | $0.005 | $5 | | Company research (company, pricing, competitors, compare, research) | `workflow_execution` | $0.015 | $15 | | Audit a product | `audit_run` | $0.03 | $30 | You are charged once per call, whether the answer is fresh or served from cache. See the full pricing page at [/pricing](/pricing). ## Metered event types Three event types are wired to the API surface today. | Event type | Recorded by | | --- | --- | | `audit_run` | `/v1/audit`, the `audit` MCP tool, `stackresolve audit` | | `workflow_execution` | `/v1/company`, `/v1/pricing`, `/v1/competitors`, `/v1/compare-companies`, `/v1/research`, and their MCP tools | | `agent_discovery_check` | `/v1/find-tools`, the `find_tools_for_task` MCP tool | The usage taxonomy also reserves `monitor_check`, `api_request`, `mcp_request`, and `browser_execution` for later primitives. Plans and included quantities are configured per event type, so a new event type can be priced without an app change. ## How a metered call is settled 1. The call resolves your workspace from the `x-api-key` header. 2. It runs an entitlement check for the event type. If the included quantity is used up and overage is off, or a hard or spend limit is reached, the call returns `402` ([Errors](/reference/errors)). 3. Otherwise the call runs and records one usage event, tagged with its source (`api`, `mcp`, or `cli`). Pass an `idempotency-key` header to make a retry safe: a repeat with the same key does not double-record. ## GET /v1/usage Your usage this billing period, per meter. ```bash curl https://api.stackresolve.dev/v1/usage -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```json Response (trimmed) { "workspaceId": "ws_123", "plan": "free", "meteredEnabled": false, "period": { "start": "2026-08-01T00:00:00Z", "end": "2026-09-01T00:00:00Z" }, "meters": [ { "eventType": "audit_run", "included": 2, "used": 1, "remaining": 1, "billableOverage": 0, "overageEnabled": false, "estimatedChargeUsd": 0 }, { "eventType": "workflow_execution", "included": 25, "used": 12, "remaining": 13, "billableOverage": 0, "overageEnabled": false, "estimatedChargeUsd": 0 }, { "eventType": "agent_discovery_check", "included": 10, "used": 3, "remaining": 7, "billableOverage": 0, "overageEnabled": false, "estimatedChargeUsd": 0 } ], "estimatedChargesUsd": 0 } ``` The same summary is available as the `get_usage` MCP tool and `stackresolve usage`. ## GET /v1/entitlements Included, used, and remaining per event type, plus whether each is allowed right now. ```json Response (trimmed) { "entitlements": [ { "eventType": "audit_run", "plan": "free", "allowed": true, "included": 25, "used": 3, "remaining": 22, "overageEnabled": false, "meteredEnabled": false, "hardLimit": null, "reason": "OK" } ] } ``` ## GET /v1/usage/events Raw usage events, newest first. Filterable. Filter to one event type. Filter to one product. ISO timestamp, inclusive lower bound. ISO timestamp, exclusive upper bound. Max rows (capped at 500). Row offset for paging. ```bash curl "https://api.stackresolve.dev/v1/usage/events?event_type=audit_run&limit=50" \ -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```json Response (trimmed) { "events": [ { "id": "evt_9", "event_type": "audit_run", "quantity": 1, "billable_quantity": 0, "source": "api", "provider_cost_usd": 0.0177, "occurred_at": "2026-08-20T08:47:13.253Z", "stripe_sync_status": "not_applicable" } ] } ``` ## GET and PATCH /v1/limits Set spend guardrails. A warning is informational; a hard limit blocks further metered calls with `402` and reason `SPEND_LIMIT_REACHED`. ```bash Get curl https://api.stackresolve.dev/v1/limits -H "x-api-key: $STACKRESOLVE_API_KEY" ``` ```bash Set curl -X PATCH https://api.stackresolve.dev/v1/limits \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"monthlyBudgetUsd": 50, "warningThresholdUsd": 40, "hardLimitUsd": 60, "notificationsEnabled": true}' ``` ```json Response { "monthlyBudgetUsd": 50, "warningThresholdUsd": 40, "hardLimitUsd": 60, "notificationsEnabled": true } ``` Soft monthly budget, or null to clear. Spend at which to warn, or null. Spend at which to block metered calls, or null. Whether to send limit notifications. ## GET /v1/billing Plan, current-period spend, and the estimated upcoming charge. ```json Response { "plan": "usage", "meteredEnabled": true, "period": { "start": "2026-08-01T00:00:00Z", "end": "2026-09-01T00:00:00Z" }, "spend": { "status": "OK", "spentUsd": 4.20, "monthlyBudgetUsd": 50, "warningThresholdUsd": 40, "hardLimitUsd": 60 }, "estimatedUpcomingUsd": 4.20, "stripeConfigured": true } ``` ## Enable metered billing Start a Stripe checkout, then manage the subscription in the portal. ```bash Checkout curl -X POST https://api.stackresolve.dev/v1/billing/checkout \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"successUrl": "https://yourapp.com/billing?ok=1", "cancelUrl": "https://yourapp.com/billing", "email": "you@yourapp.com"}' ``` The response holds a Stripe checkout `url`. Send the user there. After they subscribe, `meteredEnabled` becomes true and overage is billed against your plan. ```bash Portal curl -X POST https://api.stackresolve.dev/v1/billing/portal \ -H "x-api-key: $STACKRESOLVE_API_KEY" \ -H "content-type: application/json" \ -d '{"returnUrl": "https://yourapp.com/billing"}' ``` Where Stripe returns after a successful checkout. Where Stripe returns on cancel. Prefill the checkout email. Portal only: where the portal returns. Checkout and portal return `503` when Stripe is not configured for the deployment. ## GET /v1/billing/invoices ```json Response { "invoices": [ { "id": "in_1", "amountDueUsd": 4.20, "status": "paid", "periodStart": "2026-07-01", "periodEnd": "2026-08-01" } ] } ``` ## Related - [Rate Limits](/reference/rate-limits): the anonymous trial and keyed gating. - [Errors](/reference/errors): the `402` and entitlement reason codes. - [Caching](/reference/caching): why a cache hit still records one event.