> ## Documentation Index
> Fetch the complete documentation index at: https://developers.investorlift.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The response envelope

> The four top-level keys every response carries, and the value conventions inside them.

Every JSON response has the same shape. A single record carries `data` and `meta`. A list adds `page`, and some lists
add `summary`.

```json theme={null}
{
  "data": [],
  "page": { "next_cursor": "eyJ2IjoxLC...", "limit": 100, "returned": 100 },
  "summary": { "n_investors_ranked": 5813 },
  "meta": { "coverage": [], "terms": "..." }
}
```

| Key       | What it is                                                                                                                                                                                                                                                                   |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data`    | The answer: one record, or the rows of this page.                                                                                                                                                                                                                            |
| `page`    | Where you are in the list. [Pagination](/guides/concepts/pagination) explains the cursor.                                                                                                                                                                                    |
| `summary` | Totals over the **whole** filtered set, not this page. On `/v1/buyers/match`, `n_investors_ranked` is every investor scored in the radius.                                                                                                                                   |
| `meta`    | Everything about the answer, not in it. It carries [coverage and freshness](/guides/concepts/coverage), the effective weights on a ranking and the reference point. It also carries the location that ran (`meta.geometry`), `resolved_from` after an id merge, and `terms`. |

`meta.terms` is a one-sentence attribution that points at the API's terms document. Show it where you show the data.
[Terms and attribution](/guides/terms) carries the terms in full.

## Value conventions

* **Dates** are `YYYY-MM-DD` strings. The data has no timestamps: deeds are dated by day.
* **Money** is whole dollars as an integer. A price is `null` when the deed records none. A price is never `0` to mean
  unknown. In Texas most off-market deeds carry no price at all. The [filters page](/guides/concepts/filters) covers this.
* **Ids** carry a prefix that says what they are: `deal_`, `prop_`, `inv_`, `agt_`, `wl_` (an Investorlift listing),
  `wsr_` (a listing company), `len_` (a lender). The prefix is part of the id. Store the id. Get the name again when you
  show it, or keep the name only within the [cache window](/guides/terms).
* **Coordinates** are WGS84 decimal degrees, `latitude` and `longitude` on a record, `lat` and `lng` in a query.
* **Distances** are miles, **durations** are days, **ratios** and **scores** are 0 to 1.
* **Nulls are answers.** A null listing block means the market has no listing tables. Zeros mean the API checked the
  tables and nothing is listed. Each block's own page says which.

## Say where

Four ways, one per request:

| Geometry                    | Parameters                                                                                                                                                                                                                                                                                                           |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A point and a radius        | `lat=33.476917&lng=-111.920385&radius_miles=2` (0.25 to 20, default 2)                                                                                                                                                                                                                                               |
| A map viewport              | `bbox=-111.95,33.45,-111.89,33.50` (west, south, east, north)                                                                                                                                                                                                                                                        |
| A parcel                    | `property_id=prop_...&radius_miles=2`                                                                                                                                                                                                                                                                                |
| A ZIP list or a postal city | `zip=` takes a comma list or a repeated key, up to 50 ZIP codes. [Counties, cities and ZIP codes](/coverage/places) lists the covered ones. `city=Scottsdale` names the parcel's postal city, in any letter case. Both work on the deal, investor, wholesale and short-term rental lists, not on `/v1/buyers/match`. |

If you mix them, the API answers `400 geometry_conflict`. If you send none where one is necessary, the API answers
`400 geometry_required`. `lat` + `lng` can go beside a viewport or a place as the reference point for distances, and for
nothing more.

A point outside every loaded market is `422 outside_coverage`, not an empty answer. So is a ZIP or a city that no loaded
market's parcels carry. The body names it in `zips_unknown` or `city`. This is the [coverage](/guides/concepts/coverage)
rule. On Free and Starter the place is one ZIP ([Plans and limits](/guides/plans-and-limits)).

The response echoes the location in `meta.geometry`, as it ran. The API fills the defaults: 2 miles on the GET lists,
1 mile around `property_id` on the parcel search. It resolves a parcel to its centroid. It folds the city to upper case.
The echo shows these values under the keys of the query, so you can repeat a request from its answer.
`meta.reference_point` stays beside it.

## Response headers

Beside the body, every `/v1` response carries some useful headers:

| Header                                     | What it is                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `X-Request-Id`                             | The id of this call, which the gateway mints at the edge. The gateway also sends it as `zp-rid`, the one name it has on a refusal that the gateway answers itself. Log it. [Request ids](/guides/concepts/request-ids).                                                                                                                                                                  |
| `X-Rows`                                   | How many rows the body carries (1 on a single record): the size of the body, not a charge. Absent on a `304` and on the CSV export, whose count is known only when the stream ends.                                                                                                                                                                                                      |
| `X-Credits-Charged`, `X-Credits-Remaining` | On a charged response: what it cost, and the balance after it, recent to within a minute. The second header is absent on Enterprise. [Plans and limits](/guides/plans-and-limits).                                                                                                                                                                                                       |
| `X-Dataset-Version`, `X-Data-End`          | `market=value`, comma-joined: the same facts as `meta.coverage[]`, which you can read without parsing the body. On every `2xx` and the `304`, like `ETag`. Never on an error. [Coverage and freshness](/guides/concepts/coverage).                                                                                                                                                       |
| `ETag`                                     | On every `2xx` and the `304`. The API derives it from the dataset version of the markets in the answer, not from the body. On a JSON request, send it back as `If-None-Match`. An unchanged dataset then answers `304` with no body. The CSV export streams the file whatever the tag. The cheapest check is [`GET /v1/dataset`](/api-reference/endpoints/dataset), which runs no query. |
| `Retry-After`                              | On a `429`, on a `503 pool_saturated`, on a `503 ledger_unavailable` and on a `403 plan_limit` for the name-search day cap: seconds to wait. [Rate limits](/guides/concepts/rate-limits).                                                                                                                                                                                                |
| `X-Row-Cap`                                | On the CSV export of [a lender's loans](/api-reference/endpoints/lenders-loans#csv) and on its `422 csv_cap_exceeded`: the most rows an export streams, 50,000.                                                                                                                                                                                                                          |

The API reference declares each of these under the responses that carry it, so a generated client sees them too.

Every response is JSON but one. With the loans of a lender you can ask for a CSV file instead, from Growth.
[The CSV section of that route](/api-reference/endpoints/lenders-loans#csv) says how. For every other list,
[Give me a spreadsheet](/guides/walkthroughs/spreadsheet) shows how to build one from the paged JSON.


## Related topics

- [The response envelope](/api-reference/objects/envelope.md)
- [Authentication](/guides/concepts/authentication.md)
- [API reference](/api-reference/introduction.md)
- [Introduction](/index.md)
- [Quickstart](/guides/quickstart.md)
