CompCurve · Developer Platform

License API Docs

Query 2.5M+ US & Canada real-estate licenses, refreshed monthly. Filter by state, name, office, status, and license dates; US rows carry matched email/phone enrichment. Read-only, JSON, fast at the edge.

Base URL https://api.compcurve.com openapi.json docs.md for agents & LLMs Explorer dashboard Get a free trial key →

Authentication

Every endpoint except /v1/health requires an API key. Send it as a Bearer token (preferred) or X-API-Key header:

curl -s https://api.compcurve.com/v1/licenses?state=CA\&limit=5 \
  -H "Authorization: Bearer cck_YOUR_KEY"

No key yet? Get a free trial key in one step (masked contacts, 30/min · 300/day · 2,000/month, 14 days). Production keys, the history add-on and enterprise plans are on the pricing page; every key — trial or paid — can see its own limits, quota, scope and usage on the dashboard.

Keys carry per-key rate limits (per-minute + per-day) and, on some tiers, a monthly quota. Every response carries RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset headers (plus X-Quota-Limit / X-Quota-Used when a quota applies); 429s include Retry-After. Check your own usage anytime via GET /v1/usage. Demo and trial keys receive server-side-masked contact fields.

Keys can be scoped to specific states/countries and to a licensed set of columns — scoped keys are automatically narrowed to their grant, and out-of-scope requests return 403 scope_denied with the grant listed. See your key's scope at GET /v1/me. To request a production key, contact eli@compcurve.com.

Historical snapshots are a separate add-on. Every key reads the latest monthly snapshot; keys with history access (scope.history.mode = months or all on /v1/me) can pass ?snapshot=YYYY-MM to query prior months and call /v1/licenses/history to follow one license across months with a field-level change log. Outside your history scope the API returns 403 history_denied; /v1/snapshots flags each loaded month accessible true/false for your key.

Endpoints

EndpointPurpose
GET /v1/healthLiveness + DB reachability (no auth)
GET /v1/meYour key's tier and configured rate limits
GET /v1/usageYour request counts by day and by endpoint (?days=30)
GET /v1/snapshotsAvailable monthly snapshots with row counts
GET /v1/statesStates/provinces + per-state row counts
GET /v1/statsPrecomputed aggregates: status/type vocabularies, contact coverage, expirations
GET /v1/licensesMain query endpoint — filters, sort, pagination, sparse fields
GET /v1/licenses/:idSingle license by internal id (id is per-snapshot)
GET /v1/licenses/historyOne license across every accessible snapshot + change log (?state=TX&license_number=… or ?id=…) — history add-on
GET /v1/suggestType-ahead: distinct prefix matches (?field=city|office|last_name&q=kel)
POST /mcpRemote MCP server (JSON-RPC over HTTP) — the same API as tools for Claude / Cursor / agents. Setup →

/v1/licenses parameters

ParamBehaviorExample
snapshotMonthly snapshot, e.g. 2026-07. Defaults to latest. Prior months require the history add-on — otherwise 403 history_denied (see /v1/me → scope.history)snapshot=2026-07
stateExact state/province code; comma-separable. e.g. CA,TXstate=CA,TX
countryUS or CAcountry=US
last_nameCase-insensitive prefix matchlast_name=smith
office_nameCase-insensitive prefix match (use /v1/suggest for autocomplete)office_name=keller
license_numberExact license numberlicense_number=00007012
license_statusExact status (vocab varies by state — see /v1/stats)license_status=Active
member_typeExact member typemember_type=Broker
cityExact citycity=Austin
postal_codeExact postal code (alias: zip)postal_code=94563
issued_afterISO date: license issued on/afterissued_after=2024-01-01
issued_beforeISO date: license issued on/beforeissued_before=2026-01-01
expires_afterISO date: license expires on/afterexpires_after=2026-08-01
expires_beforeISO date: license expires on/beforeexpires_before=2026-12-31
first_issued_afterISO datefirst_issued_after=2010-01-01
first_issued_beforeISO datefirst_issued_before=2020-01-01
sortComma-separated sort columns (whitelisted)sort=member_last_name,member_first_name
orderasc | descorder=desc
page1-based page numberpage=2
limitRows per page (default 100, max 1000)limit=500
fieldsSparse fieldset: comma-separated column namesfields=id,state,member_full_name
countSet false to skip the total-count query — faster; total/total_pages become null and has_next is inferred from page fillcount=false
formatResponse format: json (default), csv, or ndjson. For csv/ndjson, pagination is returned in X-Total-Count / X-Page / X-Has-Next response headers; csv also sends a Content-Disposition download filenameformat=csv

Pagination: page × limit is capped at 50,000 rows deep — add filters for deeper slices. Sort accepts: statemember_last_namemember_full_namemember_license_issuedmember_license_expiresoffice_name and more (see OpenAPI). Status and member-type vocabularies vary by state — populate filter UIs from /v1/stats.

Response shape

{
  "data": [ { "id": 123, "state": "CA", "member_full_name": "…", … } ],
  "pagination": { "page": 1, "limit": 100, "total": 12345, "total_pages": 124,
                  "has_next": true, "has_prev": false },
  "meta": { "snapshot": "2026-07", "sort": ["state"], "order": "asc",
            "filters_applied": ["state"] }
}

Errors: { "error": { "code": "rate_limited", "message": "…" } } with an appropriate HTTP status — 400 invalid param · 401 unauthorized / key_suspended · 403 scope_denied / history_denied · 429 rate_limited / quota_exceeded / trial_limit · 5xx server.

Playground

Ready — pick an endpoint and hit Send request.
// response will appear here

Quickstart recipes

Active brokers in Texas, newest first:

curl -s "https://api.compcurve.com/v1/licenses?state=TX&member_type=Broker&sort=member_license_issued&order=desc&limit=25" \
  -H "Authorization: Bearer $KEY"

Licenses expiring in the next 90 days (renewal outreach):

curl -s "https://api.compcurve.com/v1/licenses?state=FL&expires_after=2026-07-12&expires_before=2026-10-10&fields=id,member_full_name,office_name,member_license_expires,matched_email&limit=200" \
  -H "Authorization: Bearer $KEY"

Sparse fields for a dashboard (small payloads):

curl -s "https://api.compcurve.com/v1/licenses?state=CA,TX,FL&fields=id,state,member_full_name,member_state_license_number&limit=500" \
  -H "Authorization: Bearer $KEY"

Follow one license month over month (history add-on):

curl -s "https://api.compcurve.com/v1/licenses/history?state=TX&license_number=753285-SA&fields=member_full_name,office_name,member_license_status,member_license_expires" \
  -H "Authorization: Bearer $KEY"
# data.rows → one per snapshot, newest first · data.changes → field-level diffs between months