API Best Practices

Regrid API Best Practices

The Regrid API is billed by the number of Parcel Records returned in a response, not by the number of requests you make. Because a single query can return anywhere from one parcel to hundreds of thousands, the two most important parameters to understand before you build anything at scale are limit and return_count. This guide walks through both, along with the surrounding patterns (pagination, payload trimming, and query design) that keep your integration fast, predictable, and cost-effective.

Why this matters: billing is per-parcel, not per-request

Any endpoint that can match more than one Parcel Record — search by address, owner name, parcel number, polygon, or point-with-radius, as well as the api/v2/parcels/query field-query endpoint — will return multiple Parcel Records in a single API call, and you are billed for every record returned. A broad, unfiltered query (for example, "all parcels in a county") can silently return tens of thousands of records and consume a large portion of your plan in one request.

General Rule

Before running a broad or exploratory query in production, always check how many records it will match. Guessing wrong is the single most common cause of unexpected overage charges.

Use limit to control how many parcels come back

The limit parameter caps the number of Parcel Records returned by a single request.

  • Default: 20 records if limit is omitted.
  • Range: 1 to 1000.
  • Available on every endpoint capable of returning more than one parcel.
GET https://app.regrid.com/api/v2/parcels/query?fields[county][eq]=Harris&limit=10&token=<token>

Best practices for limit:

  • Always set limit explicitly. Don't rely on the default of 20 if you actually need more (or fewer) records — an implicit default is easy to forget about once your query logic changes.
  • Start small while developing. Use a low limit (5–10) while building and testing a new query so you aren't burning through billable parcels on every test run.
  • Cap at what you actually need. If your application only displays the first 25 results to a user, request limit=25, not limit=1000.
  • Use the maximum (1000) deliberately for bulk pulls, and pair it with pagination (below) rather than trying to raise the limit further — 1000 is a hard ceiling per request.

Use return_count to check the size of a query before you pay for it

Before pulling parcel data for a broad or unfamiliar query, run the same query with return_count=true. This tells you exactly how many Parcel Records match — at no cost — so you can decide whether to narrow your filters, paginate, or proceed.

GET https://app.regrid.com/api/v2/parcels/query?fields[geoid][eq]=06037&fields[ll_gisacre][gt]=2&return_count=true&token=<token>

Response:

{
  "count": 228122
}

Key behaviors to know:

  • Setting return_count to either true or false runs the count against your entire filtered dataset, ignoring limit — limit is ignored entirely when return_count is present.
  • There is no billing cost for a return_count=true request, regardless of how large the matching dataset is.
  • Because a count request doesn't return parcel geometry or attributes, it's cheap to run defensively — treat it as a pre-flight check, not an occasional debugging tool.

Recommendation

Recommended pattern: Run return_count=true first on any new or user-driven query. If the count is small, fetch the parcels directly with an appropriate limit. If the count is large, either add more filters to narrow the result set, or move straight to paginating through it deliberately with offset_id (see below) so you know exactly how many records — and how much billing — the full pull will consume.

# Step 1 — check size, free of charge
GET /api/v2/parcels/query?fields[county][eq]=Harris&fields[ll_bldg_count][gt]=0&return_count=true&token=<token>

# Step 2 — only pull records once you know what you're committing to
GET /api/v2/parcels/query?fields[county][eq]=Harris&fields[ll_bldg_count][gt]=0&limit=200&token=<token>

Paginate large result sets with offset_id

If a query matches more than 1000 records, a single request can't return them all — limit tops out at 1000. Use offset_id to page through the remaining results.

  1. Send the first request with offset_id=0 (this guarantees results are returned in ID order) and your desired limit.
  2. Read the id field from the last parcel Feature in the response.
  3. Send the next request with offset_id set to that id, using the same filters and limit.
  4. Repeat until a page returns fewer records than limit, or an empty result set.
# First page
GET /api/v2/parcels/query?fields[geoid][eq]=06037&fields[ll_gisacre][gt]=2&offset_id=0&limit=1000&token=<token>

# Next page — offset_id is the `id` of the last parcel from the previous response
GET /api/v2/parcels/query?fields[geoid][eq]=06037&fields[ll_gisacre][gt]=2&offset_id=155171239&limit=1000&token=<token>

Error Alert

The order parameter cannot be combined with pagination — the API will return an error if both are present in the same query.

Combine this with return_count from the previous section: check the total count up front so you know how many pages to expect (and how many billable records the full pull represents) before you start looping.

Trim the response payload when you don't need everything

Several boolean flags reduce response size and can speed up large pulls — useful once you're requesting hundreds or thousands of records at a time:

ParameterDefaultEffect when set to false
return_geometrytrueOmits parcel boundary geometry — significant payload savings if you only need attribute data.
return_customfalse (already off)Leave false unless you specifically need county-specific fields beyond the standard schema.
return_matched_buildingstrue (if enabled on your plan)Disables building footprint data in the response.
return_matched_addressestrue (if enabled on your plan)Disables matched secondary address data.
return_enhanced_ownershiptrue (if enabled on your plan)Disables enhanced ownership data.
return_zoningtrue (if enabled on your plan)Disables standardized zoning data.
return_stackedtrueReturns only the first parcel when multiple parcels share identical geometry.
return_parcelstrueReturns only add on datasets to avoid incurring a parcel return cost.

If your use case is analytical (e.g., aggregating attribute values) rather than mapping, set return_geometry=false — it's the single biggest payload reduction available and doesn't affect billing, since billing is based on record count, not payload size.

Narrow your query before you widen your limit

limit and return_count control how many records come back per request, but the most effective way to manage cost is to avoid matching more parcels than you actually need in the first place:

  • Combine field filters. Up to 4 fields can be combined in a single for Standard access api/v2/parcels/query request (e.g., county + acreage + zoning) , and up to 8 fields can be returned if on Premium access — stacking filters is free and reduces the matched set before limit or billing ever comes into play.
  • Prefer the most specific lookup endpoint for the job. If you already have an address, APN, or ll_uuid, use the dedicated lookup endpoint (/parcels/address, /parcels/apn, /parcels/{ll_uuid}) instead of a broad field query — these are direct lookups rather than filtered searches.
  • Use a small radius deliberately. When searching by point, only add a radius if you expect the exact point to miss the parcel boundary (e.g., GPS drift). A larger-than-needed radius increases the number of matched parcels and their cost.
  • Use geojson polygons to bound area searches. Area queries are capped at 80 sq miles per request — plan tiling of larger regions into multiple smaller polygon queries rather than one oversized request.

Monitor usage in real time

The /usage and /usage/detailed endpoints report your current consumption against your plan's Parcel Record limit, at no cost to query. Check usage:

  • Before running any bulk or exploratory job.
  • On a schedule (e.g., daily) if your application runs recurring queries.
  • Immediately after any query where return_count revealed an unexpectedly large result set.

Summary checklist

  • Every request that can return multiple parcels has an explicit limit.
  • Broad or user-driven queries are checked with return_count=true first — it's free.
  • Result sets over 1000 records are paginated with offset_id, not fetched via a single oversized limit.
  • order is never combined with pagination.
  • return_geometry (and other return_* flags) are set to false when that data isn't needed, to reduce payload size.
  • Field filters are stacked to narrow matches before increasing limit.
  • /usage is checked periodically to track consumption against your plan.

Following this pattern — count first, filter narrow, limit deliberately, paginate when needed — is the most reliable way to use the Regrid API without running into unexpected overage charges.


Did this page help you?