{"openapi":"3.0.3","info":{"title":"Datafiniti API","version":"4","description":"Search, count, and download business, people, product, property data. Covers the same core query surface as the Datafiniti MCP server — see docs/mcp-server.md in the node-datafiniti-api repo for the MCP equivalent of every operation here."},"servers":[{"url":"https://api.datafiniti.co/v4"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"Error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_type","invalid_enum","missing_required_field","out_of_range","unknown_field","invalid_field","invalid_query","invalid_view","not_found","no_results","credit_limit_exceeded","plan_restriction","feature_not_enabled","forbidden","query_runner_error","internal_error"]},"message":{"type":"string"},"field":{"type":"string","description":"The request field this error concerns, when applicable."}},"required":["code","message"]},"ErrorResponse":{"type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/Error"}}},"required":["errors"]}}},"paths":{"/businesses/search":{"post":{"operationId":"searchBusinesses","summary":"Search, count, or download businesses","description":"Query the Datafiniti businesses index. This one endpoint does three things based on the request body: a plain query searches and returns up to 50 records; `num_records: 0` counts matches with no records returned and no credit cost; `download: true` starts an async download job instead (requires `num_records`), returning a Download object to poll via GET /downloads/{download_id}. Example: `categories:hotels AND province:TX`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"num_records":{"type":"integer","minimum":1,"description":"Number of records to return (search), or the download size when `download` is true. `num_records: 0` triggers a count instead of a search — see this operation's description."},"format":{"type":"string","enum":["json","csv","JSON","CSV"],"default":"json"},"query":{"description":"Lucene syntax. Examples: boolean — `categories:laptops AND brand:Apple`; negation with `-` — `categories:laptop AND -brand:Apple` excludes Apple; parentheses for grouping — `(categories:laptops OR categories:desktops) AND brand:Apple`; nested field, dot notation — `prices.amountMin:3`; range — `dateAdded:[2017-01-01 TO 2017-02-01]` or `prices.amountMin:>10`; compound query on a single nested sub-object — curly braces require every condition inside them to match the *same* nested array entry, not just any entry across the array: `{ reviews.rating:5 AND reviews.userProvince:Austin }` finds a product with one review that is both 5-star and from Austin, as opposed to `reviews.rating:5 AND reviews.userProvince:Austin` without braces, which would also match a 5-star review from anywhere plus a separate Austin review of any rating. Canonical example per data type: businesses — `categories:hotels AND province:TX`; people — `currentAddress.state:CA AND age:[25 TO 35]`; products — `brand:Samsung AND categories:televisions`; properties — `city:Austin AND yearBuilt:[2015 TO 2024]`. Full reference (syntax is shared across data types): https://docs.datafiniti.co/docs/constructing-product-queries — data-type-specific variants: constructing-business-queries, constructing-people-queries, constructing-property-queries. For businesses specifically: `categories:hotels AND province:TX`.","oneOf":[{"type":"string"},{"type":"object"}]},"sort":{"type":"boolean","default":true},"view":{"description":"Controls which fields come back on each record. A string names a view — either one of the data type's default views or one of your own saved views. An array is treated as an ad-hoc, one-off view: each entry is either a plain field name (e.g. `\"descriptions\"`) or `{\"name\": \"<field>\"}` when you also need `alias`/`flatten`. Use the plain field name to get a whole nested field (e.g. `\"descriptions\"` or `{\"name\": \"descriptions\"}` returns every sub-field of each description), or dot notation to pull just one sub-field (e.g. `\"descriptions.value\"`). Omit to get the default preview view.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"flatten":{"type":"boolean"}},"required":["name"]}}]},"download":{"type":"boolean","default":false,"description":"If true, this becomes an async download request instead of a search — the response is a Download object, and `num_records` becomes required (poll GET /downloads/{download_id})."},"auto_trace":{"type":"boolean","default":false},"fuzzy_match":{"type":"string","enum":["on","off","retry"],"default":"on"},"only_traceable":{"type":"boolean","description":"Only valid alongside auto_trace. See auto_trace."}}}}}},"responses":{"200":{"description":"Search results, a count, or a Download object, depending on the request body.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/businesses/{record_id}":{"get":{"operationId":"getBusinessesRecord","summary":"Fetch a single businesses record by id","parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/people/search":{"post":{"operationId":"searchPeople","summary":"Search, count, or download people","description":"Query the Datafiniti people index. This one endpoint does three things based on the request body: a plain query searches and returns up to 50 records; `num_records: 0` counts matches with no records returned and no credit cost; `download: true` starts an async download job instead (requires `num_records`), returning a Download object to poll via GET /downloads/{download_id}. Example: `currentAddress.state:CA AND age:[25 TO 35]`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"num_records":{"type":"integer","minimum":1,"description":"Number of records to return (search), or the download size when `download` is true. `num_records: 0` triggers a count instead of a search — see this operation's description."},"format":{"type":"string","enum":["json","csv","JSON","CSV"],"default":"json"},"query":{"description":"Lucene syntax. Examples: boolean — `categories:laptops AND brand:Apple`; negation with `-` — `categories:laptop AND -brand:Apple` excludes Apple; parentheses for grouping — `(categories:laptops OR categories:desktops) AND brand:Apple`; nested field, dot notation — `prices.amountMin:3`; range — `dateAdded:[2017-01-01 TO 2017-02-01]` or `prices.amountMin:>10`; compound query on a single nested sub-object — curly braces require every condition inside them to match the *same* nested array entry, not just any entry across the array: `{ reviews.rating:5 AND reviews.userProvince:Austin }` finds a product with one review that is both 5-star and from Austin, as opposed to `reviews.rating:5 AND reviews.userProvince:Austin` without braces, which would also match a 5-star review from anywhere plus a separate Austin review of any rating. Canonical example per data type: businesses — `categories:hotels AND province:TX`; people — `currentAddress.state:CA AND age:[25 TO 35]`; products — `brand:Samsung AND categories:televisions`; properties — `city:Austin AND yearBuilt:[2015 TO 2024]`. Full reference (syntax is shared across data types): https://docs.datafiniti.co/docs/constructing-product-queries — data-type-specific variants: constructing-business-queries, constructing-people-queries, constructing-property-queries. For people specifically: `currentAddress.state:CA AND age:[25 TO 35]`.","oneOf":[{"type":"string"},{"type":"object"}]},"sort":{"type":"boolean","default":true},"view":{"description":"Controls which fields come back on each record. A string names a view — either one of the data type's default views or one of your own saved views. An array is treated as an ad-hoc, one-off view: each entry is either a plain field name (e.g. `\"descriptions\"`) or `{\"name\": \"<field>\"}` when you also need `alias`/`flatten`. Use the plain field name to get a whole nested field (e.g. `\"descriptions\"` or `{\"name\": \"descriptions\"}` returns every sub-field of each description), or dot notation to pull just one sub-field (e.g. `\"descriptions.value\"`). Omit to get the default preview view.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"flatten":{"type":"boolean"}},"required":["name"]}}]},"download":{"type":"boolean","default":false,"description":"If true, this becomes an async download request instead of a search — the response is a Download object, and `num_records` becomes required (poll GET /downloads/{download_id})."},"auto_trace":{"type":"boolean","default":false},"fuzzy_match":{"type":"string","enum":["on","off","retry"],"default":"on"},"only_traceable":{"type":"boolean","description":"Only valid alongside auto_trace. See auto_trace."}}}}}},"responses":{"200":{"description":"Search results, a count, or a Download object, depending on the request body.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/people/{record_id}":{"get":{"operationId":"getPeopleRecord","summary":"Fetch a single people record by id","parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/products/search":{"post":{"operationId":"searchProducts","summary":"Search, count, or download products","description":"Query the Datafiniti products index. This one endpoint does three things based on the request body: a plain query searches and returns up to 50 records; `num_records: 0` counts matches with no records returned and no credit cost; `download: true` starts an async download job instead (requires `num_records`), returning a Download object to poll via GET /downloads/{download_id}. Example: `brand:Samsung AND categories:televisions`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"num_records":{"type":"integer","minimum":1,"description":"Number of records to return (search), or the download size when `download` is true. `num_records: 0` triggers a count instead of a search — see this operation's description."},"format":{"type":"string","enum":["json","csv","JSON","CSV"],"default":"json"},"query":{"description":"Lucene syntax. Examples: boolean — `categories:laptops AND brand:Apple`; negation with `-` — `categories:laptop AND -brand:Apple` excludes Apple; parentheses for grouping — `(categories:laptops OR categories:desktops) AND brand:Apple`; nested field, dot notation — `prices.amountMin:3`; range — `dateAdded:[2017-01-01 TO 2017-02-01]` or `prices.amountMin:>10`; compound query on a single nested sub-object — curly braces require every condition inside them to match the *same* nested array entry, not just any entry across the array: `{ reviews.rating:5 AND reviews.userProvince:Austin }` finds a product with one review that is both 5-star and from Austin, as opposed to `reviews.rating:5 AND reviews.userProvince:Austin` without braces, which would also match a 5-star review from anywhere plus a separate Austin review of any rating. Canonical example per data type: businesses — `categories:hotels AND province:TX`; people — `currentAddress.state:CA AND age:[25 TO 35]`; products — `brand:Samsung AND categories:televisions`; properties — `city:Austin AND yearBuilt:[2015 TO 2024]`. Full reference (syntax is shared across data types): https://docs.datafiniti.co/docs/constructing-product-queries — data-type-specific variants: constructing-business-queries, constructing-people-queries, constructing-property-queries. For products specifically: `brand:Samsung AND categories:televisions`.","oneOf":[{"type":"string"},{"type":"object"}]},"sort":{"type":"boolean","default":true},"view":{"description":"Controls which fields come back on each record. A string names a view — either one of the data type's default views or one of your own saved views. An array is treated as an ad-hoc, one-off view: each entry is either a plain field name (e.g. `\"descriptions\"`) or `{\"name\": \"<field>\"}` when you also need `alias`/`flatten`. Use the plain field name to get a whole nested field (e.g. `\"descriptions\"` or `{\"name\": \"descriptions\"}` returns every sub-field of each description), or dot notation to pull just one sub-field (e.g. `\"descriptions.value\"`). Omit to get the default preview view.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"flatten":{"type":"boolean"}},"required":["name"]}}]},"download":{"type":"boolean","default":false,"description":"If true, this becomes an async download request instead of a search — the response is a Download object, and `num_records` becomes required (poll GET /downloads/{download_id})."},"auto_trace":{"type":"boolean","default":false},"fuzzy_match":{"type":"string","enum":["on","off","retry"],"default":"on"},"only_traceable":{"type":"boolean","description":"Only valid alongside auto_trace. See auto_trace."}}}}}},"responses":{"200":{"description":"Search results, a count, or a Download object, depending on the request body.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/products/{record_id}":{"get":{"operationId":"getProductsRecord","summary":"Fetch a single products record by id","parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/properties/search":{"post":{"operationId":"searchProperties","summary":"Search, count, or download properties","description":"Query the Datafiniti properties index. This one endpoint does three things based on the request body: a plain query searches and returns up to 50 records; `num_records: 0` counts matches with no records returned and no credit cost; `download: true` starts an async download job instead (requires `num_records`), returning a Download object to poll via GET /downloads/{download_id}. Example: `city:Austin AND yearBuilt:[2015 TO 2024]`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"num_records":{"type":"integer","minimum":1,"description":"Number of records to return (search), or the download size when `download` is true. `num_records: 0` triggers a count instead of a search — see this operation's description."},"format":{"type":"string","enum":["json","csv","JSON","CSV"],"default":"json"},"query":{"description":"Lucene syntax. Examples: boolean — `categories:laptops AND brand:Apple`; negation with `-` — `categories:laptop AND -brand:Apple` excludes Apple; parentheses for grouping — `(categories:laptops OR categories:desktops) AND brand:Apple`; nested field, dot notation — `prices.amountMin:3`; range — `dateAdded:[2017-01-01 TO 2017-02-01]` or `prices.amountMin:>10`; compound query on a single nested sub-object — curly braces require every condition inside them to match the *same* nested array entry, not just any entry across the array: `{ reviews.rating:5 AND reviews.userProvince:Austin }` finds a product with one review that is both 5-star and from Austin, as opposed to `reviews.rating:5 AND reviews.userProvince:Austin` without braces, which would also match a 5-star review from anywhere plus a separate Austin review of any rating. Canonical example per data type: businesses — `categories:hotels AND province:TX`; people — `currentAddress.state:CA AND age:[25 TO 35]`; products — `brand:Samsung AND categories:televisions`; properties — `city:Austin AND yearBuilt:[2015 TO 2024]`. Full reference (syntax is shared across data types): https://docs.datafiniti.co/docs/constructing-product-queries — data-type-specific variants: constructing-business-queries, constructing-people-queries, constructing-property-queries. For properties specifically: `city:Austin AND yearBuilt:[2015 TO 2024]`.","oneOf":[{"type":"string"},{"type":"object"}]},"sort":{"type":"boolean","default":true},"view":{"description":"Controls which fields come back on each record. A string names a view — either one of the data type's default views or one of your own saved views. An array is treated as an ad-hoc, one-off view: each entry is either a plain field name (e.g. `\"descriptions\"`) or `{\"name\": \"<field>\"}` when you also need `alias`/`flatten`. Use the plain field name to get a whole nested field (e.g. `\"descriptions\"` or `{\"name\": \"descriptions\"}` returns every sub-field of each description), or dot notation to pull just one sub-field (e.g. `\"descriptions.value\"`). Omit to get the default preview view.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"alias":{"type":"string"},"flatten":{"type":"boolean"}},"required":["name"]}}]},"download":{"type":"boolean","default":false,"description":"If true, this becomes an async download request instead of a search — the response is a Download object, and `num_records` becomes required (poll GET /downloads/{download_id})."},"auto_trace":{"type":"boolean","default":false},"fuzzy_match":{"type":"string","enum":["on","off","retry"],"default":"on"},"only_traceable":{"type":"boolean","description":"Only valid alongside auto_trace. See auto_trace."}}}}}},"responses":{"200":{"description":"Search results, a count, or a Download object, depending on the request body.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/properties/{record_id}":{"get":{"operationId":"getPropertiesRecord","summary":"Fetch a single properties record by id","parameters":[{"name":"record_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/downloads/{download_id}":{"get":{"operationId":"getDownloadStatus","summary":"Poll the status of a download started via POST /:data_type/search with download: true","parameters":[{"name":"download_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The Download object, including status and, once complete, result file links.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Feature not enabled, or field not permitted for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}}}}