Skip to content
Docs menu (sections and pages; this page: API)

API and agents

API

The read-only REST API: authentication, endpoints, rate limits, attribution and errors.

View as Markdown

The Cadastre API is a read-only JSON API over the datasets, measures and metro figures described in these docs, with the same screening and ranking the app uses. It is in beta and free while it is. The public datasets need no account: call it with no credential at all, at 30 requests a minute. Sign in (an API key or an approved app) for higher limits.

Base URL

text
https://getcadastre.com/api/v1

The API is version 1. The OpenAPI 3.1 description is public at https://getcadastre.com/api/v1/openapi.json.

Without an account

Every endpoint except /me answers a request with no credential:

sh
curl "https://getcadastre.com/api/v1/metros?q=austin"

It serves the same datasets as a signed-in request (the public datasets whose terms allow the API), with the same attribution, at 30 requests a minute and 2,000 a day for each network address. Use is governed by the Terms of Service either way; by using the API you agree to them.

Authentication

For higher limits, send one credential in the Authorization header, as a bearer token:

sh
curl -H "Authorization: Bearer $CADASTRE_API_KEY" https://getcadastre.com/api/v1/me

A credential that is not valid (unknown, revoked or expired) is always answered 401, never served as if there were none, so a client learns its key is bad.

  • API keys, for your own scripts and servers. Make one in Settings under API keys (you are asked for your password). A key starts cad_key_ and is shown once: copy it then. It acts as you, in the account you were working in when you made it. Revoke it in the same place.
  • OAuth 2.1, for apps and AI agents that sign in on your behalf: an MCP client, or the Cadastre CLI. The app opens your browser, you sign in to Cadastre, choose the account and approve; the app receives an access token (cad_at_, one hour) and refreshes it itself. Clients register themselves (dynamic client registration) and use the authorization code flow with PKCE (S256). Discovery starts at the authorization server metadata, https://getcadastre.com/.well-known/oauth-authorization-server, and the API's protected resource metadata, https://getcadastre.com/.well-known/oauth-protected-resource/api/v1. See Connect an AI agent for client setup.

Either credential has the one scope there is, read. Read Cadastre's datasets, measures and metro figures, and run screens and rankings over them. It cannot see or change your projects, account or settings. It works only while you are a member of that account and have accepted the current Terms of Service.

API access is turned on per account, and is what gives a credential its higher limits. A new account does not have it: write to support@getcadastre.com to ask for it (it may become part of a paid plan later). Until it is on, Settings makes no keys for the account and the consent page will not connect an app to it; a key or app the account already has gets what a request without a credential gets (the same data, the per-address limits). GET /me says which: its access.tier is api (the account's limits) or public (the per-address limits).

Disconnect an app in Settings under Authorized apps.

Never put a key in a query string, a web page or a shared file; anything holding it can act as you.

Endpoints

All paths are under the base URL. Lists are paged with page (from 1) and per_page (up to 500, default 100); the answer's meta carries total and total_pages.

Account

GET /me

Who the credential acts as. Needs a credential; without one it is 401 with the sign-in challenge.

GET /openapi.json

This description. Public: no credential needed.

Datasets

GET /datasets

The datasets the API serves.

GET /datasets/{key}

One dataset, with its measures.

ParameterInTypeDescription
key (required)pathstringA dataset key, as GET /datasets lists them

Measures

GET /measures

Search the measures.

ParameterInTypeDescription
qquerystringText in the name, label or unit
geographyquerymsa, county, stateOnly measures with values at this geography
datasetquerystringOnly this dataset's measures (its key)
pagequeryintegerPage number, from 1
per_pagequeryintegerItems per page, up to 500 (default 100)

GET /measures/{name}

One measure.

ParameterInTypeDescription
name (required)pathstringA measure name, as GET /measures lists them

GET /measures/{name}/values

A measure's value for every region of a geography.

ParameterInTypeDescription
name (required)pathstringA measure name, as GET /measures lists them
geographyquerymsa, county, stateThe geography to list; needed (a request without it is a 400)
statequerystringUSPS code: metros partly in it, its counties, or the state
pagequeryintegerPage number, from 1
per_pagequeryintegerItems per page, up to 500 (default 100)

Metros

GET /metros

The metropolitan statistical areas.

ParameterInTypeDescription
statequerystringUSPS code
qquerystringText in the name
pagequeryintegerPage number, from 1
per_pagequeryintegerItems per page, up to 500 (default 100)

GET /metros/compare

Metros side by side.

ParameterInTypeDescription
ids (required)querystringUp to 25 metro ids, CBSA codes or slugs, comma-separated
measuresquerystringUp to 50 measure names, comma-separated (default: the register's standard figures)

GET /metros/{ref}

A metro's profile. Every measure the API serves that the metro has a value for. ref is the metro's id, its five-digit CBSA code or its slug (percent-encode the slug's slashes, us%2Ftx%2Faustin-12420).

ParameterInTypeDescription
ref (required)pathstringThe metro's id, CBSA code or slug

Analysis

POST /screen

Screen the metros by scope and Requirements (read-only).

The body is JSON, a ScreenRequest (fields below, under Screening and ranking).

POST /rank

Rank the metros on weighted criteria (read-only).

The body is JSON, a RankRequest (fields below, under Screening and ranking).

Incentives

GET /incentive_programs

Incentive programs federal, state and local governments offer (paid). Programs read from the jurisdictions' official pages and reviewed by Cadastre, each value with the sentence it was quoted from (evidence) and the page (source_url); a field the page does not state is null (unknown). A program is what a jurisdiction offers: not an award, an amount anyone received, or a finding that a site qualifies. A jurisdiction with no programs listed is not covered yet. Only records from pages whose terms allow reuse are served. Part of API access: an account without it is answered 403 api_access_required.

ParameterInTypeDescription
statequerystringUSPS code or state FIPS: federal programs, the state's and its local governments'
metroquerystringCBSA code, region id or slug: federal programs, the metro's states' and its local governments'
mechanismquerytax_credit, grant, loan, loan_guarantee, abatement, exemption, training_grant, infrastructure, financing_bond, zone_designation, otherOnly programs of this kind
pagequeryintegerPage number, from 1
per_pagequeryintegerItems per page, up to 200 (default 50)

Examples

sh
# The datasets the API serves
curl -H "Authorization: Bearer $CADASTRE_API_KEY" https://getcadastre.com/api/v1/datasets

# Search the measures
curl -H "Authorization: Bearer $CADASTRE_API_KEY" "https://getcadastre.com/api/v1/measures?q=unemployment&geography=msa"

# A metro's profile, by its CBSA code (Huntsville, AL)
curl -H "Authorization: Bearer $CADASTRE_API_KEY" https://getcadastre.com/api/v1/metros/26620

# Three metros side by side on the standard figures
curl -H "Authorization: Bearer $CADASTRE_API_KEY" "https://getcadastre.com/api/v1/metros/compare?ids=26620,48620,46140"

Screen and rank are POSTs with a JSON body. They compute an answer and save nothing:

sh
curl -X POST https://getcadastre.com/api/v1/screen \
  -H "Authorization: Bearer $CADASTRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requirements": {"tier": "500k", "min_mfg_share": 8, "max_unemployment": 5.5}}'

curl -X POST https://getcadastre.com/api/v1/rank \
  -H "Authorization: Bearer $CADASTRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requirements": {"tier": "500k"}, "criteria": [{"measure": "unemployment_rate", "direction": "lower_better", "weight": 2}]}'

Measure names (unemployment_rate above) come from GET /measures.

Screening and ranking

POST /screen applies a scope and the app's Requirements to the metros and answers with the funnel (how many metros each Requirement leaves) and the metros that pass. POST /rank adds weighted criteria and answers with ranks, composite scores and each criterion's value, score and contribution. The same inputs give the same answer as a project in the app.

Requirements

FieldTypeMeaning
tier1m, 500k, 250kMinimum population
min_mfg_sharenumberManufacturing share of GDP, percent, at least
max_unemploymentnumberUnemployment rate, percent, at most
min_growthnumberFive-year population growth, percent, at least
max_hazardnumberFEMA National Risk Index, at most
max_elec_pricenumberIndustrial electricity price, cents per kWh, at most
rtw_onlybooleanOnly metros entirely in right-to-work states

Criteria

FieldTypeMeaning
measurestringA measure name from GET /measures
directionhigher_better, lower_betterWhich way scores better
weightnumberDefault 1; 0 keeps the criterion as a gate only
cutoffobjectEliminates the metros it holds for.

scope.states limits either to the metros partly in the listed states (USPS codes). A Requirement or criterion that reads a measure the API does not serve is a 422.

Responses and attribution

A successful answer is JSON: { "data": ..., "meta": ..., "attribution": [...] }. attribution lists, once each, the credit every dataset behind data requires: the publisher's credit, the licence and its link, and any notices, disclaimers and conditions the publisher attaches.

  • Show the attribution with the figures, wherever they go: an analysis, a report, a deck, an app, an AI agent's answer. The Rights and attribution page explains each source's requirements, and the Terms of Service make it a condition of using the API.
  • Cite retrieved_at. Each attribution entry carries retrieved_at, when Cadastre last retrieved that data from its publisher. Give it with the data (the Bureau of Labor Statistics asks API users to cite the retrieval date).
  • Label Cadastre's computed values. A value marked computed_by_cadastre is Cadastre's figure (for example a metro total built from county figures), and calculation says how. Credit it as "Source: Cadastre, computed from" the publisher's data, not as the publisher's own figure.

Only datasets whose terms Cadastre has approved for the API are served; any other is absent from every list and a 404. Sources restricted in the app (see Rights and attribution) are never served.

Not served

  • No geometry. Answers carry names and codes (region ids, CBSA codes, FIPS), never boundaries, points or lines. Geometry is not available yet; if it is added it will be an explicit option, never a default.
  • No parcel data. The launch is metro-level; parcels are not in the API.
  • No listings. Cadastre does not carry property listings.

Rate limits

  • Without a credential, 30 requests a minute and 2,000 a day for each network address (an IPv6 /64), the API and the MCP server together. A key or app of an account without API access counts here too.
  • With a credential of an account with API access, 60 requests a minute and 10,000 a day for each API key, and for each app you approved (across its token refreshes).
  • 50,000 requests a day for each account, over all its keys and apps, so more keys do not add up to more requests.

Every answer carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds). Over a limit the answer is 429 with Retry-After: wait that many seconds; without an account, the message says how to sign in for more. These are the beta limits and may change.

Caching

The data GETs (datasets, measures, metros) carry an ETag and Last-Modified. Send If-None-Match with the ETag you have and an unchanged answer is a 304 with no body, which still counts as a request. The data changes when Cadastre imports a new release, not by the minute. An answer to a request without a credential is the same for everyone, so it is Cache-Control: public, max-age=60 (with Vary: Authorization): a cache may keep it for a minute. An answer to a credential is private and revalidated every time.

Errors

An error is JSON: { "error": "<code>", "message": "<sentence>" }.

StatuserrorWhat to do
400bad_requestA malformed parameter or body. The message names it.
401unauthorized, invalid_tokenA credential that is unknown, revoked or expired, or whose person left the account, or not sent as a bearer token; or none at all on /me. Fix or drop the credential (with none, the public datasets are served). The WWW-Authenticate header names the protected resource metadata, so an OAuth client can sign in again.
403terms_requiredThe Terms of Service were updated. Sign in to Cadastre in a browser and accept them; the key or app works again at once.
403insufficient_scopeThe credential lacks the read scope. Sign in again or make a new key.
404not_foundNo such dataset, measure or metro, or one the API does not serve.
415unsupported_media_typeSend the POST body as application/json.
422invalid_request, unknown_measureWell formed but cannot be answered: an unknown measure, or a Requirement whose source the API does not serve.
429rate_limitedOver a rate limit. Wait for Retry-After seconds, or sign in for higher limits.
503unavailableThe API is not available on this server. Try again later.

Versioning and beta

The version is in the path (/api/v1). During the beta Cadastre may add, change or remove endpoints, fields, datasets and limits, and will try to give notice of a change that breaks existing use; adding a field or a dataset is not a breaking change, so read answers tolerantly. There is no service level during the beta. See the Terms of Service.

AI agents and the MCP server

An AI agent can use the API directly, with or without a key, or connect to Cadastre's remote MCP server, which offers the same data as tools, with no sign-in or signed in with OAuth in the browser for higher limits. See MCP server and the agent guides.