API reference
Base URL: https://commonelements.com/api/v1
Find the right endpoint
| You are starting from | Use |
|---|---|
| A name from your own system to reconcile | /associations/match |
| A property address | /associations/by-address |
| Browsing or filtering a state | /associations/lookup |
| Watching for changes | /changes |
| Pulling a whole dataset (Growth and above) | /export/{resource} |
Authentication
All API requests must include an Authorization header with a bearer token. Generate an API key from your account settings.
Authorization: Bearer ce_live_your_key_hereKeys are prefixed with ce_live_ for production and ce_test_ for sandbox environments. Never expose keys in client-side code or commit them to version control.
Spec, sandbox and status
Four endpoints exist so you never have to take this page’s word for anything. None of them consumes quota, and the first three need no key at all.
Generated from the same definitions this page renders, so it cannot drift from the reference. Import it into Postman or an API gateway, or generate a client from it. Add ?format=yaml for YAML.
A published test key and a small fixed dataset at /api/v1/meta/sandbox. Build and test a client before you buy anything, and provoke a 429 or a 403 on demand to check your retry path.
Live availability at /api/v1/meta/status, plus the written compatibility and deprecation commitments procurement asks for.
Every resource and every field: type, source, how often it is actually populated, how many rows stand behind it, and the refresh cadence of the feed. Measured at request time, never typed into a page.
# Import the spec, then hit the sandbox with the published test key.
curl https://commonelements.com/api/v1/openapi -o common-elements.json
curl "https://commonelements.com/api/v1/meta/sandbox/associations" \
-H "Authorization: Bearer ce_test_sandbox"Rate limits
Limits are enforced per API key against a calendar month, UTC: the counter resets on the first request on or after the first of the next month, not on a rolling window from when the key was created. When you exceed your limit, requests return 429 Too Many Requests with quota_exceeded until the reset. There is no overage charge and no automatic top-up.
| Tier | Requests/month |
|---|---|
| Free | 250 |
| Builder | 10,000 |
| Growth | 50,000 |
| Scale | 250,000 |
| Enterprise | Unlimited |
Track your remaining quota on the API keys settings page; a request over quota returns 429 with { "error": "quota_exceeded" }.
Monitoring your usage
Your API keys settings page is the self-serve way to see where you stand. Every key you hold shows its current usage as a running count, for example 742 / 10,000 requests this month, next to its tier and status. Check it before a scheduled job or bulk import to confirm you have room, rather than finding out from a 429.
Your integration can ask the same question itself. GET /api/v1/meta/usage returns requests used and remaining, the reset date, a per-day and per-endpoint breakdown, and your most recent errors — and it does not consume quota, so it still answers when the key is already over its limit. That is the call to make before starting a batch.
curl "https://commonelements.com/api/v1/meta/usage?days=7" \
-H "Authorization: Bearer ce_live_your_key_here"It also reports the plan your organization’s subscription entitles you to, resolved from billing at request time, next to the plan the key was created at. If those two ever disagree, plan.mismatch says so and what to do about it.
A quota-exhausted request returns a 429 with this body:
{
"ok": false,
"error": "quota_exceeded",
"message": "Monthly request quota exceeded."
}Monthly quota resets at the start of the next calendar month; there is no partial reset and no automatic overage charge. If you are building an integration that calls the API on a schedule, check your usage on the API keys page before a large batch, and back off with an increasing delay after a 429 rather than retrying immediately in a tight loop.
Endpoints
Every endpoint below is live, and this list is the same one /api/v1/openapi is generated from — a reader and a generated client cannot see different APIs. A test walks app/api/v1 on every run and fails when a route exists that this page does not describe, so nothing ships here undocumented. If something below does not match what the API returns, the API is right and this page is a bug worth reporting.
Dataset catalog
What the platform holds, and what it holds for one association. Start here: the catalog names every resource, the plan it needs, and the caveat that stops an unmatched jurisdiction reading as a clean record.
GET/api/v1/datasets
The resource catalog: every published resource and every source behind it, with display name, buyer summary, provenance, state footprint, coverage basis and caveat, the plan each needs, and whether your key can read it. Resources above your plan are listed deliberately — an absence you cannot see is indistinguishable from a clean record.
Scope: associations
Response fields
| Parameter | Type | Description |
|---|---|---|
| resource_key | string | Stable key. The `source` and path segment both derive from it. |
| display_name | string | Resource name, for display. |
| buyer_summary | string | What this resource gives you, in one sentence. |
| provenance_label | string | Where the underlying records come from. |
| min_tier | string | Plan required to read rows from this resource. |
| has_access | boolean | Whether the key on this request can read its rows. |
| coverage_basis | string | What kind of coverage number this resource may be described with. |
| coverage_note | string | The caveat that says whether a zero means 'nothing happened' or 'not matched yet'. |
Example request
curl "https://commonelements.com/api/v1/datasets" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"resource_key": "permits",
"display_name": "Building permits",
"buyer_summary": "Municipal permits recorded against the association.",
"provenance_label": "Municipal permit systems",
"min_tier": "builder",
"has_access": true,
"coverage_basis": "association_share",
"coverage_note": "Matched in the jurisdictions listed; a zero outside them means not matched, not none."
}
]
}GET/api/v1/associations/{id}/datasets
What the platform holds for one association across every resource, in one round trip: record counts, how many of each resource's sources could be measured, whether your key can read them, and the coverage caveat. The call to make before deciding which resource endpoints are worth a request.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| resource_key | string | Resource this row describes. |
| record_count | number | Records held for this association in this resource. |
| sources_measured | number | How many of the resource's sources could be counted. |
| has_access | boolean | Whether your key can read the rows behind the count. |
| coverage_note | string | Whether a zero here means 'nothing happened' or 'this jurisdiction is not matched yet'. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/datasets" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{ "resource_key": "permits", "record_count": 14, "sources_measured": 1, "has_access": true, "coverage_note": "…" },
{ "resource_key": "violations", "record_count": 0, "sources_measured": 1, "has_access": false, "coverage_note": "…" }
]
}- Counts are returned for resources above your plan on purpose. The size of what is behind the gate is the offer.
Change feed
What changed, and when. The rest of the API describes the association graph as it stands today; this describes it moving.
GET/api/v1/changes
The trigger-event feed: board turnover, president changes, management-company moves, self-managed transitions, registration status and name changes, and license events across the association graph. This is the programmatic form of the change feed on data.commonelements.com, and the endpoint to poll when you want to act on a community the week something changed rather than re-download a static list.
Scope: changes or associationsYour plan sets the row cap, and a maximum lookback window (table below). Free keys: up to 10 rows per request; paid tiers raise the cap.
| Plan | Rows per request | Maximum lookback |
|---|---|---|
| Free | 50 | 30 days |
| Builder | 1,000 | 180 days |
| Growth | 5,000 | 365 days |
| Scale | 25,000 | 3 years |
| Enterprise | 100,000 | 10 years |
Change history records differences observed in public records. An observation date may differ from the date a change took effect. Available history varies by source. Your plan's lookback window limits the recorded events you can access; it does not guarantee that much history is available.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| kind | string | Comma-separated list of change kinds to include. Any of: board_turnover, board_president_changed, officer_added, officer_removed, officer_title_changed, management_company_changed, management_company_added, management_company_removed, self_managed_transition, entity_status_changed, entity_name_changed, license_added, license_lapsed. Omit for all kinds. |
| state | string | Comma-separated two-letter state codes, e.g. "FL" or "FL,GA,TX". Case-insensitive. |
| county | string | Single county name, matched exactly as stored (e.g. "Miami-Dade"). |
| subtype | string | One of "hoa", "condo", "coop". |
| since | string | Earliest observation date, YYYY-MM-DD. Clamped to your plan lookback window; an earlier date does not widen it. Available change history varies by source. Observation dates may differ from when changes took effect, and your plan's lookback window does not guarantee that much history. |
| until | string | Latest observation date, YYYY-MM-DD. |
| min_units | number | Only associations with at least this many units. |
| max_units | number | Only associations with at most this many units. |
| min_magnitude | number | Minimum change magnitude, 0 to 1. Higher means a larger share of the board or record changed at once. |
| limit | number | Rows to return, 1 to 1000 (default 100). Clamped to your plan row cap. |
| offset | number | Pagination offset (default 0). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Stable id for this change event. |
| organization_id | uuid | The association the change was observed on. |
| organization_name | string | Association legal name. |
| directory_slug | string | null | Kebab-case slug for the public directory page. |
| subtype | string | null | "hoa", "condo", or "coop". |
| city | string | null | City on the association record. |
| county | string | null | County on the association record. |
| state | string | null | Two-letter state code. |
| unit_count | number | null | Units or lots in the community, where known. |
| change_kind | string | One of the 13 kinds listed above. |
| observed_on | date | Date the change was observed in the source record. |
| magnitude | number | null | Relative size of the change, 0 to 1. |
| detail | object | Person-free summary of what changed. Null keys are stripped, so a given event carries only the relevant subset of: seats_affected, titles_affected, board_size, previous_manager, new_manager, previous_status, new_status, previous_name, new_name. |
Example request
curl "https://commonelements.com/api/v1/changes?kind=management_company_changed,board_turnover&state=FL&since=2026-06-01&min_units=100&limit=50" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "3f6b1c2e-7a41-4d0b-9f52-8c1e0a4d7b93",
"organization_id": "0b9d4f21-3c88-4a17-b5e2-6d7f109c4a55",
"organization_name": "PELICAN BAY COMMUNITY ASSOCIATION, INC.",
"directory_slug": "pelican-bay-community-association",
"subtype": "hoa",
"city": "Naples",
"county": "Collier",
"state": "FL",
"unit_count": 742,
"change_kind": "management_company_changed",
"observed_on": "2026-07-18",
"magnitude": 0.8,
"detail": {
"previous_manager": "GULF COAST PROPERTY MANAGEMENT, INC.",
"new_manager": "SUNSTATE ASSOCIATION MANAGEMENT, LLC"
}
},
{
"id": "b1244a90-55f7-4e6c-8d31-2a0f7c93e118",
"organization_id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af",
"organization_name": "HARBOUR RIDGE CONDOMINIUM ASSOCIATION, INC.",
"directory_slug": "harbour-ridge-condominium-association",
"subtype": "condo",
"city": "Fort Lauderdale",
"county": "Broward",
"state": "FL",
"unit_count": 214,
"change_kind": "board_turnover",
"observed_on": "2026-07-02",
"magnitude": 0.6,
"detail": {
"seats_affected": 3,
"board_size": 5,
"titles_affected": ["president", "director"]
}
}
],
"pagination": {
"total": 1284,
"limit": 50,
"offset": 0,
"returned": 50
},
"note": "Row cap and lookback window are set by your plan tier. Person-level identity is never included; officer changes are reported as counts and titles."
}- No officer names, ever. The feed reads a person-stripped view by construction: officer changes come back as counts and canonical titles, and management changes as firm names. There is no parameter that widens this.
- "total" in the pagination block is the count of matching rows inside your plan window, not the count in the whole dataset.
- Two caps stack and the tighter one wins: the per-request free-plan row cap of 10, and your plan row cap in the table above. A free key therefore receives up to 10 rows per request within a 30-day window. When a response was shortened by the free cap it also carries a "row_cap" field in the envelope.
GET/api/v1/changes/summary
Counts by change kind over your window: how many events, across how many distinct associations, in how many states. The cheap call for a dashboard tile or a scheduled digest, and the one to run first when you are sizing the dataset before committing to a plan.
Scope: changes or associationsAvailable on every plan, uncapped: this returns one aggregate row per change kind, not a row listing. The lookback window is set by your plan, the same window /api/v1/changes uses.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| since | string | Earliest observation date, YYYY-MM-DD. Clamped to your plan lookback window. Available change history varies by source. Observation dates may differ from when changes took effect, and your plan's lookback window does not guarantee that much history. |
| state | string | Comma-separated two-letter state codes. Omit for all states. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| change_kind | string | One of the 13 change kinds. |
| event_count | number | Events of this kind in the window. |
| org_count | number | Distinct associations with at least one such event. |
| states_covered | number | Distinct states represented. |
Example request
curl "https://commonelements.com/api/v1/changes/summary?state=FL&since=2026-05-01" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"change_kind": "board_turnover",
"event_count": 4182,
"org_count": 3907,
"states_covered": 1
},
{
"change_kind": "management_company_changed",
"event_count": 611,
"org_count": 598,
"states_covered": 1
}
]
}Associations
GET/api/v1/associations/lookup
Browse and filter community associations by state, county, subtype or registration number. For a name, `q` is a literal SUBSTRING filter: it matches only when your text appears verbatim in the filed corporate name, so "SUNSET RIDGE CONDO ASSN" will not find "Sunset Ridge Condominium Association, Inc.". If you are reconciling names from your own system, use /api/v1/associations/match instead. If `q` is a street address, the request is resolved against linked parcels (same path as /associations/by-address) rather than as a name substring. Use lookup when you hold an exact key: a registration number, or a real substring of the filed name.
Scope: associationsFree keys: up to 10 rows per request; paid tiers raise the cap.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| q | string | Exact substring of the filed corporate name, case-insensitive. Not fuzzy; for messy names use /associations/match. A street address (with ZIP) is resolved as an address, not as a name. |
| state | string | Two-letter state filter, e.g. "FL". |
| subtype | string | One of "hoa", "condo", "coop". |
| county | string | County filter, case-insensitive, e.g. "Broward" or "Pima". |
| registration_number | string | Exact state registry corp/document number (Sunbiz document number, ACC entity id, ...), case-insensitive. Returned as external_document_number. |
| limit | number | Max results to return (default 20, max 100; free tier is clamped lower). |
| offset | number | Pagination offset (default 0). |
Example request
curl "https://commonelements.com/api/v1/associations/lookup?q=Pelican+Bay&state=FL" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "0d3f6c2e-...",
"name": "PELICAN BAY COMMUNITY ASSOCIATION, INC.",
"display_name": "Pelican Bay Community Association",
"state": "FL",
"subtype": "hoa",
"unit_count": 742,
"address": "801 Laurel Oak Dr",
"city": "Naples",
"zip": "34108",
"external_document_number": "N04000001234",
"is_claimed": false,
"created_at": "2026-05-02T14:11:09.000Z"
}
],
"total": 3,
"limit": 20,
"offset": 0
}GET/api/v1/associations/match
Fuzzy name matching for entity resolution: given a messy association name from your own system, get back the best-matching Common Elements records with a similarity score. Use this to reconcile a book of business against the directory, where an exact-string lookup would miss "Pelican Bay Comm. Assn." against "PELICAN BAY COMMUNITY ASSOCIATION, INC.". If `q` is a street address (house number, city, state, ZIP), the request is resolved against linked parcels instead of names, the same path as /associations/by-address. Name-scoring an address attaches the wrong community.
Scope: associations
Query parameters
| Parameter | Type | Description |
|---|---|---|
| q* | string | The name to match, minimum 3 characters. A street address (with ZIP) is resolved as an address, not as a name. |
| state* | string | Two-letter state code. Required; matching is scoped per state. |
| county | string | Optional county filter, case-insensitive. |
| min_similarity | number | Trigram similarity floor, 0.1 to 0.99 (default 0.25). Raise it for stricter matches. |
| limit | number | Max candidates to return, 1 to 10 (default 5). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Common Elements id for the matched record. |
| canonical_name | string | Normalized association name. |
| sim | number | Trigram similarity against your query, 0 to 1. Rows come back ranked. Parcel hits use 1 (exact) or 0.99 (building) so a client that thresholds on sim still keeps a real address match. |
| resolved_via | "name" | "address" | "legal_description" | How this request was resolved. Address-shaped q never falls through to name matching. |
| matched_address / match_confidence | string | null | Present when resolved_via is address: the indexed parcel and exact or building. |
| unit_count | number | null | Present when resolved_via is address. Units in the association, where known and above our confidence floor; null does not mean zero. |
| county / state | string | null | Location on the matched record. |
| sunbiz_corp_id | string | null | State corporate registry id, where known. |
| registration_status | string | null | Registry status on the record. |
| registered_at / last_filing_at | timestamp | null | Registry formation and most recent filing timestamps. |
| cam_firm_name | string | null | Management firm of record, where known. |
| cam_license_number / cam_license_status | string | null | License of the management firm of record. |
| association_type | string | null | Association type on the record. |
| sb_4d_applicable | boolean | null | Whether Florida SB 4-D structural requirements are recorded as applicable. |
| sb_4d_inspection_status / sb_4d_last_inspection_at | string | timestamp | null | Recorded SB 4-D inspection state. |
| data_provenance | object | null | Per-field source attribution for the record. |
| last_refreshed_at | timestamp | null | When the record was last refreshed from source. |
| ai_summary / ai_summary_generated_at | string | timestamp | null | Generated plain-language summary, where one exists. |
Example request
curl "https://commonelements.com/api/v1/associations/match?q=Pelican%20Bay%20Comm%20Assn&state=FL&min_similarity=0.3" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "0b9d4f21-3c88-4a17-b5e2-6d7f109c4a55",
"canonical_name": "PELICAN BAY COMMUNITY ASSOCIATION, INC.",
"county": "Collier",
"state": "FL",
"sunbiz_corp_id": "N04000001234",
"registration_status": "ACTIVE",
"cam_firm_name": "GULF COAST PROPERTY MANAGEMENT, INC.",
"association_type": "hoa",
"sim": 0.62
}
],
"query": "Pelican Bay Comm Assn",
"state": "FL",
"county": null
}- Similarity is trigram-based, so word order matters less than shared character runs. A score above roughly 0.45 is usually a confident match; between 0.25 and 0.45, review before merging.
- If q looks like a street address, the response includes resolved_via: "address" and match_confidence of exact or building. Those rows are parcel links, not name guesses. An empty list means we do not have that address linked yet. Address-shaped q never falls through to name matching.
GET/api/v1/associations/by-address
Resolve a property address to the association that governs it. Dedicated parcel-backed contract for a book of property addresses. /associations/match and /lookup also route a street-shaped q through this same resolve path so an address is never scored as a name.
Scope: associations
Query parameters
| Parameter | Type | Description |
|---|---|---|
| address* | string | Street address, minimum 3 characters. Unit numbers are fine — see match_confidence below. |
| zip* | string | 5-digit ZIP or ZIP+4. A 4-digit ZIP (leading zero dropped by Excel) is padded. Matching is scoped to the ZIP. |
| limit | number | Max candidates to return, 1 to 5 (default 3). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| organization_id | uuid | Common Elements id for the matched association. |
| association_name | string | Name of the matched association. |
| matched_address | string | The indexed parcel address this query matched, for your own audit trail. |
| zip5 / state | string | Location on the matched record. |
| source_table | string | Which parcel source produced the link (internal provenance, not stable API surface). |
| match_confidence | "exact" | "building" | "exact" is a normalized address match. "building" means your address included a unit and the indexed parcel is the building it sits in — the common shape for a condo, where our source data is building-level. |
| unit_count | number | null | Units in the association, where known and above our confidence floor. Null does not mean zero — it means we do not have a trustworthy count for this one yet. |
Example request
curl "https://commonelements.com/api/v1/associations/by-address?address=2290%20SE%205th%20Court%2C%20Unit%204&zip=33033" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"organization_id": "0572f345-0763-4eed-810e-72a25aea4a50",
"association_name": "KEYS GATE CONDO NO. 2",
"matched_address": "2290 SE 5 CT",
"zip5": "33033",
"state": "FL",
"source_table": "association_parcels",
"match_confidence": "building",
"unit_count": 42
}
]
}- Coverage is real but not complete everywhere: this only returns a hit where a parcel has already been deterministically linked to an association. An empty result includes a hint pointing at /associations/match as a name-based fallback. It does not mean the property has no association, only that we do not have the link yet.
- Nothing here is a guess made at request time. A result is always a parcel a matcher already linked to an organization, never a fuzzy score computed on the fly — which is what makes /match the wrong tool for this and this the wrong tool for a bare name.
GET/api/v1/associations/nearby
Find associations within a radius of a coordinate, sorted nearest first. Built for "what communities are around this property" workflows: territory planning, route density for a service vendor, or comparable-community selection.
Scope: associationsFree keys: up to 10 rows per request; paid tiers raise the cap.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| lat* | number | Latitude, -90 to 90. |
| lng* | number | Longitude, -180 to 180. |
| radius_km | number | Search radius in kilometres, 0.1 to 50 (default 2). |
| subtype | string | One of "hoa", "condo", "coop". |
| limit | number | Max results, 1 to 50 (default 20). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Association id. |
| name | string | Association legal name. |
| subtype | string | null | "hoa", "condo", or "coop". |
| city / county / state / zip | string | null | Location on the association record. |
| lat / lng | number | Coordinates the distance was computed from. |
| unit_count | number | null | Units or lots, where known. |
| external_document_number | string | null | State registration document number. |
| distance_m | number | Distance from your centre point in metres, rounded. |
Example request
curl "https://commonelements.com/api/v1/associations/nearby?lat=26.2379&lng=-81.8095&radius_km=5&subtype=condo&limit=10" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af",
"name": "HARBOUR RIDGE CONDOMINIUM ASSOCIATION, INC.",
"subtype": "condo",
"city": "Naples",
"county": "Collier",
"state": "FL",
"zip": "34108",
"lat": 26.2401,
"lng": -81.8062,
"unit_count": 214,
"external_document_number": "N04000001234",
"distance_m": 412
}
],
"center": { "lat": 26.2379, "lng": -81.8095 },
"radius_km": 5
}- Only associations with recorded coordinates are searchable here. Coverage of geocoded records varies by state, so an empty result is not proof no association exists at that location.
GET/api/v1/associations/{id}/risk
Retrieve flood zone, reserve-study health, and geographic risk signals for a specific association. Useful for underwriting, due diligence, and loan origination workflows.
Scope: risk
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string | Association ID from the lookup endpoint. |
Example request
curl "https://commonelements.com/api/v1/associations/0b9d4f21-3c88-4a17-b5e2-6d7f109c4a55/risk" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"association_id": "0b9d4f21-3c88-4a17-b5e2-6d7f109c4a55",
"flood_zone": "AE",
"fema_firm_panel": "12021C0454H",
"reserve_health": {
"funded_percent": 62,
"study_year": 2023,
"next_study_due": 2028
},
"risk_signals": [
{ "type": "coastal_proximity", "value": "0.8mi", "severity": "medium" }
],
"data_as_of": "2026-01-15"
}GET/api/v1/associations/{id}/building-safety
Everything on public record about an association’s physical buildings, joined into one call: Florida SIRS filings, county milestone/recertification rolls, elevator certificates, pool inspections, parcel building characteristics, and HUD FHA condo approval. The structural sibling of the risk endpoint, which reports county-level FEMA hazard instead.
Scope: risk
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string | Association UUID. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| sirs | object | Structural Integrity Reserve Study filings: on_file, project_count, and the projects array. |
| milestone | object | County recertification roll: status and due of the record with the latest due date, record_count, and every records row so you can apply your own rule. |
| elevators | object | count, delinquent, delinquent_count, earliest_expiry, max_landings, and the certificates array from the FL DBPR elevator safety roll. |
| pools | object | inspection_count, last_inspection_date, last_result, last_violations, and the inspections array from FL DOH. |
| structure | object | max_stories, max_building_height_ft, earliest_year_built, three_plus_story_building (null when no characteristics row exists, not false), and the buildings array. |
| fha | object | project_count, status, status_date, expiration_date, approval_method, and the projects array. |
| layer_counts | object | Row count per layer: sirs, recertifications, elevators, pool_inspections, characteristics, fha_projects. |
| has_data | boolean | False when every layer is empty for this association. |
| source | string | The public-record sources behind this response. |
Example request
curl "https://commonelements.com/api/v1/associations/c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af/building-safety" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"organization_id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af",
"name": "HARBOUR RIDGE CONDOMINIUM ASSOCIATION, INC.",
"state": "FL",
"county": "Broward",
"city": "Fort Lauderdale",
"zip": "33301",
"subtype": "condo",
"unit_count": 214,
"sirs": { "on_file": true, "project_count": 1, "projects": [] },
"milestone": {
"status": "Due",
"due": "2027-12-31",
"record_count": 2,
"records": []
},
"elevators": {
"count": 4,
"delinquent": false,
"delinquent_count": 0,
"earliest_expiry": "2027-03-31",
"max_landings": 12,
"certificates": []
},
"pools": {
"inspection_count": 6,
"last_inspection_date": "2026-05-14",
"last_result": "Satisfactory",
"last_violations": 0,
"inspections": []
},
"structure": {
"max_stories": 12,
"max_building_height_ft": 128,
"earliest_year_built": 1979,
"three_plus_story_building": true,
"buildings": []
},
"fha": {
"project_count": 1,
"status": "Approved",
"status_date": "2025-08-01",
"expiration_date": "2028-08-01",
"approval_method": "HRAP",
"projects": []
},
"layer_counts": {
"sirs": 1,
"recertifications": 2,
"elevators": 4,
"pool_inspections": 6,
"characteristics": 3,
"fha_projects": 1
},
"has_data": true,
"source": "FL DBPR (SIRS, elevator safety), county recertification rolls (Miami-Dade RER, Broward BORA), FL DOH pool inspections, county property appraiser building characteristics, HUD FHA condo approvals",
"note": "Public-record data linked to the association by Common Elements entity resolution. Reference-only; not a structural determination. Coverage varies by county and layer — read layer_counts before treating an absent record as compliance."
}
}- Coverage is uneven by design: county recertification rolls are Miami-Dade and Broward only, SIRS is Florida condo, HUD FHA is national. Branch on has_data and layer_counts. An absent record means nothing was filed with a source we ingest, not that the association is compliant.
- Arrays are truncated at 500 rows per layer. The example above shows the arrays empty for brevity; live responses carry the rows.
- Reference data only, not a structural determination. Confirm anything load-bearing with a licensed engineer.
GET/api/v1/associations/{id}/vendors
The vendors and service providers an association is on record working with, from confirmed relationship edges in the Common Elements graph. Answers "who already services this community" before you bid against them or refer into them.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string | Association UUID. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Vendor organization id. |
| name | string | Vendor legal name. |
| subtype | string | null | Vendor subtype. |
| city / state | string | null | Vendor location. |
| website | string | null | Vendor website. |
| verification_status | string | null | Whether the vendor org is verified on the platform. |
| directory_slug | string | null | Slug for the public vendor directory page. |
| review_count / review_avg_rating | number | null | Platform review volume and average rating. |
| relationship_type | string | null | "under_contract" or "represented_by". This is the edge type behind the row. |
| relationship_status | string | null | Edge status; only active edges are returned. |
| start_date / end_date | date | null | Contract window, where recorded. |
| contract_value | number | null | Contract value, where recorded. |
Example request
curl "https://commonelements.com/api/v1/associations/c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af/vendors" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604",
"name": "COASTAL LANDSCAPE SERVICES, LLC",
"subtype": "landscaping",
"city": "Fort Lauderdale",
"state": "FL",
"website": "https://example.com",
"verification_status": "verified",
"directory_slug": "coastal-landscape-services",
"review_count": 12,
"review_avg_rating": 4.6,
"relationship_type": "under_contract",
"relationship_status": "active",
"start_date": "2025-01-01",
"end_date": null,
"contract_value": 84000
}
],
"association_id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af"
}- Only confirmed, active relationships appear. An empty array means no vendor edge is recorded, not that the association self-performs the work.
GET/api/v1/associations/{id}
The core record for one association: identity, location, registration status, and management-firm-of-record, in one call. The starting point once you have an id from lookup, match, or nearby.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Association id. |
| name | string | Legal name. |
| state / county / city / zip | string | null | Location on the record. |
| subtype | string | null | "hoa", "condo", or "coop". |
| unit_count | number | null | Units or lots, where known. |
| address | string | null | Street address. |
| lat / lng | number | null | Coordinates, where geocoded. |
| website / phone | string | null | Public contact info on the record, where present. |
| is_claimed | boolean | Whether a board member or manager has claimed this record on the platform. |
| registration_status | string | null | State corporate registry status (e.g. "ACTIVE"). |
| external_document_number | string | null | State registration document number. |
| management_firm | string | null | Management company of record, where known. |
| created_at / updated_at | timestamp | Record lifecycle timestamps. |
Example request
curl "https://commonelements.com/api/v1/associations/c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af",
"name": "HARBOUR RIDGE CONDOMINIUM ASSOCIATION, INC.",
"state": "FL",
"county": "Broward",
"subtype": "condo",
"unit_count": 214,
"address": "1500 Harbour Ridge Blvd",
"city": "Fort Lauderdale",
"zip": "33301",
"lat": 26.2401,
"lng": -81.8062,
"website": null,
"phone": null,
"is_claimed": true,
"registration_status": "ACTIVE",
"external_document_number": "N04000001234",
"management_firm": "SUNSTATE ASSOCIATION MANAGEMENT, LLC",
"created_at": "2025-02-11T14:03:00Z",
"updated_at": "2026-07-18T09:22:00Z"
}
}GET/api/v1/associations/{id}/officers
The current board/officer roster on file for an association, from state officer filings. Coverage is strongest in the eight states with published officer rolls. Board-turnover events on the change feed come from diffing successive snapshots of this roster, so they currently exist only for the states that have had more than one snapshot.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| officer_title | string | Title as filed (e.g. "President", "Director"). |
| first_name / last_name | string | Officer name as filed. |
| middle_initial / suffix | string | null | Additional name parts, where present. |
| city / county / state | string | null | Location on the filing, not necessarily the officer's residence. |
| directory_source | string | The state filing source this row came from. |
| source_snapshot_label | string | Which ingested snapshot this row belongs to. |
| is_resolved | boolean | Whether this filing row has been matched to a canonical person record. |
Example request
curl "https://commonelements.com/api/v1/associations/c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af/officers" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"officer_title": "President",
"first_name": "JANE",
"middle_initial": null,
"last_name": "MARTINEZ",
"suffix": null,
"city": "Fort Lauderdale",
"county": "Broward",
"state": "FL",
"directory_source": "fl_sunbiz",
"source_snapshot_label": "2026-07-15",
"is_resolved": true
}
],
"association_id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af"
}- This is the current roster only. For board history over time (who served when, and each turnover as an event), use data.commonelements.com or the change feed's board_turnover / officer_* events.
- An empty array means no officer filing is on record for this association, not necessarily that the board has vacancies.
GET/api/v1/associations/{id}/management
Who manages this association, from two independent sources: the manager-association graph built from state CAM/registration filings (ranked by source priority), and any confirmed management relationship recorded on the platform itself.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| managers | array | Rows from state filings: manager_name, source, priority, and provenance, ranked highest-priority first. |
| confirmed_relationships | array | Platform-confirmed management edges: to_org_id (the management company's org id), relationship_type ("managed_by"), status, start_date, end_date, contract_value. |
Example request
curl "https://commonelements.com/api/v1/associations/c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af/management" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"managers": [
{
"manager_name": "SUNSTATE ASSOCIATION MANAGEMENT, LLC",
"source": "fl_dbpr_cam",
"priority": 3,
"provenance": "DBPR licensee-of-record filing"
}
],
"confirmed_relationships": []
},
"association_id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af"
}- The two arrays can disagree, and that is meaningful: managers reflects the state filing, confirmed_relationships reflects what the platform's own users have confirmed. Treat managers as the source of record when they differ; confirmed_relationships is corroborating, not authoritative.
- Both empty means no manager is on record at all, which for a professionally-managed association usually means self-managed or an unfiled change.
GET/api/v1/associations/{id}/buildings
Building footprint, roof/facade area estimates, floor count, and recorded structural facts (measured stories, year built, FL Ch. 553 milestone relevance) for an association, derived from mapped building outlines and county parcel rolls.
Scope: valuations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| building_count | number | Mapped buildings for this association. |
| total_footprint_sqft / total_footprint_sqm | number | null | Summed footprint area across mapped buildings. |
| primary_building_sqft / avg_footprint_sqm | number | null | Largest building's footprint, and the average across all of them. |
| roof_area_sqft_estimate | number | null | Estimated from footprint; add a pitch multiplier for sloped roofs. |
| facade_area_sqft_estimate | number | null | Perimeter x height estimate. A starting point for painting/waterproofing scope. |
| floors_estimate | number | null | Rough estimate from measured height only. Not a milestone determination. |
| max_height_m | number | null | Measured height, capped ~34m by the underlying source; null when unmeasured. Never a hard stories count. |
| height_confidence | string | null | Confidence label for the height figure. |
| stories | number | null | Recorded stories from the county parcel roll (FL only currently) — measured, not estimated. |
| year_built | number | null | Earliest recorded year built across the association's buildings. |
| milestone_inspection_relevant | boolean | null | True when a recorded building has 3+ stories — the real FL Ch. 553 signal. Reference-only. |
| structural_source / source / attribution | string | null | Where each figure came from. |
Example request
curl "https://commonelements.com/api/v1/associations/c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af/buildings" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"organization_id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af",
"name": "HARBOUR RIDGE CONDOMINIUM ASSOCIATION, INC.",
"state": "FL",
"unit_count": 214,
"building_count": 3,
"total_footprint_sqft": 48210,
"roof_area_sqft_estimate": 48210,
"facade_area_sqft_estimate": 61500,
"floors_estimate": 11,
"max_height_m": 34.5,
"height_confidence": "medium",
"stories": 12,
"year_built": 1979,
"milestone_inspection_relevant": true,
"structural_source": "FL DOR parcel roll (fl_association_characteristics)",
"source": "overture_maps",
"attribution": "Overture Maps building footprints",
"note": "Building footprint data derived from mapped outlines (Overture Maps). Reference-only; not a survey or underwriting-grade valuation."
}
}- Requires the "valuations" scope, not "associations" — the one endpoint in this group that does.
- Footprint coverage is uneven outside FL/NC/MA/NY/WI; a low building_count can mean sparse mapping, not a small property. Recorded structural facts (stories, year_built, milestone_inspection_relevant) are Florida-only today.
- Reference data only. Confirm anything load-bearing with a licensed engineer.
Statutes
GET/api/v1/statutes/search
Full-text search across the community-association statute corpus, ranked by relevance. The endpoint behind the statute search on commonelements.com, available programmatically.
Scope: statutes or associationsFree keys: up to 10 rows per request; paid tiers raise the cap.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| q* | string | Search text, minimum 2 characters. |
| state | string | Two-letter state code to scope results to one jurisdiction. Omit to search every jurisdiction. |
| limit | number | Max results, 1 to 25 (default 10). |
| offset | number | Pagination offset (default 0). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| section_id | uuid | Statute section id, for use with /v1/statutes/sections/{id}. |
| chapter_slug / chapter_short_title / chapter_jurisdiction / chapter_number | string | The chapter this section belongs to. |
| section_number / subsection | string | null | Section numbering as published. |
| section_slug | string | Slug for the public statute page. |
| title / summary | string | null | Section title and plain-language summary. |
| snippet | string | null | Search-result highlight from the matched text. |
| rank | number | Relevance score. Results are pre-sorted by this, highest first. |
Example request
curl "https://commonelements.com/api/v1/statutes/search?q=reserve+study&state=FL" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"query": "reserve study",
"state": "FL",
"data": [
{
"section_id": "8a3f0c1e-2b4d-4e9a-9f0c-1e2b4d4e9a9f",
"chapter_id": "chp_...",
"chapter_slug": "florida-718",
"chapter_short_title": "Condominium Act",
"chapter_jurisdiction": "FL",
"chapter_number": "718",
"section_number": "718.112",
"subsection": "2",
"section_slug": "718-112-bylaws",
"title": "Bylaws; reserve accounts",
"summary": "Requires reserve accounts for capital expenditures and deferred maintenance...",
"snippet": "...the association shall include reserve accounts for capital expenditures and deferred maintenance...",
"rank": 0.87
}
],
"count": 1
}GET/api/v1/statutes/by-state
Browse/enumerate every statute section on file for a state, grouped by chapter — the companion to statutes/search for "show me everything" rather than a keyword match. Filter to one chapter or a tagged topic.
Scope: statutes or associationsFree keys: up to 10 rows per request; paid tiers raise the cap.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| state* | string | Two-letter state code. |
| chapter | string | Limit to one chapter number. |
| topic | string | Limit to sections tagged with this topic. |
| limit | number | Max results, 1 to 200 (default 100). |
| offset | number | Pagination offset (default 0). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Statute section id. |
| chapter_number / chapter_title | string | null | The chapter this section belongs to. |
| section_number / subsection | string | null | Section numbering as published. |
| slug | string | Slug for the public statute page. |
| title / summary | string | null | Section title and plain-language summary. |
| topics | string[] | Tagged topics for this section. |
| citation | string | null | Formatted legal citation, e.g. "Fla. Stat. § 718.112". |
| effective_date | date | null | When this version took effect. |
| source_url | string | null | Link to the official published text. |
Example request
curl "https://commonelements.com/api/v1/statutes/by-state?state=FL&chapter=718" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "8a3f0c1e-2b4d-4e9a-9f0c-1e2b4d4e9a9f",
"chapter_number": "718",
"chapter_title": "Condominium Act",
"section_number": "718.112",
"subsection": "2",
"slug": "718-112-bylaws",
"title": "Bylaws; reserve accounts",
"summary": "Requires reserve accounts for capital expenditures and deferred maintenance...",
"topics": ["reserves", "bylaws"],
"citation": "Fla. Stat. § 718.112",
"effective_date": "2026-07-01",
"source_url": "https://www.leg.state.fl.us/..."
}
],
"state": "FL",
"pagination": { "total": 214, "limit": 100, "offset": 0 }
}GET/api/v1/statutes/sections/{id}
The full text and metadata for one statute section, including its parent chapter and formatted citation. Follow-up call after search or by-state to read the section in full.
Scope: statutes or associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Section id from search or by-state. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| section_id | uuid | Statute section id. |
| section_number / subsection | string | null | Section numbering as published. |
| title / summary | string | null | Section title and plain-language summary. |
| body_text | string | Full text of the section. |
| topics | string[] | Tagged topics for this section. |
| effective_date / source_url | date | string | null | Effective date and link to the official published text. |
| chapter | object | id, slug, jurisdiction, chapter_number, short_title, citation_format for the parent chapter. |
| citation | string | Formatted legal citation for this exact section. |
Example request
curl "https://commonelements.com/api/v1/statutes/sections/8a3f0c1e-2b4d-4e9a-9f0c-1e2b4d4e9a9f" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"section_id": "8a3f0c1e-2b4d-4e9a-9f0c-1e2b4d4e9a9f",
"section_number": "718.112",
"subsection": "2",
"title": "Bylaws; reserve accounts",
"summary": "Requires reserve accounts for capital expenditures and deferred maintenance...",
"body_text": "(2) BYLAWS. (a) The original bylaws of the association...",
"topics": ["reserves", "bylaws"],
"effective_date": "2026-07-01",
"source_url": "https://www.leg.state.fl.us/...",
"chapter": {
"id": "chp_...",
"slug": "florida-718",
"jurisdiction": "FL",
"chapter_number": "718",
"short_title": "Condominium Act",
"citation_format": "Fla. Stat. § {section}"
},
"citation": "Fla. Stat. § 718.112(2)"
}
}Vendors
GET/api/v1/vendors
Search the public vendor directory: verified vendors only, ranked by review rating. Filter by name/description text, state (home or served), or service category.
Scope: vendors.readFree keys: up to 10 rows per request; paid tiers raise the cap.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| q | string | Free-text search over name and description. |
| state | string | Two-letter state code. Matches either the vendor's home state or a state it serves. |
| category | string | A vendor-category slug, matched against the vendor's self-tagged service categories. |
| limit | number | Max results per page. Free keys are capped at 10; paid tiers get a higher cap. |
| offset | number | Pagination offset (default 0). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Vendor organization id. |
| name | string | Vendor legal name. |
| subtype | string | null | Vendor category subtype. |
| city / state / zip | string | null | Vendor location. |
| website | string | null | Vendor website. |
| service_states | string[] | States the vendor reports serving. |
| directory_slug | string | null | Slug for the public vendor directory page. |
| review_count / review_avg_rating | number | null | Platform review volume and average rating. Results are sorted by rating, highest first. |
| description | string | null | Vendor-authored description. |
| service_categories / service_counties | string[] | Vendor-self-asserted service scope. |
| license_number / insurance_carrier | string | null | Vendor-self-asserted credentials. Not independently verified at this endpoint — see /v1/vendors/{id} for the verified trust profile. |
Example request
curl "https://commonelements.com/api/v1/vendors?state=FL&category=roofing" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604",
"name": "COASTAL ROOFING SOLUTIONS, LLC",
"subtype": "roofing",
"city": "Fort Lauderdale",
"state": "FL",
"zip": "33301",
"website": "https://example.com",
"service_states": ["FL"],
"directory_slug": "coastal-roofing-solutions",
"review_count": 24,
"review_avg_rating": 4.8,
"description": "Licensed commercial and residential roofing serving South Florida HOAs and condos.",
"service_categories": ["roofing"],
"service_counties": ["Broward", "Miami-Dade"],
"license_number": "CCC1234567",
"insurance_carrier": null
}
],
"total": 1,
"limit": 10,
"offset": 0
}- Only verified vendors are listed. Coverage grows as vendors complete verification — see the note this endpoint returns on an empty result for the current count.
GET/api/v1/vendors/{id}
The full public profile for one verified vendor: identity, self-reported service offerings, review summary, and the neutral, independently-sourced trust profile (workers' comp status, professional licenses, enforcement history) pulled from public records.
Scope: vendors.read
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Vendor organization id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id / name / subtype / city / state / zip / website | string | null | Vendor identity and location. |
| verification_status | string | Always "verified" for a row this endpoint returns. |
| service_states | string[] | States the vendor reports serving. |
| review_count / review_avg_rating | number | null | Platform review summary. |
| description / license_number / insurance_carrier / team_size / booth_tagline | string | null | Vendor-self-asserted display fields. |
| services_offered / certifications / service_categories / service_counties | string[] | Vendor-self-asserted service scope and credentials. |
| service_offerings | array | Published offering posts: id, title, body, category_slugs, service_states, service_counties, pinned, published_at. |
| trust_profile | object | null | Independently-sourced, public-record credential facts (FL workers'-comp status, professional licenses, enforcement count). Null when the vendor has no confirmed public-record match — this is the verified boundary, distinct from the self-asserted fields above. |
| created_at | timestamp | When the vendor record was created. |
Example request
curl "https://commonelements.com/api/v1/vendors/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"id": "9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604",
"name": "COASTAL ROOFING SOLUTIONS, LLC",
"subtype": "roofing",
"city": "Fort Lauderdale",
"state": "FL",
"zip": "33301",
"website": "https://example.com",
"verification_status": "verified",
"service_states": ["FL"],
"directory_slug": "coastal-roofing-solutions",
"review_count": 24,
"review_avg_rating": 4.8,
"follower_count": 6,
"description": "Licensed commercial and residential roofing serving South Florida HOAs and condos.",
"service_categories": ["roofing"],
"service_counties": ["Broward", "Miami-Dade"],
"license_number": "CCC1234567",
"insurance_carrier": null,
"year_established": 2011,
"team_size": "11-50",
"booth_tagline": "24/7 emergency roof response for South Florida associations.",
"services_offered": ["Roof replacement", "Storm damage repair"],
"certifications": ["GAF Master Elite"],
"service_offerings": [],
"trust_profile": {
"workers_comp_status": "active",
"licenses": [{ "type": "CCC", "number": "CCC1234567", "status": "active" }],
"enforcement_count": 0
},
"created_at": "2025-06-01T00:00:00Z"
}
}- Never returns private contact data, street address lines, phone, or email. That data does not exist on this endpoint at all, not merely hidden.
- Distinguish self-asserted from verified: description/services_offered/certifications/license_number are what the vendor states about itself; trust_profile is what public records independently confirm.
GET/api/v1/vendors/{id}/reviews
Published reviews for a vendor, newest first. Every review is tied to a completed RFP or proposal, so each one is a verified-buyer review, not an open review anyone can post.
Scope: vendors
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Vendor organization id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Max results, 1 to 100 (default 25). |
| offset | number | Pagination offset (default 0). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Review id. |
| rating | number | 1 to 5. |
| body | string | Review text. |
| created_at / updated_at | timestamp | Review lifecycle timestamps. |
Example request
curl "https://commonelements.com/api/v1/vendors/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/reviews" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "f1a2b3c4-5d6e-4f70-8a91-2b3c4d5e6f70",
"rating": 5,
"body": "Responsive and finished ahead of schedule after the storm.",
"created_at": "2026-06-02T00:00:00Z",
"updated_at": "2026-06-02T00:00:00Z"
}
],
"vendor_id": "9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604",
"total": 1,
"limit": 25,
"offset": 0
}- Reviewer identity is never included, by design — the reviewing association is withheld to keep the projection neutral.
Professionals and licenses
GET/api/v1/licenses/verify
Verify a professional license against the state board roll by license number, or by name when you do not have the number. Returns the raw status and expiry plus two derived flags, because a status that reads "current" can still be past its expiry date.
Scope: licenses
Query parameters
| Parameter | Type | Description |
|---|---|---|
| license_number | string | Exact license number. Provide this or name. |
| name | string | Licensee name, substring match. Provide this or license_number. |
| state* | string | Two-letter state code. |
| license_type | string | Substring filter on license type, e.g. "CAM". |
| limit | number | Max results, 1 to 25 (default 10). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| license_number | string | License number as issued. |
| license_type / license_type_desc | string | null | License class and its description. |
| name / dba | string | null | Licensee name and trade name. |
| status | string | null | Board status verbatim from the source roll. |
| issue_date / expiry_date | date | null | License dates verbatim from the source roll. |
| city / county | string | null | Address of record. |
| board | string | null | Issuing board. |
| organization_id | uuid | null | Linked Common Elements org, when the licensee resolves to one. |
| is_expired | boolean | True when expiry_date is in the past. |
| is_active | boolean | The trust signal to branch on: status reads current/active/valid/clear AND the license is not past expiry. |
Example request
curl "https://commonelements.com/api/v1/licenses/verify?license_number=CAM12345&state=FL" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"license_number": "CAM12345",
"license_type": "CAM",
"license_type_desc": "Community Association Manager",
"name": "SAMPLE LICENSEE",
"dba": null,
"status": "Current",
"issue_date": "2019-04-02",
"expiry_date": "2027-09-30",
"city": "Naples",
"county": "Collier",
"board": "Regulatory Council of Community Association Managers",
"organization_id": null,
"is_expired": false,
"is_active": true
}
],
"state": "FL"
}- Branch on is_active, not on status. A board roll can carry a "Current" status on a license whose expiry date has already passed.
GET/api/v1/professionals/search
Search the licensed professional graph: community association managers, contractors, engineers, and the firms they work under, from state licensing board rolls. Filter by name, state, license type, board, or status.
Scope: professionalsFree keys: up to 10 rows per request; paid tiers raise the cap.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| q | string | Licensee name, substring match. Minimum 2 characters. |
| state | string | Two-letter state code. |
| license_type | string | Exact license type, e.g. "CAM". |
| board | string | Exact issuing board name. |
| status | string | Exact board status. |
| limit | number | Rows to return, 1 to 100 (default 25). |
| offset | number | Pagination offset (default 0). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | License record id. Pass this to the detail endpoints below. |
| state / board | string | Issuing jurisdiction and board. |
| license_number / license_type / license_type_desc | string | null | License identity. |
| name / dba | string | null | Licensee name and trade name. |
| status | string | null | Board status verbatim. |
| issue_date / expiry_date | date | null | License dates verbatim. |
| is_expired | boolean | True when expiry_date is in the past. |
| city / county / zip | string | null | Address of record. |
| organization_id | uuid | null | Linked Common Elements org, when one is resolved. |
Example request
curl "https://commonelements.com/api/v1/professionals/search?state=FL&license_type=CAM&q=coastal&limit=25" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "5e3b8c17-2af9-4d60-9a11-77c04e5b8d32",
"state": "FL",
"board": "Regulatory Council of Community Association Managers",
"license_number": "CAM12345",
"license_type": "CAM",
"license_type_desc": "Community Association Manager",
"name": "COASTAL ASSOCIATION MANAGEMENT, LLC",
"dba": null,
"status": "Current",
"issue_date": "2019-04-02",
"expiry_date": "2027-09-30",
"is_expired": false,
"city": "Naples",
"county": "Collier",
"zip": "34108",
"organization_id": "7d1e2a90-6b4c-4f31-a8d5-9c0f3e7b1246"
}
],
"total": 37,
"limit": 25,
"offset": 0
}- At least one of q, state, license_type, or board is required. The roll is multi-million rows and cannot be paged unfiltered. Omitting all four returns a 400.
GET/api/v1/professionals/{id}
The full single-record projection for one licensed professional or firm, including the city/county/zip of record and the linked Common Elements organization. The street address is not returned: a licence with no firm and no d/b/a is an individual, and that address is overwhelmingly a home.
Scope: professionals
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string | License record UUID, from the search endpoint. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | License record id. |
| state / board | string | Issuing jurisdiction and board. |
| license_number / license_type / license_type_desc | string | null | License identity. |
| name / dba | string | null | Licensee name and trade name. |
| status | string | null | Board status verbatim. |
| issue_date / expiry_date | date | null | License dates verbatim. |
| is_expired | boolean | True when expiry_date is in the past. |
| city / county / zip | string | null | Address of record, to locality level. The street line is never returned. |
| organization_id | uuid | null | Linked Common Elements org, when one is resolved. |
| created_at | timestamp | When the record entered Common Elements. |
Example request
curl "https://commonelements.com/api/v1/professionals/5e3b8c17-2af9-4d60-9a11-77c04e5b8d32" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"id": "5e3b8c17-2af9-4d60-9a11-77c04e5b8d32",
"state": "FL",
"board": "Regulatory Council of Community Association Managers",
"license_number": "CAM12345",
"license_type": "CAM",
"license_type_desc": "Community Association Manager",
"name": "COASTAL ASSOCIATION MANAGEMENT, LLC",
"dba": null,
"status": "Current",
"issue_date": "2019-04-02",
"expiry_date": "2027-09-30",
"is_expired": false,
"city": "Naples",
"county": "Collier",
"zip": "34108",
"organization_id": "7d1e2a90-6b4c-4f31-a8d5-9c0f3e7b1246",
"created_at": "2026-06-06T08:00:00.000Z"
}
}- Business address of record only. No personal email or phone is returned by any Common Elements endpoint.
GET/api/v1/professionals/{id}/associations
The communities a professional or firm is on record serving: the manager-to-portfolio view. Merges confirmed relationship edges with name-matched rows from the public management registry, de-duplicated, with the provenance of each row.
Scope: professionals
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | string | License record UUID, from the search endpoint. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Association organization id. |
| name | string | Association legal name. |
| subtype | string | null | "hoa", "condo", or "coop". |
| city / state | string | null | Association location. |
| directory_slug | string | null | Slug for the public directory page. |
| source | string | How this row was resolved: "relationship:<type>" for a confirmed graph edge (managed_by, under_contract, represented_by), or "manager_view:<source>" for a name match against the public management registry. |
Example request
curl "https://commonelements.com/api/v1/professionals/5e3b8c17-2af9-4d60-9a11-77c04e5b8d32/associations" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "c4d0a7e5-91b3-4f28-8a6d-0e51937bb2af",
"name": "HARBOUR RIDGE CONDOMINIUM ASSOCIATION, INC.",
"subtype": "condo",
"city": "Fort Lauderdale",
"state": "FL",
"directory_slug": "harbour-ridge-condominium-association",
"source": "relationship:managed_by"
},
{
"id": "0b9d4f21-3c88-4a17-b5e2-6d7f109c4a55",
"name": "PELICAN BAY COMMUNITY ASSOCIATION, INC.",
"subtype": "hoa",
"city": "Naples",
"state": "FL",
"directory_slug": "pelican-bay-community-association",
"source": "manager_view:dbpr_condo"
}
],
"professional_id": "5e3b8c17-2af9-4d60-9a11-77c04e5b8d32",
"linked_org_id": "7d1e2a90-6b4c-4f31-a8d5-9c0f3e7b1246"
}- Read the source field before treating a row as confirmed. A "relationship:" row is a confirmed edge in the graph; a "manager_view:" row is a name match against a public registry and carries the ambiguity of name matching.
- When the license has no linked organization (linked_org_id is null), only name-matched rows are returned.
Aggregates and compliance
GET/api/v1/geo/state-summary
Per-state rollup of the dataset: association counts broken out by subtype, plus insurance licensee counts. The market-sizing call: how much of a state the data covers before you build against it.
Scope: associationsAvailable on every plan, uncapped: this returns one row per state, not a row listing.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| state | string | Two-letter state code. Omit for every state, ranked by association count. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| state | string | Two-letter state code. |
| association_count | number | Associations in the state, summed across subtypes. |
| by_subtype | object | Subtype to count, e.g. { "hoa": 51204, "condo": 27810 }. |
| insurance_licensee_count | number | Insurance licensees recorded in the state. |
| insurance_active_count | number | Of those, the ones recorded as active. |
Example request
curl "https://commonelements.com/api/v1/geo/state-summary?state=FL" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"state": "FL",
"association_count": 79014,
"by_subtype": { "hoa": 51204, "condo": 27810 },
"insurance_licensee_count": 43638,
"insurance_active_count": 39120
}
],
"total": 1
}- Aggregate counts only. No per-association rows, no personal data. Counts move as ingestion runs, so treat them as current rather than fixed.
POST/api/v1/compliance/scan
Submit a community association document for automated compliance analysis. Returns a structured assessment against Florida and multi-state statutory requirements, plus best-practice governance rules.
Scope: compliance
Request body
| Parameter | Type | Description |
|---|---|---|
| text* | string | The full text of the governing document to analyze. |
| state* | string | Two-letter state code (e.g. "FL", "GA"). |
| doc_type | string | Optional. One of: "governing_document" (default), "cc_and_rs", "bylaws", "articles", "rules_and_regulations". |
Example request
curl -X POST https://commonelements.com/api/v1/compliance/scan \
-H "Authorization: Bearer ce_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"text": "Article I. Name. The name of this Association...",
"state": "FL",
"doc_type": "cc_and_rs"
}'Example response
{
"ok": true,
"score": {
"score": 88,
"grade": "B",
"label": "1 item to review with counsel"
},
"findings": [
{
"ruleId": "fl-solar-preemption",
"title": "Solar-energy-device restriction (statewide preemption)",
"category": "preemption",
"severity": "flag",
"statute": "Fla. Stat. § 163.04",
"guidance": "Florida § 163.04 voids most prohibitions on solar-energy devices...",
"excerpt": "...no solar panels or collectors shall be installed on any roof surface...",
"corpusVerified": false,
"matchQuality": "restrictive"
}
],
"total_findings": 1,
"total_applicable_rules": 17,
"state": "FL",
"engine": "statute_scan_v1"
}Bulk export
Stream a full dataset as CSV or JSON. Growth plan or higher.
GET/api/v1/export/{resource}
Stream a full dataset as CSV or JSON, one request against your monthly quota regardless of row count. `resource` is one of associations, vendors, statutes, building-safety, or report-card. Each resource has its own filter parameters (narrow the export the same way you would narrow the matching list endpoint) and a public-safe column allowlist. report-card streams the per-association public-record signal set behind the Explorer — FEMA NRI county risk, SIRS on file, HUD FHA status, elevator certificates, latest pool inspection, 24-month building permits, and IRS Form 990 revenue — keyed by organization id, name, state, and county.
Scope: per-resource: associations scope for associations, vendors.read for vendors, statutes or associations for statutes, risk for building-safety and report-cardGrowth plan or higher. Free and Builder keys receive 403 tier_not_allowed — the per-row endpoints above are included in every plan, but streaming a full dataset is a Growth+ capability. Per-tier row cap on a single export: Growth 50,000 · Scale 250,000 · Enterprise 1,000,000.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| resource* | string | One of: associations, vendors, statutes, building-safety, report-card. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| format | string | "csv" (default) or "json". |
| columns | string | Comma-separated column names to narrow the output. An unknown column name 400s and lists the valid set for that resource. |
| state | string | Two-letter state code. Every resource supports this filter. |
| q | string | Free-text filter, meaning varies by resource (name for associations/vendors, statute text for statutes). |
| county | string | County filter. Supported by associations, vendors, and building-safety. |
| subtype | string | "hoa", "condo", or "coop". Supported by associations and building-safety. |
| category | string | Vendor category slug. Vendors only. |
| unit_min / unit_max | number | Unit count range. Associations only. |
| year_min / year_max | number | Year-built range. Associations only. |
| is_claimed | boolean | "true" or "false". Associations only. |
| mgmt | string | Management firm name filter. Associations only. |
| chapter / topic | string | Statutes only, same meaning as on /v1/statutes/by-state. |
| sirs_on_file / elevator_delinquent | boolean | "true" or "false". Building-safety only. |
| milestone_status / pool_last_result | string | Free-text, matches the source county/agency's own vocabulary. Building-safety only. |
| has_sirs / has_elevator_cert | boolean | "true" or "false". Report-card only. |
| fha_status | string | Normalized HUD decision: approved, rejected, withdrawn, expired, or other. Report-card only. |
| min_risk / max_risk | number | FEMA NRI county risk score range. Report-card only. |
Example request
curl "https://commonelements.com/api/v1/export/associations?state=FL&subtype=condo&unit_min=100&columns=name,state,unit_count,directory_slug" \
-H "Authorization: Bearer ce_live_your_key_here" -o fl-condos.csvExample response
name,state,unit_count,directory_slug
HARBOUR RIDGE CONDOMINIUM ASSOCIATION INC,FL,214,harbour-ridge-condominium-association
PELICAN BAY COMMUNITY ASSOCIATION INC,FL,742,pelican-bay-community-association
...- One export = one request against your monthly quota, whatever the row count, up to your plan's row cap.
- The scope required depends on the resource, not the export capability itself — a key needs both the resource's read scope AND a Growth+ tier.
- A source guard enforces the same public-record exclusions as every other v1 endpoint; a "columns" value that would expose an excluded field 400s rather than silently dropping it.
- The first page is validated before the response starts streaming, so a bad filter or column name returns a clean JSON error. A failure mid-stream truncates the file — check row counts on large exports.
GET/api/v1/export/changes
Stream the change feed as CSV or JSON: one row per observed event, with the event date, the association it happened to (id, name, state, county), the event type, the changed field, and person-free old/new value summaries. The bulk form of /api/v1/changes for loading trigger events into a warehouse or CRM instead of polling pages.
Scope: changes or associationsGrowth plan or higher, same as every bulk export, with the same per-tier row caps (Growth 50,000 · Scale 250,000 · Enterprise 1,000,000). Your plan lookback window from the change feed still applies: the exported date range is clamped exactly as /api/v1/changes clamps it.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| format | string | "csv" (default) or "json". |
| columns | string | Comma-separated column names to narrow the output. An unknown column name 400s and lists the valid set. |
| kind | string | Comma-separated change kinds, same vocabulary as /api/v1/changes. Omit for all kinds. |
| state | string | Comma-separated two-letter state codes. |
| county | string | Single county name, case-insensitive exact match. |
| subtype | string | One of "hoa", "condo", "coop". |
| since | string | Earliest observation date, YYYY-MM-DD. Clamped to your plan lookback window; an earlier date does not widen it. |
| until | string | Latest observation date, YYYY-MM-DD. |
| min_magnitude | number | Minimum change magnitude, 0 to 1. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Stable id for this change event. |
| observed_on | date | Date the change was observed in the source record. |
| organization_id / organization_name | uuid / string | The association the change was observed on. |
| state / county / subtype | string | null | Location and type of the association. |
| event_type | string | One of the 13 change kinds. |
| field | string | The part of the record that moved: board_roster, management_company, entity_status, entity_name, or license. |
| old_value / new_value | string | null | Person-free before/after summaries: firm names for management changes, statuses for registration changes, seat counts and canonical titles for board changes. Never an individual's name. |
| magnitude | number | null | Relative size of the change, 0 to 1. |
Example request
curl "https://commonelements.com/api/v1/export/changes?kind=management_company_changed,board_turnover&state=FL&since=2026-06-01" \
-H "Authorization: Bearer ce_live_your_key_here" -o fl-changes.csvExample response
Event ID,Event date,Organization ID,Organization name,State,County,Subtype,Event type,Changed field,Old value,New value,Magnitude
3f6b1c2e-...,2026-07-18,0b9d4f21-...,PELICAN BAY COMMUNITY ASSOCIATION INC,FL,Collier,hoa,management_company_changed,management_company,GULF COAST PROPERTY MANAGEMENT INC,SUNSTATE ASSOCIATION MANAGEMENT LLC,0.8
b1244a90-...,2026-07-02,c4d0a7e5-...,HARBOUR RIDGE CONDOMINIUM ASSOCIATION INC,FL,Broward,condo,board_turnover,board_roster,,"3 seats affected; titles: president, director; board size 5",0.6
...- No officer names, ever. The export reads the same person-stripped view as /api/v1/changes: officer changes come back as seat counts and canonical titles, and management changes as firm names. There is no parameter that widens this.
- The lookback window is your plan's change-feed window, applied server-side. The row cap is the bulk-export cap for your tier, not the per-request /api/v1/changes cap.
- One export = one request against your monthly quota, whatever the row count.
Association resources
Public record joined to one association: parcels, structures, permits, code enforcement, hazards, insurance, legal, financials, governance and documents. Same request shape for every one, so a client written against one works against all ten.
GET/api/v1/associations/{id}/parcels
County parcel records matched to the association: the physical footprint behind the corporate record. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: propertyRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/parcels?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "parcels.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/structures
Building footprints and recorded structural characteristics for the association's buildings. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: propertyRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/structures?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "structures.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/permits
Municipal building permits recorded against the association, with work type, value and date. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: permitsRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/permits?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "permits.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/violations
Code enforcement cases recorded against the association by the local jurisdiction. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: enforcementRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/violations?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "violations.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/hazards
Natural-hazard exposure for the association's location: recorded storm events and county-level risk. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: hazardRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/hazards?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "hazards.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/insurance
Insurance-side public record touching the association, including coverage and carrier filings where published. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: insuranceRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/insurance?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "insurance.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/legal
Litigation and legal history recorded against the association, and the counsel of record where published. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: legalRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/legal?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "legal.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/financials
Financial public record for the association, including IRS Form 990 filings where it files one. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: financialsRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/financials?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "financials.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/governance
Governance record for the association: filings, officers over time, and registered agent history. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: governanceRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/governance?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "governance.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/associations/{id}/documents
Governing and recorded documents held for the association, with their source and recording date. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: documentsRow access is plan-gated per source; counts and coverage are returned at every plan so the size of what is behind the gate is visible.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Association id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/associations/9a71c6b0-4e2f-41d8-8b09-5c3a2d17e604/documents?limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "documents.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
Cross-association collections
The same corpora queried across associations, where the buyer genuinely asks the question that way and an indexed filter exists to answer it.
GET/api/v1/storm-events
NOAA storm events by county and date. The hazard history behind an association's exposure, queryable across the whole corpus. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: hazardRow access is plan-gated per source; counts and coverage are returned at every plan.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
| state | string | Two-letter state code. |
| county_fips | string | Five-digit county FIPS code. |
| jurisdiction | string | Jurisdiction name as published by the source. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/storm-events?state=FL&limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "storm-events.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- A cross-association collection requires at least one indexed filter. Without one the request is refused with a 400 naming the filters it accepts, rather than starting a sequential scan over millions of rows.
- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/insurance/carriers
Carriers writing in the association market, by state, with their filings and market presence. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: insuranceRow access is plan-gated per source; counts and coverage are returned at every plan.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
| state | string | Two-letter state code. |
| county_fips | string | Five-digit county FIPS code. |
| jurisdiction | string | Jurisdiction name as published by the source. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/insurance/carriers?state=FL&limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "insurance-carriers.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- A cross-association collection requires at least one indexed filter. Without one the request is refused with a 400 naming the filters it accepts, rather than starting a sequential scan over millions of rows.
- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/insurance/rate-filings
Insurance rate filings by carrier and state: what carriers asked for, and when. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: insuranceRow access is plan-gated per source; counts and coverage are returned at every plan.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
| state | string | Two-letter state code. |
| county_fips | string | Five-digit county FIPS code. |
| jurisdiction | string | Jurisdiction name as published by the source. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/insurance/rate-filings?state=FL&limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "rate-filings.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- A cross-association collection requires at least one indexed filter. Without one the request is refused with a 400 naming the filters it accepts, rather than starting a sequential scan over millions of rows.
- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/legal/cases
Litigation involving community associations across the corpus, filterable by state and date. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: legalRow access is plan-gated per source; counts and coverage are returned at every plan.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
| state | string | Two-letter state code. |
| county_fips | string | Five-digit county FIPS code. |
| jurisdiction | string | Jurisdiction name as published by the source. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/legal/cases?state=FL&limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "legal-cases.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- A cross-association collection requires at least one indexed filter. Without one the request is refused with a 400 naming the filters it accepts, rather than starting a sequential scan over millions of rows.
- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
GET/api/v1/complaints
CFPB consumer complaints against mortgage servicers, banks and debt collectors, as market context for an association's counterparties. Not a record about the association. Live description, provenance and coverage caveat come from /api/v1/datasets.
Scope: financialsRow access is plan-gated per source; counts and coverage are returned at every plan.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | number | Rows per page, 1-500 (default 50). Your plan's row cap and the source's own page ceiling can only lower this; the response's `meta` block reports what was actually applied. |
| offset | number | Pagination offset, 0-100000 (default 0). |
| source | string | Narrow the read to one physical source behind the resource, e.g. `parcels.fl`. Source keys are listed by /api/v1/datasets. |
| since | date | Only records on or after this ISO date (YYYY-MM-DD). |
| until | date | Only records on or before this ISO date (YYYY-MM-DD). |
| state | string | Two-letter state code. |
| county_fips | string | Five-digit county FIPS code. |
| jurisdiction | string | Jurisdiction name as published by the source. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| source_key | string | Which physical source the record came from. Provenance travels with every row. |
| record_id | string | The source's own identifier for the record. |
| occurred_on | date | null | When the recorded event happened, where the source publishes a date. |
| headline | string | null | One-line description of the record, from the source's own headline column. |
| payload | object | null | The record's fields, projected through the source's column allowlist. A column added to a backing table later cannot appear here unless it is added to that allowlist. |
| pagination.limit | number | Rows requested after every server-side cap was applied. |
| pagination.offset | number | Offset used. |
| pagination.total | number | Rows matching the query, before paging. |
| pagination.has_more | boolean | Whether another page exists. |
Example request
curl "https://commonelements.com/api/v1/complaints?state=FL&limit=5" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"source_key": "complaints.example",
"record_id": "SRC-000123",
"occurred_on": "2026-05-14",
"headline": "Example record",
"payload": { "field": "value" }
}
],
"pagination": { "limit": 5, "offset": 0, "total": 1, "has_more": false },
"meta": { "coverage": "…", "sources_measured": 1 }
}- A cross-association collection requires at least one indexed filter. Without one the request is refused with a 400 naming the filters it accepts, rather than starting a sequential scan over millions of rows.
- Read `meta.coverage` before treating an empty result as an absence. A resource can return zero rows because nothing happened, or because that jurisdiction is not matched yet, and those are different facts. The coverage caveat says which.
Bulk delivery
Asynchronous exports for datasets larger than one HTTP response. Request, poll, download a durable artifact with a manifest and a column dictionary beside it — or put it on a schedule and stop asking. Growth plan and above.
GET/api/v1/deliveries/datasets
The deliverable catalog and its column dictionary: what can be delivered, in what shape, and — resolved for the key on this request — what your plan allows. Every dataset is listed, each carrying `available_to_you` and the reason when it is false. Add `?dataset=<key>` for one dataset's full column dictionary.
Scope: associations
Query parameters
| Parameter | Type | Description |
|---|---|---|
| dataset | string | Narrow to one dataset and include its full column dictionary. Without it the response carries column counts rather than every column. Current keys: associations, vendors, statutes, building-safety, report-card, changes. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| dataset_key | string | Stable key to pass as `dataset` when requesting a delivery. |
| label | string | Dataset name, for display. |
| description | string | What the dataset contains. |
| required_scopes | string[] | Scopes a key must carry to request it. |
| required_feature | string | Plan feature the dataset sits behind. |
| supports_snapshot | boolean | Whether the dataset can be delivered as a full snapshot. |
| available_to_you | boolean | Whether the key on this request may request it, resolved at request time. |
Example request
curl "https://commonelements.com/api/v1/deliveries/datasets" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"dataset_key": "associations",
"label": "Example dataset",
"description": "What this dataset contains.",
"required_scopes": ["associations"],
"required_feature": "bulk_export",
"supports_snapshot": true,
"available_to_you": true
}
]
}- The dictionary returned here is the same document shipped inside each delivery, so a schema can be built against this endpoint before the first file arrives, and diffed afterwards.
POST/api/v1/deliveries
Request an asynchronous bulk delivery. Returns immediately with a delivery id; the export runs server-side with keyset pagination and produces a durable artifact with a manifest and a column dictionary beside it. Use this instead of /v1/export when the dataset is larger than one HTTP response can carry.
Scope: associationsBulk delivery is a Growth plan capability, the same line /v1/export draws. Row cap, lookback window, monthly delivery quota and concurrency are all resolved server-side from the key; none of them is a parameter.
Request body
| Parameter | Type | Description |
|---|---|---|
| dataset* | string | Dataset key from /v1/deliveries/datasets. Current keys: associations, vendors, statutes, building-safety, report-card, changes. |
| format | string | `csv` (default) or `jsonl`. |
| mode | string | `snapshot` for the dataset as it stands, or `changes` for what moved inside the window your plan allows. |
| filters | object | Dataset-specific filters, in the same vocabulary as the matching read endpoint. |
| columns | string[] | Subset of the dataset's column dictionary. Narrowing only; it can never add a column the dictionary does not already publish. |
| label | string | Your own label for the run, echoed back on status and in the manifest. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Delivery id. Poll /v1/deliveries/{id} with it. |
| status | string | Lifecycle state: queued, running, succeeded, failed, or cancelled. |
| row_cap | number | Row ceiling applied to this run, from your plan. |
| max_lookback_days | number | null | Lookback window applied in `changes` mode, from your plan. |
| requested_at | timestamp | When the delivery was accepted. |
Example request
curl -X POST "https://commonelements.com/api/v1/deliveries" \
-H "Authorization: Bearer ce_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "dataset": "associations", "format": "csv", "mode": "snapshot" }'Example response
{
"ok": true,
"data": {
"id": "1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4",
"status": "queued",
"dataset": "associations",
"format": "csv",
"mode": "snapshot",
"row_cap": 250000,
"max_lookback_days": 365,
"requested_at": "2026-08-16T12:00:00.000Z"
}
}- One delivery counts once against your monthly request quota and once against your plan's separate monthly delivery quota. Polling its status costs a request like any other call.
- A refusal names its reason: `tier_not_allowed` when the plan does not include delivery, `quota_exceeded` when the monthly delivery quota is spent, and 429 again when too many deliveries are already running.
GET/api/v1/deliveries
List this organization's deliveries, most recent first, with their status, row and byte counts, checksum, and download links while they are live.
Scope: associations
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Delivery id. |
| status | string | queued, running, succeeded, failed, or cancelled. |
| rows_written | number | null | Rows written once the run has produced output. |
| truncated | boolean | Whether the run stopped at the plan's row cap. |
| checksum | string | null | Checksum of the artifact, for verifying a download. |
| download_expires_at | timestamp | null | When the download link stops working. |
Example request
curl "https://commonelements.com/api/v1/deliveries" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4",
"dataset": "associations",
"status": "succeeded",
"rows_written": 48210,
"truncated": false,
"checksum": "sha256:…",
"download_expires_at": "2026-08-23T12:00:00.000Z"
}
]
}GET/api/v1/deliveries/{id}
Status of one delivery: progress while it runs, download links once it succeeds, and — when it fails — a machine-readable `error.code` with a message written for the person who has to decide what to do next.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Delivery id returned when the delivery was requested. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| status | string | queued, running, succeeded, failed, or cancelled. |
| rows_written | number | null | Rows written so far, or in total once finished. |
| part_count | number | null | How many parts the artifact was split into. |
| download_url | string | null | Signed download link, present only while the delivery is downloadable. |
| error_code | string | null | Machine-readable failure reason. Switch on this, not on the message. |
Example request
curl "https://commonelements.com/api/v1/deliveries/1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"id": "1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4",
"status": "succeeded",
"rows_written": 48210,
"part_count": 1,
"download_url": "https://commonelements.com/api/v1/deliveries/…",
"error_code": null
}
}DELETE/api/v1/deliveries/{id}
Cancel a queued or running delivery. Authorization is enforced in SQL from the key's organization rather than asserted by the route, so a delivery belonging to another organization cannot be cancelled even by a caller that skips the check.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Delivery id. |
Example request
curl -X DELETE "https://commonelements.com/api/v1/deliveries/1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": { "id": "1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4", "status": "cancelled" }
}GET/api/v1/deliveries/{id}/download
Stream a delivered artifact, or one of its sidecars. Two doors, one gate: the artifact's own capability token for a pipeline that should not hold an API key, or the organization's API key for anything that already does. Either way the same database function re-checks that the run succeeded, that its retention window is still open, and that the presenter is entitled.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Delivery id. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| token | string | The artifact's capability token, as returned on the delivery's status. Use this when the consumer should not hold an API key. A token download does not consume your monthly request quota. |
| part | string | `manifest` for the run's manifest or `dictionary` for its column dictionary, fetched through the same authorization. Omit for the data itself. |
Example request
curl -L "https://commonelements.com/api/v1/deliveries/1f0a9c4e-2b57-4c1d-9f3a-7b2e5d61c8a4/download?token=…" \
-o delivery.csvExample response
# Streams the artifact. Sidecars return JSON:
{
"dataset": "associations",
"rows": 48210,
"checksum": "sha256:…",
"generated_at": "2026-08-16T12:04:11.000Z"
}- The response is the file itself, not a redirect to storage. A signed storage URL would keep working after the artifact expired, after the subscription lapsed and after the key was revoked, with no server left in the path to reconsider.
- Fetch `?part=dictionary` to build a schema before parsing, and `?part=manifest` to verify the row count and checksum after downloading.
POST/api/v1/deliveries/schedules
Create a recurring delivery: this dataset, these filters, this format, on this cadence, produced whether or not anyone is awake. In `changes` mode each run covers only what was observed after the previous SUCCESSFUL delivery, so a failed run is re-covered on the next one rather than silently skipped.
Scope: associationsGrowth plan and above, the same gate as one-off delivery.
Request body
| Parameter | Type | Description |
|---|---|---|
| dataset* | string | Dataset key. Fixed at creation, because it is what entitlement was checked against. Current keys: associations, vendors, statutes, building-safety, report-card, changes. |
| cadence* | string | `daily`, `weekly`, or `monthly`. |
| format | string | `csv` (default) or `jsonl`. Fixed at creation. |
| mode | string | `snapshot` or `changes`. Fixed at creation. |
| filters | object | Dataset-specific filters. Editable later with PATCH. |
| columns | string[] | Subset of the dataset's column dictionary. Editable later. |
| target | object | Where to deliver. An unimplemented target type is refused with 501 `not_implemented` rather than accepted and silently dropped. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Schedule id. |
| cadence | string | How often it runs. |
| next_run_at | timestamp | null | When the next run is due. |
| paused_at | timestamp | null | Set while the schedule is paused. |
Example request
curl -X POST "https://commonelements.com/api/v1/deliveries/schedules" \
-H "Authorization: Bearer ce_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "dataset": "associations", "cadence": "weekly", "mode": "changes" }'Example response
{
"ok": true,
"data": {
"id": "6c2b71de-9a44-4d8e-8f31-0c5a9e77b210",
"dataset": "associations",
"cadence": "weekly",
"mode": "changes",
"next_run_at": "2026-08-23T06:00:00.000Z",
"paused_at": null
}
}- Dataset, format and mode are fixed at creation. Filters, columns, cadence and pause/resume are editable through PATCH on the schedule.
GET/api/v1/deliveries/schedules
List this organization's recurring deliveries, with their cadence, next run, watermark and paused state.
Scope: associations
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Schedule id. |
| dataset | string | Dataset the schedule delivers. |
| cadence | string | daily, weekly, or monthly. |
| next_run_at | timestamp | null | When the next run is due. |
| last_success_at | timestamp | null | When a file last landed. In `changes` mode this is the watermark the next run reads from. |
Example request
curl "https://commonelements.com/api/v1/deliveries/schedules" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": [
{
"id": "6c2b71de-9a44-4d8e-8f31-0c5a9e77b210",
"dataset": "associations",
"cadence": "weekly",
"next_run_at": "2026-08-23T06:00:00.000Z",
"last_success_at": "2026-08-16T06:00:12.000Z"
}
]
}GET/api/v1/deliveries/schedules/{id}
One recurring delivery and its recent runs.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Schedule id. |
Response fields
| Parameter | Type | Description |
|---|---|---|
| id | uuid | Schedule id. |
| cadence | string | daily, weekly, or monthly. |
| next_run_at | timestamp | null | When the next run is due. Null while paused. |
| runs | array | The schedule's recent runs, each in the same shape as a one-off delivery. |
Example request
curl "https://commonelements.com/api/v1/deliveries/schedules/6c2b71de-9a44-4d8e-8f31-0c5a9e77b210" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": {
"id": "6c2b71de-9a44-4d8e-8f31-0c5a9e77b210",
"cadence": "weekly",
"next_run_at": "2026-08-23T06:00:00.000Z",
"runs": []
}
}PATCH/api/v1/deliveries/schedules/{id}
Pause, resume, retime or refilter a recurring delivery. Dataset, format and mode are deliberately not editable: they are what entitlement was checked against at creation, and letting a PATCH swap the dataset would turn one authorized decision into a standing permission for any other. Change them by creating a new schedule.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Schedule id. |
Request body
| Parameter | Type | Description |
|---|---|---|
| cadence | string | `daily`, `weekly`, or `monthly`. |
| filters | object | Replacement filters, re-validated against the dataset. |
| columns | string[] | Replacement column subset, re-validated against the dictionary. |
| paused | boolean | Pause or resume. Resuming recomputes the next run from now, so a schedule paused for a month does not wake and fire a backlog. |
Example request
curl -X PATCH "https://commonelements.com/api/v1/deliveries/schedules/6c2b71de-9a44-4d8e-8f31-0c5a9e77b210" \
-H "Authorization: Bearer ce_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "paused": true }'Example response
{
"ok": true,
"data": {
"id": "6c2b71de-9a44-4d8e-8f31-0c5a9e77b210",
"paused_at": "2026-08-16T12:00:00.000Z",
"next_run_at": null
}
}- For a `changes` schedule the watermark is untouched by a pause, so the first run after resuming covers everything that happened while it slept — clamped, as always, by your plan's lookback window.
DELETE/api/v1/deliveries/schedules/{id}
Remove a recurring delivery. Artifacts already produced are unaffected and remain downloadable until their retention window closes.
Scope: associations
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id* | uuid | Schedule id. |
Example request
curl -X DELETE "https://commonelements.com/api/v1/deliveries/schedules/6c2b71de-9a44-4d8e-8f31-0c5a9e77b210" \
-H "Authorization: Bearer ce_live_your_key_here"Example response
{
"ok": true,
"data": { "id": "6c2b71de-9a44-4d8e-8f31-0c5a9e77b210", "deleted": true }
}Error codes
All errors return a flat JSON envelope with a machine-readable error string and a human-readable message. Switch on the code; the wording of the message can change, the code will not. Endpoints in the meta namespace add docs_url and next_steps alongside them.
{
"ok": false,
"error": "quota_exceeded",
"message": "Monthly request quota exceeded.",
"docs_url": "https://commonelements.com/developers/docs#errors",
"next_steps": "Call /api/v1/meta/usage to see the reset date and how the quota was spent, then either wait for the reset at the start of the next calendar month or upgrade the plan. /api/v1/meta/usage does not itself consume quota."
}| Status | Code | What happened, and what to do |
|---|---|---|
| 400 | validation_error | Invalid request. A query parameter or body field is missing, malformed, or outside its allowed range. The message names the first parameter that failed.Fix the named parameter and re-send. Every parameter and its accepted values are in the OpenAPI document at /api/v1/openapi; retrying an unchanged request will fail the same way. |
| 401 | invalid_api_key | Key missing, malformed, or revoked. No Authorization header, a header that is not `Bearer <key>`, or a key that does not resolve to an active record.Send `Authorization: Bearer ce_live_...`. If the header is correct, the key has been revoked or expired — mint a new one at /settings/api-keys. Keys are shown once at creation and stored only as a hash, so a lost key cannot be recovered. |
| 403 | scope_not_allowed | Key lacks the required scope. The key is valid but was created without the scope this endpoint requires. Scopes are set at key creation and are not widened at request time.Create a key carrying the scope named in the message, or use the `all` scope. Each endpoint's required scope is on its OpenAPI operation as `x-ce-scope`. |
| 403 | tier_not_allowed | Plan does not include this endpoint. The key is valid and correctly scoped, but the endpoint is gated to a higher plan. Bulk export is the current case: it is Growth and above.Check your plan and the endpoint's minimum at /api/v1/meta/usage, then upgrade from /settings/api-keys. Per-row endpoints remain available on your current plan. |
| 404 | not_found | No such record. The identifier is well-formed but matches nothing this key may see. Records excluded from the public directory read as absent rather than forbidden, deliberately — a 403 would confirm the row exists.Confirm the identifier against a list or search endpoint before fetching it by id. A record that appears in the product but not here is outside the licensed dataset. |
| 429 | quota_exceeded | Monthly request quota used up. The key has spent every request included in the current calendar month. There is no overage charge and no automatic top-up.Call /api/v1/meta/usage to see the reset date and how the quota was spent, then either wait for the reset at the start of the next calendar month or upgrade the plan. /api/v1/meta/usage does not itself consume quota. |
| 501 | not_implemented | Option accepted by the schema, not yet built. The request named a documented option that is not live yet — currently, a delivery target type that has no implementation behind it. Refused rather than accepted, because a schedule that silently drops its files is worse than one that never starts.Use one of the target types the catalog reports as implemented, or contact support if you need the one you asked for. This is not a transient failure; retrying will return the same 501. |
| 504 | search_timeout | Similarity search exceeded the database time limit. The trigram similarity search behind /associations/match ran past the database's statement timeout. The request itself was well-formed; the search simply took too long under current load.Retry after a few seconds; the Retry-After header says how long. Narrowing with the county parameter reduces the search space. If a specific query times out repeatedly, report it: that is a performance bug on our side, not an error in your request. |
| 500 | internal_error | Unexpected server error. The request was accepted and failed on our side.Retry with exponential backoff (1s, 2s, 4s, up to about 30s). If it persists past a few minutes, check /api/v1/meta/status and contact support with the time of the request. |
| 503 | service_unavailable | Dependency unavailable. A backing dependency is unreachable. Returned by the status endpoint when its own database probe fails, so uptime monitors see a non-200.Treat as transient and retry with backoff. /api/v1/meta/status reports which dependency is failing. |
MCP integration
Common Elements runs a hosted MCP (Model Context Protocol) server that lets AI assistants call this API as tools, without writing HTTP client code. It is live today at one endpoint:
https://commonelements.com/api/mcpClaude and ChatGPT: add that URL as a custom connector and sign in when prompted. The OAuth flow issues the key for you, so there is nothing to copy.
Clients that read a JSON config (Cursor and similar): point at the same URL and send your API key as a bearer header.
{
"mcpServers": {
"common-elements": {
"url": "https://commonelements.com/api/mcp",
"headers": {
"Authorization": "Bearer ce_live_your_key_here"
}
}
}
}Once connected, your agent can call tools like search_associations and scan_compliance conversationally, with structured responses automatically parsed. An npm connector package is planned but not published yet; the hosted endpoint is the supported path today. MCP server documentation and changelog live at commonelements.com/developers/mcp.
Command-line tool
The ce CLI wraps this API for terminal and scripting use, with the same key, scopes, and quota as every other surface. Its npm package is not published yet, so there is no install command to run today; this section will carry one when it ships. Everything the CLI wraps is plain REST, so the same jobs run from curl now:
export CE_API_KEY=ce_live_your_key_here
curl "https://commonelements.com/api/v1/associations/lookup?state=FL&q=sunset&limit=5" \
-H "Authorization: Bearer $CE_API_KEY"
curl "https://commonelements.com/api/v1/statutes/search?q=reserve%20study&state=FL" \
-H "Authorization: Bearer $CE_API_KEY"
curl "https://commonelements.com/api/v1/export/associations?state=FL" \
-H "Authorization: Bearer $CE_API_KEY" -o fl-associations.csvFull command and option reference lives at commonelements.com/developers/cli.
FAQ
- What happens when I get a 429 response?
- A 429 means your monthly request quota is used up. The body carries a JSON error envelope with "quota_exceeded" as the error code. Wait for the reset at the start of the next calendar month or upgrade your tier from your API keys settings; there is no automatic overage charge.
- How do API keys map to scopes?
- Every key carries a list of scopes set when it is created, one per data domain: associations, changes, compliance, risk, licenses, professionals, vendors, valuations, and statutes. A request is only authorized if the key carries the scope the endpoint requires; a key without the "vendors" scope gets a 403 from vendor endpoints even with a valid, unexpired key. The change feed accepts either "changes" or "associations".
- What does "read-only" vs "full-access" mean for a scope?
- Every scope on a Developer API key is read and analysis access to the public dataset: no Developer API key can write to your account or to anyone else, regardless of scope. The "all" scope is full access, unlocking every endpoint across every domain. Narrower scopes like "associations" or "compliance" unlock only endpoints in that one domain, so a key you hand to a teammate or embed in a single-purpose integration can be scoped down to just what it needs.
- Where can I see my usage?
- Your API keys settings page shows live usage for every key you hold, as requests used against requests included for the current calendar month. It is the fastest way to check how close a key is to its limit before you hit a 429.
Ready to integrate?
Generate a free API key from your account settings and start building.
Get your API key