↑↓ navigate ↵ open esc close

REST · OpenAPI 3.1

The government-contracts API, at full parity.

Every screen on Sell to State is backed by a documented REST endpoint under /api/v1. Search, drill into a buyer or supplier, export CSV, and keep saved lists — with one API key and the same paywall the MCP server and CLI share.

Ask your AI agent

Claude ChatGPT Perplexity Grok
Set up Sell to State for me: government tenders and contract awards from official sources in 73 countries, as MCP tools. Agent docs: https://docs.selltostate.com/llms.txt
1. Sign me in yourself. Try this first: you need me only for one approval click.
- If you can send HTTP requests: POST https://app.selltostate.com/api/v1/agent/signup with JSON {"client_name": "<your app name>"}. Show me verification_uri_complete from the reply as a link. I open it, sign up free with Google or email, and approve the code. Every "interval" seconds, POST token_endpoint with {"device_code": "<device_code>"} until the reply has access_token. Send access_token in the x-api-key header to the MCP server https://app.selltostate.com/api/mcp.
- If you cannot send HTTP requests: tell me to add the MCP server https://app.selltostate.com/api/mcp in this app. Its sign-in page also creates the free account. Claude: Customize > Connectors > Add custom connector. ChatGPT: chatgpt.com/plugins > + > Add custom MCP server, choose OAuth. Claude Code: claude mcp add --transport http selltostate https://app.selltostate.com/api/mcp, then /mcp > Authenticate.
2. The tools are free to connect. A free account gets plan_search 3 times a day and search for 2 different searches a day: titles, buyers, status and dates. Amounts, winners and notice links need a plan. Call whoami to see my plan.
3. Ask me what my company sells and in which countries. Call plan_search with my answer, then search with its scope, q and filters. Show me the 10 best open tenders with the title, the buyer and the dates. Then give me app_url: it shows every row, and I can save the search there for email alerts.

Enterprise

# 60-second quickstart

# 1. Create a key in the dashboard
#    Account → API keys
# 2. Verify it
curl -s https://app.selltostate.com/api/v1/whoami \
  -H "x-api-key: sts_xxxxxxxx"

# 3. Search
curl -s "https://app.selltostate.com/api/v1/search\
?scope=tenders&q=cybersecurity" \
  -H "x-api-key: sts_xxxxxxxx"

Same key works for the MCP server and the selltostate CLI.

Auth & the 402 paywall

Two credential types resolve to one entitlement check. Humans and backends send an API key as x-api-key: sts_…. Autonomous agents self-register over RFC 7591 DCR and present Authorization: Bearer client:<id>.

Until your subject has an active subscription, every data call returns 402 with a payment_link (humans) and a machine_payment affordance (agents can pay off-session via POST /api/v1/pay and continue without a browser). GET /api/v1/whoami is the exception — it returns 200 with active:false so you can decide to pay before doing work.

Plan caps: monthly and annual = 5,000 rows/page; the 3-day pass = 10,000 rows in total. Rate limit: 120 data calls/min per credential (faceted search has its own 300/min budget). Saved lists and saved searches are owner-scoped — they require a user x-api-key; an OIDC client token gets 403.

Endpoints.

All under /api/v1. Full params, schemas and "Try it" live in the reference.

GET /api/v1/whoami Auth + entitlement + scopes. Returns 200 active:false (not 402) for a valid-but-unsubscribed key — check before you spend.
GET /api/v1/search Faceted Typesense search over one scope (tenders | buyers | suppliers | sectors): hits + facet counts + pagination.
GET /api/v1/awards Paginated, filterable award rows ordered by value. CSV at /api/v1/awards.csv.
GET /api/v1/buyers/{slug} Buyer (agency) detail: summary, yearly spend trend, sector split, top suppliers.
GET /api/v1/suppliers/{slug} Supplier detail: summary, yearly awarded trend, sector split, top buyers.
GET /api/v1/sectors/{slug} Sector detail: summary, yearly trend, active partners (?kind=buyers|suppliers).
GET /api/v1/tenders/{id} Single award by numeric id or public tender id, plus related awards.
CRUD /api/v1/lists* Saved award lists. Owner-scoped — requires a user x-api-key.
CRUD /api/v1/saved-searches* Saved searches. Owner-scoped — requires a user x-api-key.

Examples.

Python — search awards

import requests

H = {"x-api-key": "sts_xxxxxxxx"}
r = requests.get(
    "https://app.selltostate.com/api/v1/search",
    params={"scope": "tenders", "q": "cybersecurity", "year_min": 2023},
    headers=H,
)
if r.status_code == 402:
    print("subscribe:", r.json()["payment_link"]); raise SystemExit
data = r.json()
print(data["found"], "matches")
for hit in data["hits"]:
    print(hit)

Node — buyer detail + CSV export

const H = { "x-api-key": process.env.STS_API_KEY };

const buyer = await fetch(
  "https://app.selltostate.com/api/v1/buyers/ministry-of-education",
  { headers: H },
).then((r) => r.json());
console.log(buyer.buyer, buyer.yearly);

// Stream the entitlement-capped CSV
const csv = await fetch(
  "https://app.selltostate.com/api/v1/awards.csv?supplier=ACME",
  { headers: H },
).then((r) => r.text());

Saved lists (user key)

# Create a list, add a tender, read it back
LID=$(curl -s -X POST https://app.selltostate.com/api/v1/lists \
  -H "x-api-key: sts_xxxxxxxx" -H "content-type: application/json" \
  -d '{"name":"Cyber FY24"}' | jq -r .id)

curl -s -X POST https://app.selltostate.com/api/v1/lists/$LID/items \
  -H "x-api-key: sts_xxxxxxxx" -H "content-type: application/json" \
  -d '{"tender_no":"MOE000ETT24300001"}'

Poll for new tenders.

A job in your scheduler, Zapier or n8n can ask for the tenders added to Sell to State since its last run. Keep the time of each run and send it as added_after. Remove duplicates by slug.

LAST=$(cat last_run 2>/dev/null || echo 0)
NOW=$(date +%s)
curl -s "https://app.selltostate.com/api/v1/search?scope=tenders&country=united-kingdom&q=software&sort=added_desc&added_after=$LAST&per_page=50"   -H "x-api-key: sts_xxxxxxxx"
echo "$NOW" > last_run
ParamValues
sortadded_desc (newest in Sell to State first), published_desc (newest publish date first), deadline, relevance
added_afterUnix seconds. Only tenders added after this time.
published_days1, 7, 30, 90, 365

The search limit is 300 calls a minute per key. A poll every 5 minutes or more is enough for tenders. Integrations

Pricing

One price for the whole team.

Search and daily email alerts are free. A plan shows the winner and the value of each award, and adds CSV export, the API and MCP.

3-day pass

US$19€19one payment

For one research job. Full access for 72 hours, then it stops. Nothing renews.

Get the 3-day pass

Sign up, then pay by card.

  • Full access for 3 days
  • 10,000 export rows in total
  • Search, lists, API and MCP
  • Saved searches and daily email alerts
  • One pass per account

Subscription

US$49€45/mo

US$499€449/yr

Cancel at any time.

One payment a year. 15%17% less than 12 monthly payments.

Subscribe monthlySubscribe annually

Sign up, then pay by card.

  • Access until you cancel12 months of access
  • 5,000 rows per export
  • Search, lists, API and MCP
  • Saved searches and daily email alerts
  • One price for the whole team. No seat fees.

Enterprise

Custom

For teams that need bulk data or their own contract terms.

Book a call

A 30-minute call with our team.

  • Everything in Subscription
  • Bulk delivery to Snowflake, Amazon S3 or a CRM webhook
  • Custom contract terms
Secure payments via Stripe Stripe Visa Mastercard American Express
See full pricing →

Get an API key.

Save a search, and we email you the new matches each day. Or ask your AI agent, or book a demo for your team.

Ask your AI agent

Claude ChatGPT Perplexity Grok
Set up Sell to State for me: government tenders and contract awards from official sources in 73 countries, as MCP tools. Agent docs: https://docs.selltostate.com/llms.txt
1. Sign me in yourself. Try this first: you need me only for one approval click.
- If you can send HTTP requests: POST https://app.selltostate.com/api/v1/agent/signup with JSON {"client_name": "<your app name>"}. Show me verification_uri_complete from the reply as a link. I open it, sign up free with Google or email, and approve the code. Every "interval" seconds, POST token_endpoint with {"device_code": "<device_code>"} until the reply has access_token. Send access_token in the x-api-key header to the MCP server https://app.selltostate.com/api/mcp.
- If you cannot send HTTP requests: tell me to add the MCP server https://app.selltostate.com/api/mcp in this app. Its sign-in page also creates the free account. Claude: Customize > Connectors > Add custom connector. ChatGPT: chatgpt.com/plugins > + > Add custom MCP server, choose OAuth. Claude Code: claude mcp add --transport http selltostate https://app.selltostate.com/api/mcp, then /mcp > Authenticate.
2. The tools are free to connect. A free account gets plan_search 3 times a day and search for 2 different searches a day: titles, buyers, status and dates. Amounts, winners and notice links need a plan. Call whoami to see my plan.
3. Ask me what my company sells and in which countries. Call plan_search with my answer, then search with its scope, q and filters. Show me the 10 best open tenders with the title, the buyer and the dates. Then give me app_url: it shows every row, and I can save the search there for email alerts.

Enterprise

Sign Up