# 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
```
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.