parcelpump — API reference (generated)
This file is generated from src/api/route-registry.ts by
npm run docs:api. Do not edit by hand — edit the registry and
regenerate.
Narrative documentation, examples, type definitions, and worked
consumer flows live in docs/api.md.
Endpoints at a glance
| Method | Path | Cap | Summary |
|---|---|---|---|
| GET | /health |
public | Liveness check |
| GET | /openapi.json |
public | OpenAPI 3.0 spec for this API |
| GET | /docs |
public | Swagger UI for human browsing |
| GET | /llms.txt |
public | LLM-friendly summary + pointers (markdown) |
| GET | /.well-known/ai-plugin.json |
public | ChatGPT-plugin manifest pointing at /openapi.json |
| GET | /tiles/manifest.json |
public | Active PMTiles archive pointer |
| GET | /v1/sources |
read | List every wired (source, vendor) tuple |
| PATCH | /v1/sources/{source} |
admin | Toggle source.active or update vendor_config |
| PATCH | /v1/source-refresh-policies/{source} |
admin | Adjust cadence / next_due_at / agricultural_only |
| GET | /v1/parcels/{source}/{id} |
read | Single parcel with full Scrape jsonb |
| GET | /v1/parcels |
read | Bbox query — lightweight rows |
| POST | /v1/parcels/{source}/{id}/scrape-now |
enqueue | Synchronously scrape a parcel via its vendor adapter |
| GET | /v1/search |
read | Fuzzy typeahead across parcels + sos_entities |
| GET | /v1/findings/{source}/{id} |
read | Review-engine findings for a parcel |
| GET | /v1/scrape-jobs |
read | List/filter scrape jobs |
| GET | /v1/scrape-jobs/{id} |
read | Single scrape-job detail |
| POST | /scrape-jobs |
enqueue | Enqueue per-parcel scrape jobs |
| POST | /v1/scrape-jobs/enqueue-ag-county |
enqueue | Bulk-enqueue every is_agricultural parcel in a source |
| DELETE | /scrape-jobs/{id} |
admin | Cancel a queued/running job |
| GET | /v1/admin/concurrency |
read | Per-vendor concurrency configs |
| GET | /v1/admin/tuning-log |
read | Recent tuner decisions |
| PATCH | /v1/admin/concurrency/{vendor} |
admin | Update bounds / mode / target / thresholds for one vendor |
| POST | /v1/admin/concurrency/run-tuner |
admin | Run one tuner cycle synchronously |
| GET | /v1/admin/sources/health |
read | Per-source aggregates (parcel count, queue depth, last success/error) |
system
GET /health
Capability: public (no auth) · Tag: system
Liveness check
Responses:
200— Service is up
{
"status": "ok",
"time": "2026-05-05T03:16:22.038Z"
}
GET /openapi.json
Capability: public (no auth) · Tag: system
OpenAPI 3.0 spec for this API
Generated from src/api/route-registry.ts. Use to feed code generators (openapi-typescript, openapi-generator-cli, etc.).
Responses:
200— OpenAPI document
GET /docs
Capability: public (no auth) · Tag: system
Swagger UI for human browsing
Responses:
200— HTML — Swagger UI rendered against /openapi.json
GET /llms.txt
Capability: public (no auth) · Tag: system
LLM-friendly summary + pointers (markdown)
Emerging convention (similar to robots.txt). Tells Claude / Grok / GPT etc. what parcelpump is and where to find machine-readable specs. Tuned for LLM context windows.
Responses:
200— text/plain markdown
GET /.well-known/ai-plugin.json
Capability: public (no auth) · Tag: system
ChatGPT-plugin manifest pointing at /openapi.json
Responses:
200— Plugin manifest JSON
tiles
GET /tiles/manifest.json
Capability: public (no auth) · Tag: tiles
Active PMTiles archive pointer
Returns the URL + pmtiles:// URL of the most recent parcels archive. Public so map clients can fetch without auth. Cached 5 min at the edge.
Responses:
200— Manifest
{
"parcels": {
"url": "https://api.parcelpump.io/tiles/parcels/a43955359b44b9e4.pmtiles",
"pmtiles_url": "pmtiles://https://api.parcelpump.io/tiles/parcels/a43955359b44b9e4.pmtiles",
"updated_at": "2026-05-04T18:07:39.546Z",
"size_bytes": 51420430
}
}
sources
GET /v1/sources
Capability: read (any valid key) · Tag: sources
List every wired (source, vendor) tuple
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
Responses:
200— Source rows + cadence
{
"count": 922,
"sources": []
}
PATCH /v1/sources/{source}
Capability: admin · Tag: sources
Toggle source.active or update vendor_config
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
source |
path | yes | Source slug e.g. franklin-county-wa |
Request body: Partial update
{
"active": false,
"vendor_config": {
"pacsCid": 12
}
}
Responses:
200— Updated row404— source not found
PATCH /v1/source-refresh-policies/{source}
Capability: admin · Tag: sources
Adjust cadence / next_due_at / agricultural_only
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
source |
path | yes | Source slug |
Request body: Any subset of cadence|next_due_at|agricultural_only
{
"cadence": "monthly",
"agricultural_only": true
}
Responses:
200— Updated policy404— policy not found
parcels
GET /v1/parcels/{source}/{id}
Capability: read (any valid key) · Tag: parcels
Single parcel with full Scrape jsonb
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
source |
path | yes | Source slug |
id |
path | yes | source_parcel_id |
Responses:
200— ParcelpumpParcel
{
"id": "...",
"source": "franklin-county-wa",
"source_parcel_id": "123290284",
"owner_name": "ROUNDABOUT FARM LLC"
}
404— not found
GET /v1/parcels
Capability: read (any valid key) · Tag: parcels
Bbox query — lightweight rows
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
bbox |
query | yes | west,south,east,north (EPSG:4326) |
source |
query | no | Optional source filter |
limit |
query | no | max rows (default 500, cap 5000) |
Responses:
200— Lightweight parcel rows400— bbox missing or non-numeric
POST /v1/parcels/{source}/{id}/scrape-now
Capability: enqueue · Tag: parcels
Synchronously scrape a parcel via its vendor adapter
Dispatches the adapter immediately, waits for the result (5–15s typical), upserts to RDS, returns the full parcel record. Path used by the 'user clicked an unknown parcel' flow. Playwright vendors auto-enqueue and return 503 with enqueued:true.
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
source |
path | yes | Source slug |
id |
path | yes | source_parcel_id |
Request body: Optional vendor-key overrides
{}
Responses:
200— Full parcel record after scrape404— unknown source502— vendor / network error503— vendor requires Playwright; auto-enqueued
{
"enqueued": true,
"error": "vendor helion-pso requires async path"
}
search
GET /v1/search
Capability: read (any valid key) · Tag: search
Fuzzy typeahead across parcels + sos_entities
pg_trgm-based; tolerates typos. Owner name match weighted 3×, situs address 2×, mailing/agent 1×; exact-prefix bonus +0.3 to +0.5; exact parcel-ID match +5.0.
Proximity ranking (Google-Maps-style) — when lat and lon are supplied, parcels closer to that point get a score bonus that decays linearly over proximity_km (default 50). This re-ranks but never filters — a uniquely-named distant match still wins on text alone.
Query-term parsing — when state is not supplied, a trailing state name or 2-letter code is extracted from the query. So q="smith florida" is equivalent to q="smith"&state=FL.
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
q |
query | yes | Search query, min 2 chars. May contain a trailing state token ("jackass WA", "smith florida") which is auto-extracted into the state filter. |
limit |
query | no | max rows (default 20, cap 100) |
types |
query | no | Comma-separated subset |
state |
query | no | 2-letter state code. Hard filter when supplied (overrides query-term extraction). |
source |
query | no | Source slug to narrow search (e.g. 'franklin-county-wa'). Parcels-only filter; doesn't apply to entities. |
lat |
query | no | Latitude in degrees for proximity ranking. Pair with lon. Re-ranks results, never filters. |
lon |
query | no | Longitude in degrees. Pair with lat. |
proximity_km |
query | no | Decay radius for the proximity bonus (default 50). At distance=0 bonus is +1.5; at proximity_km bonus is 0. |
zoning |
query | no | Zoning filter — prefix-matches zoning_code, zoning_description, or land_use_class. e.g. 'R-1', 'agricultural', 'commercial'. |
group |
query | no | Set to 'owner' to merge parcels with the same owner_name into a single kind: "owner-group" entry with a members array + bbox. Useful for Google-Maps-style highlight of all parcels owned by a single entity. |
Responses:
200— Ranked hits
{
"count": 14,
"results": [
{
"kind": "parcel",
"source": "franklin-county-wa",
"source_parcel_id": "123300017",
"owner_name": "HAYDEN FARMS INC",
"score": 1.58
}
]
}
400— q < 2 chars
findings
GET /v1/findings/{source}/{id}
Capability: read (any valid key) · Tag: findings
Review-engine findings for a parcel
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
source |
path | yes | Source slug |
id |
path | yes | source_parcel_id |
Responses:
200— Findings array (often empty in v0)
scrape-jobs
GET /v1/scrape-jobs
Capability: read (any valid key) · Tag: scrape-jobs
List/filter scrape jobs
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
status |
query | no | queued |
source |
query | no | Source slug filter |
limit |
query | no | default 100, cap 500 |
Responses:
200— Job rows
GET /v1/scrape-jobs/{id}
Capability: read (any valid key) · Tag: scrape-jobs
Single scrape-job detail
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
id |
path | yes | Job UUID |
Responses:
200— Job row404— not found
POST /scrape-jobs
Capability: enqueue · Tag: scrape-jobs
Enqueue per-parcel scrape jobs
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
Request body: Single object or array
[
{
"source": "franklin-county-wa",
"source_parcel_id": "113110106"
}
]
Responses:
200— Inserted job IDs
POST /v1/scrape-jobs/enqueue-ag-county
Capability: enqueue · Tag: scrape-jobs
Bulk-enqueue every is_agricultural parcel in a source
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
Request body: Source + optional limit + skip_existing flag
{
"source": "franklin-county-wa",
"skip_existing": true
}
Responses:
200— Enqueue summary404— unknown source
DELETE /scrape-jobs/{id}
Capability: admin · Tag: scrape-jobs
Cancel a queued/running job
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
id |
path | yes | Job UUID |
Responses:
200— Cancelled404— not found or terminal
concurrency
GET /v1/admin/concurrency
Capability: read (any valid key) · Tag: concurrency
Per-vendor concurrency configs
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
Responses:
200— Vendor rows
GET /v1/admin/tuning-log
Capability: read (any valid key) · Tag: concurrency
Recent tuner decisions
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
vendor |
query | no | Vendor filter |
limit |
query | no | default 50, cap 500 |
Responses:
200— Log rows
PATCH /v1/admin/concurrency/{vendor}
Capability: admin · Tag: concurrency
Update bounds / mode / target / thresholds for one vendor
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
vendor |
path | yes | Vendor name |
Request body: Any subset of min/max/target/mode/threshold fields
{
"mode": "manual",
"target_concurrency": 2
}
Responses:
200— Updated config404— vendor not found
POST /v1/admin/concurrency/run-tuner
Capability: admin · Tag: concurrency
Run one tuner cycle synchronously
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
Responses:
200— Per-vendor decisions
admin
GET /v1/admin/sources/health
Capability: read (any valid key) · Tag: admin
Per-source aggregates (parcel count, queue depth, last success/error)
Parameters:
| Name | In | Required | Description |
|---|---|---|---|
X-Parcelpump-Key |
header | yes | API key. See docs/secrets-and-keys.md. |
Responses:
200— Health rows
{
"count": 922,
"sources": []
}