---
title: "Bounded CSV export through the same guarded query path."
method: POST
path: "/v1/export"
tags: ["query"]
---

# Bounded CSV export through the same guarded query path.

`POST /v1/export`

## Request

- Base URL: `https://api.premiumpin.com`
- URL: `https://api.premiumpin.com/v1/export`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `pp_session`

Accepts the same scoped closed-catalog request as /v1/query. The server applies the same authentication, entitlement, suppression, metering, snapshot, and hard 5,000-row cap before streaming CSV. Omit-select CSV headers are the 91 canonical_fields in schema order; unheld values are empty cells. A named filter that is not held on the scoped county returns JSON empty + unavailable_fields, not CSV. CSV preflight carries bounded scope status/count headers; detailed arrays stay in query/empty JSON and the existing export audit entry. Unavailable-Count sums counties without tables and held counties missing required capability. These are not row, visited-county, field-fill or legally accessible-parcel counts. Delivery terminal states and geography availability are independent. The MCP wrapper preserves delivery status (complete/truncated/error; not-started for JSON/local honest empties), exposes delivery_complete and the bounded scope_coverage status/requested_count/bindable_count/unavailable_count, and sets complete only for exhausted delivery with valid available scope headers. Missing/unknown/contradictory available headers cannot certify completeness; error/truncation/disconnect overrides success. JSON empties retain full shared metadata and never claim completed CSV delivery. Local unresolved empties have unknown scope. No scope enumeration grants access or bypasses suppression. The in-band CSV terminal receipt includes field_notes for delivered nonblank county-field values with a material official source caveat. Notes identify the bound source and do not assign an inferred effective year. For prepared delivery, send X-PP-Delivery: artifact-v1 and a stable Idempotency-Key. A large result returns an account-bound artifact descriptor; retrieve its exact bytes through GET /v1/artifacts/{artifact_id} with the same account authorization before expiry. The path is not a bearer token.

## Headers

- `Idempotency-Key` string
- `X-PP-Delivery` 'artifact-v1'

## Request body

- QueryRequest
  - `cursor` string: opaque keyset cursor from a prior response. Bound to store_version + query; else 400/410.
  - `filter` Filter: Structured filter contract accepted by the public query builder.
    - `filters` object[]
      - `field` string, required
      - `op` 'eq' | 'ne' | 'in' | 'contains' | 'starts_with' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'is_null' | 'is_not_null', required
      - `value` unknown
    - `logic` 'and'
    - `order_by` object
      - `dir` 'asc' | 'desc'
      - `field` string
  - `limit` integer
  - `order_by` object
    - `dir` 'asc' | 'desc'
    - `field` string
  - `q` string: Closed English question over held catalog slots. Not freehand SQL.
  - `scope` union, required: REQUIRED. Exactly one of fips, state, or held bounds the search.
    - object
      - `fips` string[], required
      - `held` string[]
      - `state` string[]
    - object
      - `fips` string[]
      - `held` string[]
      - `state` string[], required
    - object
      - `fips` string[]
      - `held` string[], required
      - `state` string[]
  - `select` string[]: Return-field whitelist from the public field catalog. Private internal fields are never allowed.
  - `slots` object: Named closed-catalog slots. Combined with filter.filters using AND. tax_amount and subdivision_name are rejected.

## Response `200`

CSV rows, a prepared artifact descriptor, or an honest-empty JSON response when a named filter field is not held on the scoped county.

- union
  - QueryResponse
    - `bindable_fips` string[]
    - `count` integer: rows returned (<= limit)
    - `empty_reason` 'field-not-held', nullable
    - `field_notes` FieldSourceNote[]
      - `capture_receipt_sha256` string, required
      - `effective_year` integer, nullable, required: Null when the field's effective year is unknown.
      - `field` string, required
      - `fieldbook_sha256` string, required
      - `fips` string, required
      - `parcel_universe_year` integer, required: Dataset membership year, not field effective year.
      - `release_manifest_sha256` string, required
      - `source_field` string, required
      - `source_url` string, uri, required
      - `stage_sha256` string, required
      - `warning` string, required
    - `honest_empty` boolean
    - `miss_reason` string, nullable
    - `next_cursor` string, nullable: pass as cursor for the next page; null on last page
    - `parcels` Parcel[]
      - `access_type` string, nullable
      - `acres` number, nullable
      - `ag_value` number, nullable
      - `assessed_value` number, nullable
      - `bedrooms` integer, nullable
      - `block` string, nullable
      - `building_type` string, nullable
      - `calc_area` number, nullable
      - `census_tract` string, nullable
      - `census_tract_name` string, nullable
      - `cooling` string, nullable
      - `county_fips` string, nullable
      - `county_name` string, nullable
      - `county_sub_fips` string, nullable
      - `county_sub_name` string, nullable
      - `deed_book` string, nullable
      - `deed_instrument` string, nullable
      - `deed_page` string, nullable
      - `elev_avg` number, nullable
      - `elev_max` number, nullable
      - `elev_min` number, nullable
      - `epa_dfr_url` string, nullable
      - `epa_frs_id` string, nullable
      - `fips` string, nullable
      - `fireplaces` integer, nullable
      - `firm_date` string, date, nullable
      - `firm_id` string, nullable
      - `flood_zone` string, nullable
      - `foundation` string, nullable
      - `full_baths` integer, nullable
      - `half_baths` integer, nullable
      - `heat_fuel` string, nullable
      - `heating` string, nullable
      - `improvement_value` number, nullable
      - `iucn_class` string, nullable
      - `land_use` string, nullable
      - `land_use_desc` string, nullable
      - `land_value` number, nullable
      - `legal_desc` string, nullable
      - `living_area_sqft` number, nullable
      - `lot` string, nullable
      - `market_value` number, nullable
      - `naics_code` string, nullable
      - `num_buildings` integer, nullable
      - `num_floors` integer, nullable
      - `num_units` integer, nullable
      - `owner_address` string, nullable
      - `owner_city` string, nullable
      - `owner_country` string, nullable
      - `owner_name` string, nullable
      - `owner_state` string, nullable
      - `owner_type` string, nullable
      - `owner_zip` string, nullable
      - `parcel_id` string, nullable
      - `parcel_id_alt` string, nullable
      - `parcel_id_original` string, nullable
      - `parcel_id_original_alt` string, nullable
      - `parcel_type` string, nullable
      - `parent_parcel_id` string, nullable
      - `permit_caa` string, nullable
      - `permit_cwa` string, nullable
      - `permit_rcra` string, nullable
      - `place_name` string, nullable
      - `place_type` string, nullable
      - `plss_desc` string, nullable
      - `prior_deed_book` string, nullable
      - `prior_deed_page` string, nullable
      - `quarter_section` string, nullable
      - `range` string, nullable
      - `roof_cover` string, nullable
      - `sale_date` string, date, nullable
      - `sale_price` number, nullable
      - `section` string, nullable
      - `siding` string, nullable
      - `site_address` string, nullable
      - `site_city` string, nullable
      - `site_state` string, nullable
      - `site_zip` string, nullable
      - `source_updated` string, date, nullable
      - `source_vintage` string, nullable
      - `stack_id` string, nullable
      - `state_fips` string, nullable
      - `static_bfe` number, nullable
      - `tax_account` string, nullable
      - `tax_district` string, nullable
      - `tax_year` integer, nullable
      - `township` string, nullable
      - `year_built` integer, nullable
      - `zoning_code` string, nullable
      - `zoning_desc` string, nullable
      - `zoning_subtype` string, nullable
    - `question_id` string, nullable
    - `scope_coverage` ScopeCoverage, required: Shared Engine availability for the effective existing filter and type rules. All FIPS arrays are sorted and deduplicated. For resolved supported filters, bindable/unavailable/field-unavailable are disjoint and exhaust requested_fips. Available means all requested counties bindable, partial a nonempty proper subset, unavailable none. Unknown means unresolved filter, with no certified bindable/unavailable/field-unavailable classification; it is never a fallback for missing or corrupt Census authority (generation binding fails). This does not promise visited counties, nonnull fields, distinct parcel totals, or legal access. Optional nullable projections retain existing binding rules.
      - `bindable_fips` string[], required: Eligible under existing required-field/type rules, not visited on this page.
      - `field_unavailable_fips` string[], required: Held geography lacking required capability.
      - `legacy_fips` string[], required: Loaded/requested historical codes outside pinned current authority; not successor-jurisdiction coverage.
      - `requested_fips` string[], required
      - `status` 'available' | 'partial' | 'unavailable' | 'unknown', required
      - `unavailable_fips` string[], required: Requested geography without a loaded table.
    - `store_version` string
    - `truncated` boolean: more rows exist beyond this page
    - `unavailable_fields` string[]: Named fields not held by the scoped county; present on field-not-held honest empties.
  - PreparedArtifact
    - `artifact` object, required
      - `bytes` integer, required
      - `expires_at` integer, required: UTC Unix timestamp
      - `path` string, required
      - `rows` integer, required
      - `sha256` string, required
    - `complete` boolean, required
    - `delivery_complete` boolean, required
    - `next_cursor` string, nullable
    - `receipt` object, required
    - `row_cap` integer
    - `scope_coverage` object
    - `status` string, required
    - `store_version` string, required

## Other responses

- `400`: bad filter / no scope / unknown field or op / malformed cursor / county-not-held for wholly unloaded search or absent lookup table
- `401`: missing or invalid API key / session
- `402`: metered quota exhausted (hard cap). Includes upgrade_url.
- `403`: requested owner-PII fields but the plan/entitlement doesn't allow them
- `410`: cursor was minted against an older snapshot; restart pagination
- `413`: scope would exceed the row/scan cap; narrow fips/state/held or add filters
- `429`: too many requests; retry after the window

---

[API](https://skmtc.dev/premiumpin/apis/premiumpin-property-records-api.md) · [All operations](https://skmtc.dev/premiumpin/apis/premiumpin-property-records-api/llms.txt) · [OpenAPI document](https://skmtc.dev/premiumpin/apis/premiumpin-property-records-api/revisions/18f5ec1c629c?raw)
