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.
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.
| Endpoint | Purpose |
|---|---|
GET /v1/health | Liveness + DB reachability (no auth) |
GET /v1/me | Your key's tier and configured rate limits |
GET /v1/usage | Your request counts by day and by endpoint (?days=30) |
GET /v1/snapshots | Available monthly snapshots with row counts |
GET /v1/states | States/provinces + per-state row counts |
GET /v1/stats | Precomputed aggregates: status/type vocabularies, contact coverage, expirations |
GET /v1/licenses | Main query endpoint — filters, sort, pagination, sparse fields |
GET /v1/licenses/:id | Single license by internal id (id is per-snapshot) |
GET /v1/licenses/history | One license across every accessible snapshot + change log (?state=TX&license_number=… or ?id=…) — history add-on |
GET /v1/suggest | Type-ahead: distinct prefix matches (?field=city|office|last_name&q=kel) |
POST /mcp | Remote MCP server (JSON-RPC over HTTP) — the same API as tools for Claude / Cursor / agents. Setup → |
| Param | Behavior | Example |
|---|---|---|
snapshot | Monthly 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 |
state | Exact state/province code; comma-separable. e.g. CA,TX | state=CA,TX |
country | US or CA | country=US |
last_name | Case-insensitive prefix match | last_name=smith |
office_name | Case-insensitive prefix match (use /v1/suggest for autocomplete) | office_name=keller |
license_number | Exact license number | license_number=00007012 |
license_status | Exact status (vocab varies by state — see /v1/stats) | license_status=Active |
member_type | Exact member type | member_type=Broker |
city | Exact city | city=Austin |
postal_code | Exact postal code (alias: zip) | postal_code=94563 |
issued_after | ISO date: license issued on/after | issued_after=2024-01-01 |
issued_before | ISO date: license issued on/before | issued_before=2026-01-01 |
expires_after | ISO date: license expires on/after | expires_after=2026-08-01 |
expires_before | ISO date: license expires on/before | expires_before=2026-12-31 |
first_issued_after | ISO date | first_issued_after=2010-01-01 |
first_issued_before | ISO date | first_issued_before=2020-01-01 |
sort | Comma-separated sort columns (whitelisted) | sort=member_last_name,member_first_name |
order | asc | desc | order=desc |
page | 1-based page number | page=2 |
limit | Rows per page (default 100, max 1000) | limit=500 |
fields | Sparse fieldset: comma-separated column names | fields=id,state,member_full_name |
count | Set false to skip the total-count query — faster; total/total_pages become null and has_next is inferred from page fill | count=false |
format | Response 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 filename | format=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.
{
"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.
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