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 RuleBefore 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
limit to control how many parcels come backThe limit parameter caps the number of Parcel Records returned by a single request.
- Default: 20 records if
limitis 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
limitexplicitly. 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, notlimit=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
return_count to check the size of a query before you pay for itBefore 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_countto eithertrueorfalseruns the count against your entire filtered dataset, ignoringlimit—limitis ignored entirely whenreturn_countis present. - There is no billing cost for a
return_count=truerequest, 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.
RecommendationRecommended pattern: Run
return_count=truefirst on any new or user-driven query. If the count is small, fetch the parcels directly with an appropriatelimit. If the count is large, either add more filters to narrow the result set, or move straight to paginating through it deliberately withoffset_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
offset_idIf 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.
- Send the first request with
offset_id=0(this guarantees results are returned in ID order) and your desiredlimit. - Read the
idfield from the last parcel Feature in the response. - Send the next request with
offset_idset to thatid, using the same filters andlimit. - 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 AlertThe
orderparameter 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:
| Parameter | Default | Effect when set to false |
|---|---|---|
return_geometry | true | Omits parcel boundary geometry — significant payload savings if you only need attribute data. |
return_custom | false (already off) | Leave false unless you specifically need county-specific fields beyond the standard schema. |
return_matched_buildings | true (if enabled on your plan) | Disables building footprint data in the response. |
return_matched_addresses | true (if enabled on your plan) | Disables matched secondary address data. |
return_enhanced_ownership | true (if enabled on your plan) | Disables enhanced ownership data. |
return_zoning | true (if enabled on your plan) | Disables standardized zoning data. |
return_stacked | true | Returns only the first parcel when multiple parcels share identical geometry. |
return_parcels | true | Returns 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
limitlimit 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/queryrequest (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 beforelimitor 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
radiusdeliberately. When searching by point, only add aradiusif 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
geojsonpolygons 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_countrevealed 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=truefirst — it's free. - Result sets over 1000 records are paginated with
offset_id, not fetched via a single oversizedlimit. -
orderis never combined with pagination. -
return_geometry(and otherreturn_*flags) are set tofalsewhen that data isn't needed, to reduce payload size. - Field filters are stacked to narrow matches before increasing
limit. -
/usageis 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.
Updated about 2 hours ago
