Datasets API endpoint
Returns the values of one field of the BBB businesses index (dataset id enum value `bbb-businesses`) with the number of records for each, honoring the same filters as search. Facet enum: `country`, `address_country`, `category`, `state`, `city`, `rating`, `accredited`, `entity_type`, `run_id`, `alert_title`, `has_alerts`. The `country` facet is parsed from profile URLs; `address_country` is derived from business addresses. Both enums are `us`, `ca`. Values come most frequent first, 50 per page by default; page through all of them with `limit` (up to 1000) and `offset` while `has_more` is true. The response also returns `total` (records matching the filters), `total_values` (distinct values) and `missing` (records with no value for the facet), so the counts can be checked against the total. Values of the `accredited` and `has_alerts` facets are `1` (true) and `0` (false). Use it to split a search that would exceed 10,000 records: `facet=state` lists every state and province, and `facet=city` with a `state` filter lists every city in it.
/datasets/bbb-businesses/facetsDataset id enum:
bbb-businessesQuery parameters:
facet: required facet to aggregate. Allowed values: country, address_country, category, state, city, rating, accredited, entity_type, run_id, alert_title, has_alerts. A request without it returns 400.limit: optional values per page, 1 to 1000, default 50.offset: optional number of values to skip, 0 or greater, default 0. offset + limit must not exceed 10000.q: optional full-text match on the business name/category, max 256 characters.category: optional exact category filter, e.g. Plumber (case-sensitive). Use the values returned by facet=category.country: optional country filter parsed from the profile URL (case-insensitive). Allowed values: us, ca.address_country: optional country filter derived from the business address (case-insensitive). Allowed values: us, ca.state: optional exact 2-letter state or province code as in the profile URL, e.g. tx (case-insensitive). Use the values returned by facet=state.city: optional exact city slug as in the profile URL, e.g. san-diego (case-insensitive). Use the values returned by facet=city with a state filter.rating: optional exact letter-grade rating filter. Allowed values: A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F.min_rating_rank: optional numeric floor against the numeric rating rank (A+=12 down to F=0), e.g. 10 for "A- and above".accredited: optional accreditation filter; true keeps only accredited businesses, false only the others.has_alerts: optional BBB-alert filter; true keeps businesses whose profile carries at least one BBB alert, false keeps refreshed records with none.alert_title: optional exact BBB alert title filter, e.g. Pattern of Complaint (case-sensitive). Use the values returned by facet=alert_title.min_complaints: optional floor against total_complaints (BBB's three-year complaint count), 0 or greater.entity_type: optional exact entity-type filter, e.g. Limited Liability Company (LLC) (case-sensitive). Use the values returned by facet=entity_type.run_id: optional exact crawl run id filter, e.g. bbb-20260906. Use the values returned by facet=run_id.Errors:
400 when facet is missing or not an allowed value, when a country or rating value is not in its list, when limit is outside 1..1000, when offset is negative, or when offset + limit exceeds 10000. The reason is in the data field of the error body.Response fields:
dataset: always bbb-businesses.facet: the facet that was aggregated.items: one page of { "value", "count" }. value is what to send as the matching filter; count is the number of matching records with that value.total: records matching the filters.total_values: distinct values of the facet across all pages.missing: matching records that have no value for the facet. For a single-valued facet, the counts of all values plus missing equal total.limit, offset: the page that was returned.has_more: true while another page exists. Request offset + limit next.values_truncated: present and true only when the facet has more than 10,000 values, which is as far as offset can reach. Add a filter to split it; total_values is then an estimate.Listing every value, and reading more than 10,000 records:
limit=1000 and offset=0, 1000, 2000, ... until has_more is false.facet=state (optionally with country=us) lists every state and province, then facet=city&state=<state> lists every city in it, and search?state=<state>&city=<city> reads that part. facet=city without a state filter has more than 10,000 values and the same city name exists in several states, so always facet cities per state.category with state when splitting by category. Records with no category are counted in missing.Response behavior:
accredited and has_alerts values are "1" (true) and "0" (false).facet=category returns the category values to use as the category search/facet filter, with counts.facet=country and facet=address_country return separate counts for the country parsed from the profile URL and the country derived from the business address. Both use us and ca values.facet=alert_title returns the BBB alert titles present in the dataset (for example Pattern of Complaint, Licensing) with the number of businesses carrying each; facet=has_alerts splits refreshed records into those with and without alerts. Records not re-crawled since the alert fields were added are in neither bucket.facet=rating is useful to see the letter-grade distribution across the currently-filtered slice of the dataset.items array (not an error) when the dataset has no data yet.| Field | Filled in, of 20 checked | Values in the sample |
|---|---|---|
| value | 20 | |
| count | 20 | 3,187 to 15,076, median 4,361 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| facet | string | Yes | Facet enum: country, address_country, category, state, city, rating, accredited, entity_type, run_id, alert_title, has_alerts Allowed values: country, address_country, category, state, city, rating, accredited, entity_type, run_id, alert_title, has_alerts. | category | |
| limit | integer | No | 50 | Values per page, 1 to 1000, defaults to 50 | |
| offset | integer | No | 0 | Values to skip, 0 or greater, defaults to 0; offset + limit must be <= 10000. Request offset + limit next while has_more is true | |
| q | string | No | Full-text match on the business name/category, max 256 characters | ||
| category | string | No | Exact category filter, e.g. Plumber (case-sensitive). Use the values returned by facet=category | ||
| country | string | No | Country filter, parsed from the profile URL (case-insensitive). Enum: us, ca Allowed values: us, ca. | ||
| address_country | string | No | Country filter derived from the business address, separate from the profile-URL country (case-insensitive). Enum: us, ca Allowed values: us, ca. | ||
| state | string | No | Exact 2-letter state or province code as in the profile URL, e.g. tx (case-insensitive). Use the values returned by facet=state | ||
| city | string | No | Exact city slug as in the profile URL, e.g. san-diego (case-insensitive). Use the values returned by facet=city with a state filter | ||
| rating | string | No | Exact letter-grade rating filter. Enum: A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F Allowed values: A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F. | ||
| min_rating_rank | integer | No | Numeric floor against the denormalized rating rank (A+=12 down to F=0), e.g. 10 for 'A- and above' | ||
| accredited | boolean | No | Accreditation filter; true keeps only accredited businesses, false only the others | ||
| has_alerts | boolean | No | BBB-alert filter; true keeps businesses whose profile carries at least one BBB alert, false keeps refreshed records with none | ||
| alert_title | string | No | Exact BBB alert title filter, e.g. Pattern of Complaint (case-sensitive). Use the values returned by facet=alert_title | ||
| min_complaints | integer | No | Floor against total_complaints (BBB's three-year complaint count), 0 or greater | ||
| entity_type | string | No | Exact entity-type filter, e.g. Limited Liability Company (LLC) (case-sensitive). Use the values returned by facet=entity_type | ||
| run_id | string | No | Exact crawl run id filter, e.g. bbb-20260906. Use the values returned by facet=run_id | ||
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/datasets/bbb-businesses/facets?facet=category&limit=10&q=coffee&country=us&address_country=us&rating=A%2B&accredited=true&has_alerts=true" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"dataset": "bbb-businesses",
"facet": "rating",
"items": [
{
"value": "A+",
"count": 512
},
{
"value": "A",
"count": 210
},
{
"value": "A-",
"count": 88
},
{
"value": "B+",
"count": 34
}
],
"total": 900,
"missing": 56,
"total_values": 4,
"limit": 50,
"offset": 0,
"has_more": false
}
}Request schema
No body schema
Response schema
#/definitions/datasets.bbbBusinessesFacetResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | datasets.BBBBusinessesFacetResponse | No | ||||
| data.dataset | string | No | bbb-businesses | Dataset id, always bbb-businesses. | ||
| data.facet | string | No | city | The facet that was aggregated, as requested. | ||
| data.has_more | boolean | No | true | True while another page exists; request offset + limit next. | ||
| data.items | array | No | One page of values, most frequent first, ties in value order. | |||
| data.items[].count | integer | No | 3438 | Number of matching records with this value. | ||
| data.items[].value | string | No | san-diego | The facet value, to use as the matching search or facet filter. For the accredited and has_alerts facets it is 1 (true) or 0 (false). | ||
| data.limit | integer | No | 50 | Values per page that was applied. | ||
| data.missing | integer | No | 0 | Number of matching records that have no value for this facet. | ||
| data.offset | integer | No | 0 | Number of values skipped. | ||
| data.total | integer | No | 44730 | Number of records matching the filters. | ||
| data.total_values | integer | No | 1128 | Number of distinct values of the facet across all pages. | ||
| data.values_truncated | boolean | No | Present and true only when the facet has more than 10000 values, the furthest offset can reach; add a filter such as state to split it. total_values is then an estimate. | |||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 500 | Internal Server Error | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/datasets/bbb-businesses/facets?facet=category&limit=10&q=coffee&country=us&address_country=us&rating=A%2B&accredited=true&has_alerts=true" \
-H "x-api-key: $CRAWLORA_API_KEY"