{
  "content_type": "application/problem+json",
  "body": [
    "type",
    "title",
    "status",
    "code",
    "detail",
    "instance",
    "request_id",
    "errors?"
  ],
  "problems": [
    {
      "code": "validation_error",
      "status": 400,
      "title": "Validation error",
      "description": "A parameter failed validation. errors[] names each offending parameter.",
      "recovery": "Fix the parameters named in errors[] and send the request again.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#validation_error"
    },
    {
      "code": "unknown_parameter",
      "status": 400,
      "title": "Unknown parameter",
      "description": "The query carries a parameter the endpoint does not define. Bracketed list syntax such as kind[] counts as an unknown parameter. A list is comma-separated values or repeated keys.",
      "recovery": "Remove the parameter, or write the list as comma-separated values or repeated keys, for example kind=flip,hold.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#unknown_parameter"
    },
    {
      "code": "invalid_cursor",
      "status": 400,
      "title": "Invalid cursor",
      "description": "The API cannot decode the cursor, or issued it for another query, sort, weight set or dataset version. Restart from page 1.",
      "recovery": "Restart from page 1 without cursor; the data refreshed or the query changed.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#invalid_cursor"
    },
    {
      "code": "geometry_required",
      "status": 400,
      "title": "Geometry required",
      "description": "The request needs one geometry: lat and lng (with radius_miles), bbox, property_id, zip or city.",
      "recovery": "Pass one geometry: lat and lng with radius_miles, bbox, property_id, zip (a list) or city.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#geometry_required"
    },
    {
      "code": "geometry_conflict",
      "status": 400,
      "title": "Geometry conflict",
      "description": "The geometry parameters contradict each other. Conflicts: radius_miles with bbox, property_id with a point or a bbox, a lone lat or lng, or zip beside city. A place (zip or city) beside radius_miles, bbox or property_id is also a conflict. A place on a route that ranks around a point (buyers/match) is also a conflict. A point beside a place is the reference point, not a conflict. On the coverage route, two place groups at once are a conflict, and so is a lone lat or lng. The place groups of the coverage route are lat and lng, county, zip and market.",
      "recovery": "Send one geometry only: lat and lng with radius_miles, bbox alone, property_id with radius_miles, or zip or city. On the coverage route, pass one place: lat and lng, county, zip or market.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#geometry_conflict"
    },
    {
      "code": "sort_requires_point",
      "status": 400,
      "title": "Sort requires a reference point",
      "description": "sort=distance needs lat and lng, or property_id. With bbox alone, or with a zip or city without a point, the default sort is date_desc.",
      "recovery": "Add lat and lng or property_id, or drop sort=distance and take the default date order.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#sort_requires_point"
    },
    {
      "code": "invalid_id",
      "status": 400,
      "title": "Invalid id",
      "description": "Every id has a prefix. The forms: deal_<32 hex>, prop_<32 hex>, inv_<12 hex>, agt_<12 hex>, wl_<32 hex> (an Investorlift listing), wsr_<12 hex> (a wholesaler), len_<12 hex> (a lender). The prefix is part of the id.",
      "recovery": "Pass the id exactly as it was served, prefix included, for example inv_ followed by 12 hex characters.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#invalid_id"
    },
    {
      "code": "market_required",
      "status": 400,
      "title": "Market required",
      "description": "The investor or agent id exists in more than one loaded market. Or you asked for a lender list (GET /v1/lenders) while the API has several markets loaded, and named no market. A lender list ranks inside one market. Pass market=. The body lists the markets.",
      "recovery": "The id exists in each listed market, or the list ranks inside one; pass market.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#market_required"
    },
    {
      "code": "unauthorized",
      "status": 401,
      "title": "Unauthorized",
      "description": "The request carries no bearer key, or the key is malformed or unknown.",
      "recovery": "Send Authorization: Bearer with a current key. A revoked or mistyped key gets the same answer.",
      "producer": "both",
      "type": "https://developers.investorlift.com/guides/concepts/errors#unauthorized"
    },
    {
      "code": "quota_exceeded",
      "status": 403,
      "title": "Quota exceeded",
      "description": "Your requests spent the plan's credits for the billing period: the allowance, or on Growth and Scale the overage ceiling. On the Free plan, spent lifetime credits get the same refusal, with stop budget in the body. The body carries used and line. Every route that charges credits answers it until the period resets or the plan changes. A re-read of a record you already hold gets the same refusal, from the origin before it prices the page and from the gateway's check. The routes priced at 0 and the MCP handshake keep answering.",
      "recovery": "Upgrade the plan in the developer console, or wait for the billing period to reset.",
      "producer": "both",
      "type": "https://developers.investorlift.com/guides/concepts/errors#quota_exceeded"
    },
    {
      "code": "subscription_required",
      "status": 403,
      "title": "Subscription required",
      "description": "The key has no active plan subscription: the gateway found none, or forwarded no subscription for a route that charges credits.",
      "recovery": "Subscribe to a plan in the developer console. The Free plan is enough to call the API.",
      "producer": "both",
      "type": "https://developers.investorlift.com/guides/concepts/errors#subscription_required"
    },
    {
      "code": "payment_overdue",
      "status": 403,
      "title": "Payment overdue",
      "description": "The subscription's last payment failed and the grace period passed. The gateway blocks the key until you update the card under Manage Billing in the console. A refused request charges nothing.",
      "recovery": "Update the card under Manage Billing in the developer console. The key works again within a minute of a successful payment.",
      "producer": "gateway",
      "type": "https://developers.investorlift.com/guides/concepts/errors#payment_overdue"
    },
    {
      "code": "plan_limit",
      "status": 403,
      "title": "Plan limit",
      "description": "The request exceeds what this plan allows. The limits: geometry, the daily name-search cap, an MCP page over the plan's largest, the change series' weeks over /mcp, monitors or export rows. The response names the limit. Upgrade in the console.",
      "recovery": "Narrow the request to what the body names as the limit, or upgrade the plan in the developer console.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#plan_limit"
    },
    {
      "code": "not_found",
      "status": 404,
      "title": "Not found",
      "description": "No such route, or no such deal, investor, agent, lender or parcel in any loaded market.",
      "recovery": "Check the path and the id; the entity is in no loaded market, or the route does not exist.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#not_found"
    },
    {
      "code": "not_acceptable",
      "status": 406,
      "title": "Not acceptable",
      "description": "The Accept header names a representation the endpoint does not produce. No Accept header, */* and application/* mean JSON. text/csv works only where a route documents it.",
      "recovery": "Send Accept: application/json, or no Accept header at all. The API serves CSV only where a route documents it: a lender's loans from the Growth plan, the rest for partners and staff.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#not_acceptable"
    },
    {
      "code": "gone",
      "status": 410,
      "title": "Gone",
      "description": "A retired investor, agent or lender id. superseded_by is null. Search by name instead (/v1/investors/search, /v1/agents/search or /v1/lenders/search).",
      "recovery": "This id is retired and has no successor; look the investor, agent or lender up by name.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#gone"
    },
    {
      "code": "outside_coverage",
      "status": 422,
      "title": "Outside coverage",
      "description": "The point (or parcel centroid) lies farther from every loaded market's coverage bbox than its point tolerance, or the bbox intersects none of them. The tolerance is meta.coverage[].point_tolerance_miles on any list response: 20 miles for a metro, 2 for a county market. The deal, investor, wholesale-listing and short-term-rental lists answer it for a zip or city that no parcel of a loaded market carries. The body then carries zips_unknown or city, and the loaded markets. A lender list (GET /v1/lenders) answers it too when the named zip, city or county lies outside the counties its market's lender registry covers. Those counties are meta.coverage[].lenders.counties, and the body carries counties_covered. A ZIP of an unloaded county is not a place with no lending.",
      "recovery": "No data at this location. Read the loaded markets and their areas from markets[] when present, and from meta.coverage[] on any list response.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#outside_coverage"
    },
    {
      "code": "ambiguous_apn",
      "status": 422,
      "title": "Ambiguous APN",
      "description": "The APN matches several parcels that are not the same parcel. candidates[] lists them.",
      "recovery": "Pick the parcel from candidates[] and pass its property_id.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#ambiguous_apn"
    },
    {
      "code": "ambiguous_address",
      "status": 422,
      "title": "Ambiguous address",
      "description": "The address matches several parcels: the units of one building, or twins of the line in the ZIP or city. The body's candidates[] lists them with their units.",
      "recovery": "Pass unit=, or the ZIP instead of the city, or pick the parcel from candidates[] and pass its property_id.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#ambiguous_address"
    },
    {
      "code": "csv_cap_exceeded",
      "status": 422,
      "title": "CSV cap exceeded",
      "description": "The CSV export exceeds the 50,000-row cap (X-Row-Cap). The API counts the filtered set before the first row streams. Narrow the geometry or filters, or on the loans of a lender the recorded_from and recorded_to window.",
      "recovery": "Narrow the filters, or the recorded_from and recorded_to window on a lender's loans, until the set is under the row cap. Or page the JSON list instead.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#csv_cap_exceeded"
    },
    {
      "code": "listings_unavailable",
      "status": 422,
      "title": "Listings unavailable",
      "description": "You gave listing_status, or asked the comps route for source=mls, for a market with no published listing tables. Its meta.coverage[].listings_data_end is null, so \"listed or not\" has no answer. An empty page reads as \"nothing listed\", so the API refuses. Drop the parameter, or ask the comps for source=deed or both, or wait for the market's listing feed.",
      "recovery": "Not published for this market yet. The API still serves deal, investor and property rows with the listing block null, and the comps from the deed registry alone.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#listings_unavailable"
    },
    {
      "code": "agents_unavailable",
      "status": 422,
      "title": "Agents unavailable",
      "description": "You called a /v1/agents route for a market with no published agent registry. Its meta.coverage[].agents_data_end is null, so the API can find or profile no agent. An empty answer reads as \"no such agent\", so the API refuses. Wait for the market's agent registry. The API still serves the listing agents on deal and property rows, without ids.",
      "recovery": "Not published for this market yet. The API still serves the listing agents on deal and property rows, without ids.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#agents_unavailable"
    },
    {
      "code": "lenders_unavailable",
      "status": 422,
      "title": "Lenders unavailable",
      "description": "You called a /v1/lenders route for a market with no published lender registry, so the API can find, rank or profile no lender. The registry tables are absent, or the market has no financing slice to build them from, so meta.coverage[].lenders is null there. An empty answer reads as \"no such lender\", so the API refuses.\n\nGET /v1/lenders/{id}/borrowers and the deed-link and borrower-match filters answer it too, before any query, on a registry that predates both. Those filters are purpose, outcome, deal_kind, investor_id and investor_only, and such a registry has meta.coverage[].lenders.purchase_measured, investor_lending_measured or borrowers_measured false. Every phase-5 parameter and route answers it too on a registry built before the place rankings, or on a host without the h3 extensions. Phase 5 is a period other than 24m, a geometry, foreclosed, cell, GET /v1/lenders/{id}/rankings and /cells, and its fields are null there. Wait for the market's lender build. The API still serves the financing block on parcels where the slice is.",
      "recovery": "Not published for this market yet, or its registry predates the borrower match or the place rankings the request asked for. The API still serves the financing block on parcels where the slice is.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#lenders_unavailable"
    },
    {
      "code": "wholesale_unavailable",
      "status": 422,
      "title": "Wholesale transactions unavailable",
      "description": "You called the /v1/wholesale-listings, /v1/wholesalers or `/v1/investors/{id}/wholesale-purchases` route, or the source=investorlift or bought_on_investorlift filter, for a market with no published Investorlift wholesale tables. Its meta.coverage[].wholesale_as_of is null, so the API can find no listing or wholesaler. An empty answer reads as \"nothing listed\", so the API refuses. Wait for the market's wholesale tables. The API still serves the deal, investor and property rows, with their wholesale blocks null.",
      "recovery": "Not published for this market yet; deal, investor and property rows are still served with their wholesale blocks null.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#wholesale_unavailable"
    },
    {
      "code": "str_unavailable",
      "status": 422,
      "title": "Short-term rental data unavailable",
      "description": "You gave the str_status, str_business_use, str_operator or str_holdings_min filter, or called GET /v1/str-parcels, for a market with no published short-term rental tables. Its meta.coverage[].str_as_of is null, so \"licensed or not\" has no answer. An empty page reads as \"no licence\", so the API refuses. Drop the parameter, or wait for the market's STR build. The API still serves the deal, investor and property rows, with their short_term_rental and str blocks null.",
      "recovery": "Not published for this market yet. The API still serves deal, investor and property rows with their short_term_rental and str blocks null.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#str_unavailable"
    },
    {
      "code": "cash_sale_unavailable",
      "status": 422,
      "title": "Cash sale proxy unavailable",
      "description": "You gave the cash-buyer quicklist or the sale.cash_sale filter for a market where meta.coverage[].parcel.sale_mortgage_measured is false. Its delivery records a purchase mortgage on fewer than one priced last sale in five, so cash_sale_proxy is null on every parcel. So \"cash or not\" has no answer: an empty page reads as \"no cash buyers\" and a full one as \"every priced sale was cash\". Drop the quicklist or the filter. Where meta.coverage[].auction_counted is true, the measured cash signals are the auction block, bought_auction_kind, buys_at_auction and buys_reo.",
      "recovery": "Not measured for this market: drop cash-buyer and sale.cash_sale. Where auction_counted is true, bought_auction_kind, buys_at_auction and buys_reo are the measured cash signals.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#cash_sale_unavailable"
    },
    {
      "code": "auction_unavailable",
      "status": 422,
      "title": "Auction counts unavailable",
      "description": "You gave buys_at_auction, buys_reo or bought_auction_kind for a market with no published foreclosure-auction and REO purchase counts. Its meta.coverage[].auction_counted is false: its registry predates the counts. So \"bought at auction or not\" has no answer, and an empty page reads as \"nobody buys at auction\". Drop the parameter, or wait for the market's registry rebuild. The API still serves the investor and deal rows, with investor.auction and bought_auction_kind null.",
      "recovery": "Not published for this market yet. Drop buys_at_auction, buys_reo and bought_auction_kind to list every row, or wait for the market's rebuild.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#auction_unavailable"
    },
    {
      "code": "parcels_unavailable",
      "status": 422,
      "title": "Parcel products unavailable",
      "description": "You called POST /v1/properties/search, a financing, permits, history or listing-history route, or GET /v1/markets/{market}/changes, for a market with no published parcel product tables. Its meta.coverage[].parcel is null, so the API can find no parcel. An empty answer reads as \"nothing matches\", so the API refuses. Wait for the market's parcel build.",
      "recovery": "Not published for this market yet. The API still serves the deal, investor and property rows.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#parcels_unavailable"
    },
    {
      "code": "addresses_unavailable",
      "status": 422,
      "title": "Addresses unavailable",
      "description": "You called GET /v1/properties/resolve with address, but no market has a published address table: meta.coverage[].address_as_of is null on every market.",
      "recovery": "Resolve by lat / lng or apn, or retry once coverage[].address_as_of carries a date.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#addresses_unavailable"
    },
    {
      "code": "dated_refused",
      "status": 422,
      "title": "Dated data refused",
      "description": "The request set require_current: true and also names a dated block (valuation, financing or liens) in a filter, the sort or datasets. A dated block is a snapshot valued at the slice date in meta.coverage[].parcel.financing.as_of. Drop require_current to get the dated blocks with their meta.dated[] stamp, or drop the dated filters, sort and datasets.",
      "recovery": "Drop require_current to accept the dated blocks (stamped in meta.dated[]), or remove the dated filters, sort and datasets named in errors[].",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#dated_refused"
    },
    {
      "code": "history_unavailable",
      "status": 422,
      "title": "History unavailable",
      "description": "The parcel lies outside the ZIP codes the history lake covers for its market (meta.coverage[].parcel.history.zips), or the market has no history tables. So no timeline or listing cycle exists for the parcel. An empty timeline reads as \"nothing changed\", so the API refuses.",
      "recovery": "No history for this parcel: it is outside the ZIP codes the history lake covers (meta.coverage[].parcel.history.zips).",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#history_unavailable"
    },
    {
      "code": "quicklist_unavailable",
      "status": 400,
      "title": "Quicklist unavailable",
      "description": "A quicklist name in quicklists, any_quicklists or not_quicklists is not one this API can compute. Either the name is unknown, or no delivery carries its dataset. Examples: notice-of-default, preforeclosure, active-auction, has-hoa and for-sale-by-owner. The body's errors[] names each one and the dataset that unlocks it.",
      "recovery": "Remove the quicklists named in errors[]. The quicklists guide lists every name this API computes.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#quicklist_unavailable"
    },
    {
      "code": "dataset_unavailable",
      "status": 400,
      "title": "Dataset unavailable",
      "description": "A name in datasets is not a block this API serves. Either the name is unknown, or no delivery carries the dataset (contact, demographic, foreclosure, batchrank). The body's errors[] names each one.",
      "recovery": "Remove the datasets named in errors[]. The search guide lists every block a row can carry.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#dataset_unavailable"
    },
    {
      "code": "rate_limited",
      "status": 429,
      "title": "Rate limited",
      "description": "The request exceeded the per-key, per-IP or per-X-On-Behalf-Of budget. Retry-After says when to retry.",
      "recovery": "Retry after retry_after seconds.",
      "producer": "both",
      "type": "https://developers.investorlift.com/guides/concepts/errors#rate_limited"
    },
    {
      "code": "internal_error",
      "status": 500,
      "title": "Internal error",
      "description": "Unexpected failure. The body carries the request_id to quote. The API echoes nothing from the database.",
      "recovery": "Retry once. If it occurs again, report the request_id.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#internal_error"
    },
    {
      "code": "database_unavailable",
      "status": 503,
      "title": "Database unavailable",
      "description": "The service failed to reach or keep a connection to the database.",
      "recovery": "Retry with backoff. The database was unreachable and the API did not run the request.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#database_unavailable"
    },
    {
      "code": "pool_saturated",
      "status": 503,
      "title": "Pool saturated",
      "description": "No pooled connection came free within 2 s, or the pod reached its in-flight cap. Retry-After: 1.",
      "recovery": "Retry in a second. The service is at capacity and did not run the request.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#pool_saturated"
    },
    {
      "code": "ledger_unavailable",
      "status": 503,
      "title": "Ledger unavailable",
      "description": "The credit ledger is unreachable. Retry after the interval in Retry-After. The API charged nothing.",
      "recovery": "Retry after retry_after seconds. The API charged nothing and served nothing.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#ledger_unavailable"
    },
    {
      "code": "statement_timeout",
      "status": 504,
      "title": "Statement timeout",
      "description": "The query exceeded the 10 s statement timeout. Narrow the geometry or filters.",
      "recovery": "Narrow the radius or add filters. The query exceeded 10 seconds.",
      "producer": "origin",
      "type": "https://developers.investorlift.com/guides/concepts/errors#statement_timeout"
    }
  ]
}
