AreaOps Developer Platform
The AreaOps API for developers and AI agents
The AreaOps API is a territory-intelligence API for home-services brands. It scores every US ZIP code 0–100 for demand fit from US Census ACS data, reads and edits the service areas your team already manages, and renders shareable territory maps. It is available three ways: a Model Context Protocol server for AI agents, a REST API described by a published OpenAPI 3.1 contract, and an official command-line tool.
Quickstart
- Create an account and an API key. Sign up, then mint a key in Settings → Developers & API. Keys are prefixed
aoa_live_and are shown once. Agent access requires an active subscription or trial. - Point your agent at the MCP server. One command with the Claude Code CLI:
claude mcp add --transport http areaops https://areaops.app/api/mcp \ --header "Authorization: Bearer aoa_live_your_key_here" - Ask it a territory question. “Score the top 20 roofing ZIP codes in Atlanta and tell me which ones my Peachtree brand is already in.” The agent calls
areaops_score_territoryandareaops_compare_brand_to_scores, and answers from real data.
Authentication
Every authenticated request carries a bearer token in the Authorization header. API keys work on the MCP endpoint; the REST agent endpoints additionally accept a signed-in AreaOps browser session. Public endpoints need no credential at all.
curl https://areaops.app/api/mcp \
-H "Authorization: Bearer aoa_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Treat a key like a password: it carries your organization's brand scope and write entitlement. Revoke and re-mint from Settings → Developers & API at any time.
MCP server
AreaOps runs a real Model Context Protocol server over stateless Streamable HTTP at POST https://areaops.app/api/mcp. The discovery document at /api/mcp/info is public and needs no key — point an agent directory or an answer engine at it.
Client configuration
{
"mcpServers": {
"areaops": {
"type": "http",
"url": "https://areaops.app/api/mcp",
"headers": { "Authorization": "Bearer aoa_live_your_key_here" }
}
}
}Read tools
| Tool | What it returns |
|---|---|
areaops_get_capabilities | Account standing: plan, write entitlement, brand scope, per-call limits. |
areaops_list_brands | The org's brands with approved and pending territory counts. |
areaops_score_territory | Rank ZIPs for a vertical in a metro or explicit ZIP list. |
areaops_get_brand_territory | A brand's ZIPs, paged, filterable by state, flag and review status. |
areaops_compare_brand_to_scores | Keep / cut / add read on a footprint against vertical scores. |
areaops_query_targeting | The org's own targeting scores with demographic filters. |
areaops_get_zip_profile | Everything AreaOps knows about one ZIP code. |
areaops_discover_zips | Expansion candidates by radius or city. |
areaops_list_pending_review | Read-only visibility into the human review queue. |
areaops_get_brand_health | Coverage and review-status health for a brand. |
areaops_get_activity | The agent's own change trail. |
areaops_list_share_links | Public share links the org has minted. |
areaops_render_territory_map | A rendered PNG map of a territory. |
Write tools
Every write requires an explicit confirm: true, an active write entitlement, and passes your key's brand scope. Added ZIPs land in a human review queue rather than going live, and removals are undo-snapshotted in the same transaction. There is deliberately no tool that approves a review.
| Tool | Behavior |
|---|---|
areaops_apply_territory | Add ZIPs to a brand. Lands in the human review queue, never live. |
areaops_remove_territory | Remove ZIPs from a brand. Undo-snapshotted in the same transaction. |
areaops_share_territory_map | Mint a public, expiring share link for a territory. |
areaops_revoke_share_link | Revoke a share link the org owns. |
Command-line tool
The official AreaOps CLI scripts the same API from a shell or a CI job, with --json on every command so an agent can pipe the output straight into a tool call.
npm install -g areaops # or: npx areaops <command>
export AREAOPS_API_KEY=aoa_live_your_key_here
areaops zip 30309 # public ZIP profile, no key needed
areaops score roofing --metro atlanta-ga --limit 20
areaops mcp-config # print MCP client JSON
areaops openapi > areaops-openapi.json # fetch the published contractREST API and OpenAPI contract
The full contract is published as OpenAPI 3.1 at /openapi.json (and /api/openapi.yaml). Every operation carries a unique operationId, a description, typed parameters and a typed response schema, so it drops straight into an LLM function-calling definition without hand-editing.
Public endpoints — no key required
GET /api/healthz— service health.GET /api/mcp/info— MCP discovery document.GET /api/public/zip/{zip}— citation-safe ZIP profile.GET /api/public/vertical/{vertical}— vertical summary.GET /api/public/data-study— the flagship data study, also available as CSV.
Worked example
curl "https://areaops.app/api/public/zip/30309"
{
"zipCode": "30309",
"city": "Atlanta",
"state": "GA",
"scores": [{ "vertical": "roofing", "score": 71 }],
"signals": { "ownerOccupiedRate": 0.42, "medianHomeValue": 512300 }
}Rate limits and usage
Every API response carries standard rate-limit headers so a client can self-throttle without guessing. AreaOps sends the IETF RateLimit and RateLimit-Policy structured fields, the widely-supported X-RateLimit-* triple for older clients, and Retry-After on every 429.
RateLimit: "default";r=57;t=42
RateLimit-Policy: "default";q=60;w=60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 42
Retry-After: 42 # on 429 only| Endpoint | Limit | Scope |
|---|---|---|
POST /api/mcp | 60 / minute, 2,000 / day | Per API key, durable (Postgres-backed) |
GET /api/mcp/info | 60 / minute | Per IP, unauthenticated discovery |
GET /api/public/* | 100 / minute | Per IP, unauthenticated |
GET /api/shared/:token/* | 240 / minute | Per IP — recipients are external |
GET /api/map-context | 240 / minute | Per IP, cached 24h |
Separately from rate limits, agent tool calls consume metered units against your plan's monthly allowance: 1,000 units are included, most tools cost 1 unit, areaops_score_territory costs 10, and map rendering and sharing cost 5. Exhausting the allowance returns a 402 carrying code: usage_quota_exceeded and the current meter.
Errors
REST errors are JSON objects with a human-readable error and, where one exists, a machine-readable code to branch on. MCP errors use the JSON-RPC error envelope.
| Status | Meaning |
|---|---|
| 400 | Invalid request body or parameters. |
| 401 | Missing, malformed, or revoked credential. |
| 402 | No active subscription, or the monthly unit allowance is exhausted. |
| 404 | No data for the requested market, ZIP, or token. |
| 406 | No representation matches the request's Accept header. |
| 429 | Rate limited. Wait Retry-After seconds. |
| 503 | Usage recording unavailable; the call was not served. |
Machine-readable resources
- /openapi.json — the OpenAPI 3.1 contract for the whole public and agent surface.
- /llms.txt — what AreaOps is, when to use it, and how an agent should call it.
- /llms-full.txt — every public page inlined as one markdown document.
- /api/mcp/info — MCP discovery, unauthenticated.
- /sitemap-index.xml — every indexable URL.
- /docs — the API reference index.