API & MCP reference

Reconmark's data - live opportunities, recompetes, agencies, companies, contract vehicles, and your own pipeline - is available as a read-only REST API and as an MCP server, so you can pull it into scripts, spreadsheets, or an LLM agent. Both surfaces share one auth mechanism (an API key) and one rate limit.

Auth

Every request - REST or MCP - authenticates with an API key as a bearer token:

Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Create a key from Settings → API keys. The full secret is shown exactly once, at creation time - Reconmark stores only a hash, so if you lose it you'll need to revoke it and create a new one. API access is a paid-plan feature.

A missing or invalid key returns 401 with error.code = "invalid_api_key". A key that's over its rate limit returns 429 - see Rate limits.

Envelope & errors

Every list endpoint returns data plus a meta pagination block:

{
  "data": [ { "id": "SAM-2026-00123", "title": "IT Support Services", ... } ],
  "meta": { "page": 1, "pageSize": 10, "total": 342, "totalPages": 35 }
}

Single-resource endpoints (e.g. GET /opportunities/{id}) return just data, no meta. Every error - on any 4xx/5xx, from any endpoint - has the same shape, never a bare string:

{ "error": { "code": "rate_limited", "message": "Rate limit exceeded. Retry after 12 seconds." } }
codestatusmeaning
invalid_api_key401Missing/malformed Authorization header, or the secret doesn't match any non-revoked key.
invalid_request400Query params failed validation; message plus, where relevant, an issues array.
not_found404The requested resource id doesn't exist.
rate_limited429Per-key per-minute limit exceeded. Retry-After header is set.
not_implemented501Spec'd but not-yet-built endpoint - an honest placeholder, never a fake empty success.
internal_error500Unhandled server error, logged server-side.

Rate limits

Every key has a per-minute limit - 60 requests/min by default, shown per-key in Settings. Every response carries the current state:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1751500860

X-RateLimit-Resetis unix seconds for the start of the next window. When you're over the limit you get 429 plus a Retry-After header (seconds). The limit is a fixed one-minute window shared across REST and MCP - calling a tool over MCP counts against the same budget as calling the equivalent REST route.

Endpoints

All routes are under /api/v1, read-only, paginated with page (default 1) and pageSize (default 20, max 100).

GET/api/v1/opportunities

Search live opportunities (RFPs, grants, sources-sought, etc). Same filters as the dashboard's opportunity table.

naics2-6 digit NAICS prefix
agencyAgency acronym, e.g. GSA
setAsideSet-aside code, e.g. 8A, WOSB, SDVOSB
statePlace-of-performance 2-letter state
cityPlace-of-performance city (partial match)
typeNotice type, e.g. RFP, GRANT, Sources Sought
qFree-text search
fStructured filter, repeatable: field:op:value
sort / dirtitle | type | agency | closes | posted | value, asc | desc
page / pageSize1-based page, max pageSize 100 (default 20)
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/opportunities?naics=541512&setAside=8A&sort=closes&dir=asc&pageSize=10"
GET/api/v1/opportunities/{id}

Full detail for one opportunity by notice id, including documents and Q&A.

idThe opportunity's notice_id (path segment)
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/opportunities/cd997119e32f4adfbcfc2dfbb6f2812a"
GET/api/v1/recompetes

Contracts with an expiring incumbent in a time window - what's coming up for rebid.

monthsExpiring-within window, 3-24 (default 18)
naics / agency / setAsideSame as opportunities
minValueMinimum contract value
qFree-text search
sortends | value
page / pageSizePagination
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/recompetes?months=12&naics=541512&sort=ends"
GET/api/v1/agencies

Agency directory: acronym, name, active opportunity counts.

qFree-text search
sort / dirdepartment | agencyComponent | agencyType | activeSolicitationsCount | totalAwardedYtd
page / pageSizePagination
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/agencies?sort=activeSolicitationsCount&dir=desc"
GET/api/v1/agencies/{code}

Agency-intel summary: department, component, active solicitations, YTD awards, top NAICS.

codeagencies.agency_code (path segment)
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/agencies/097.97AS"
GET/api/v1/companies

Search government contractors by name, UEI, or location, ranked by total obligated.

qSearch legal name, UEI, or city
sort / dirlegal_name | total_obligated
page / pageSizePagination
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/companies?q=lockheed"
GET/api/v1/companies/{uei}

UEI-keyed company profile: certifications, NAICS/PSC codes, and the last 20 awards.

ueiThe company's UEI (path segment)
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/companies/G4KDGE4JFFK7"
GET/api/v1/vehicles

Contract-vehicle / IDIQ directory: ceiling, IDC type, ordering activity, expiration.

q / naics / agencySearch, NAICS prefix, awarding agency (substring)
idcTypeIDC type filter
minCeilingMinimum ceiling value
expiringWithinMonthsOrdering-window filter, 1-60 months
sortceiling | lastDateToOrder | obligated | childAwardCount
page / pageSizePagination
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/vehicles?naics=541512&sort=ceiling"
GET/api/v1/vehicles/{piid}

Vehicle profile: holders, ceiling, task-order flow by fiscal year, top ordering agencies.

piidThe vehicle's PIID (path segment)
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/vehicles/80JSC023DA004"
GET/api/v1/pipeline

The calling key's own user's pursuit pipeline (bid/no-bid tracking). Identity-bound - resolved from the key, not a public/shared resource.

statusqualifying | bidding | submitted | won | lost | no_bid
curl -H "Authorization: Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  "https://reconmark.io/api/v1/pipeline?status=bidding"

MCP setup

Reconmark also exposes an MCP server at /api/mcp (Streamable HTTP transport) with five tools that wrap the same query functions as the REST API above - no separate data path, same API key, same rate limit.

{
  "mcpServers": {
    "reconmark": {
      "url": "https://reconmark.io/api/mcp",
      "headers": { "Authorization": "Bearer rm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
    }
  }
}

That's Claude Desktop's remote-MCP config shape - other Streamable HTTP clients use the same URL + header. Reconmark doesn't ship a stdio bridge, so a stdio-only client would need its own local proxy.

toolwhat it does
search_opportunitiesSearch opportunities - same filters as the REST list endpoint, trimmed to agent-useful fields.
get_opportunityFull opportunity detail by notice id, including documents and Q&A.
list_recompetesContracts with an expiring incumbent in a time window - what's coming up for rebid.
my_pipelineYour own pursuit pipeline, resolved from the calling API key's owner - the one identity-bound tool.
get_verdictThe transparent 0-100 bid/no-bid score (Go/Watch/Pass) for one opportunity, calibrated from your capability profile and pursuit history. Deterministic - no LLM call happens inside Reconmark for this.

Changelog & versioning

v1is stable: field names, pagination shape, and error format won't change under you. Breaking changes ship as a new /api/v2 - v1 keeps working alongside it, not pulled out from under existing integrations.