---
title: "Search the BBB businesses dataset"
method: GET
path: "/datasets/bbb-businesses/search"
tags: ["Datasets"]
---

# Search the BBB businesses dataset

`GET /datasets/bbb-businesses/search`

## Request

- Base URL: `https://api.crawlora.net/api/v1`
- URL: `https://api.crawlora.net/api/v1/datasets/bbb-businesses/search`
- Auth: API key in header `x-api-key`

Searches the BBB (Better Business Bureau) businesses index (dataset id enum value `bbb-businesses`) — business profiles crawled from bbb.org's own search/category-browse pages: computed A+-F letter-grade rating, paid-accreditation status, category, contact info, business details, operating hours, and products/services. Complaints, full reviews, and the full "reasons for rating"/service-area detail are NOT embedded here; each record instead carries complaints_url/reviews_url/more_info_url pointing at the live bbb-business-complaints/bbb-business-reviews/bbb-business-more-info endpoints for on-demand lookup. rating enum: `A+`, `A`, `A-`, `B+`, `B`, `B-`, `C+`, `C`, `C-`, `D+`, `D`, `D-`, `F`. Each record also stores BBB's complaint and review counts (total_complaints and related fields) and the BBB alerts on the profile (has_alerts, alert_titles, alerts[] with full text), so businesses with complaints or with a given alert can be listed without calling the live endpoints; these fields are filled as records are re-crawled and are absent on a record not refreshed since they were added. `country` is parsed from the profile URL; `address_country` is derived separately from the business address. Both enums are `us`, `ca`. sort enum: `relevance`, `rating_desc`, `rating_asc`, `accredited_first`, `name_asc`, `years_in_business_desc`, `complaints_desc`. A query returns at most 10,000 records; to read more, split it with the values and counts from the facets endpoint (for example one request per state, then per city) so each part stays under that limit. Billing: this search costs 1 credit per record returned, with a minimum of 2 (an empty result costs 2, a full page of 100 costs 100); the item and facets endpoints cost 1.

## Query parameters

- `q` string
- `category` string
- `country` 'us' | 'ca'
- `address_country` 'us' | 'ca'
- `state` string
- `city` string
- `rating` 'A+' | 'A' | 'A-' | 'B+' | 'B' | 'B-' | 'C+' | 'C' | 'C-' | 'D+' | 'D' | 'D-' | 'F'
- `min_rating_rank` integer
- `accredited` boolean
- `has_alerts` boolean
- `alert_title` string
- `min_complaints` integer
- `entity_type` string
- `run_id` string
- `sort` 'relevance' | 'rating_desc' | 'rating_asc' | 'accredited_first' | 'name_asc' | 'years_in_business_desc' | 'complaints_desc'
- `page` integer
- `page_size` integer

## Headers

- `x-api-key` string, required

## Response `200`

OK

- DatasetsBbbBusinessesSearchResponseDoc
  - `code` integer
  - `data` DatasetsBBBBusinessesSearchResponse
    - `dataset` string
    - `items` EsBBBBusinessRecord[]
      - `accredited` boolean
      - `accredited_since` string
      - `additional_phone_numbers` string[]
      - `additional_websites` string[]
      - `address` string
      - `address_country` 'us' | 'ca': AddressCountry is derived from the recognized US state/territory/military or Canadian province code at the end of Address. Empty when unrecognized.
      - `alert_titles` string[]
      - `alerts` EsBBBBusinessAlert[]
        - `id` string
        - `links` EsBBBBusinessAlertLink[]
          - `text` string
          - `url` string
        - `text` string
        - `title` string
        - `type_id` integer
        - `url` string
      - `alternate_names` string[]
      - `average_review_rating` number
      - `bbb_file_opened` string
      - `bbb_local_id` string
      - `business_id` string
      - `business_incorporated` string
      - `business_management` string
      - `business_started` string
      - `categories` string[]
      - `category` string
      - `city` string
      - `complaints_closed_last_12_months` integer
      - `complaints_closed_last_3_years` integer
      - `complaints_url` string: On-demand pointers -- not crawled/embedded, see package doc above.
      - `country` string: State/City are parsed from the profile URL's /us|ca/<state>/<city>/... path segments -- BusinessResponse.Address is a free-text joined string, not structured, so it isn't a reliable filter/facet field on its own.
      - `crawled_at` string
      - `discovery_source` string: Crawl bookkeeping. DiscoverySource records how the CURRENT document content was obtained (last-crawl mechanism), not first-discovery provenance -- keyword-sweep, category-grid, and Common Crawl discovery are deduplicated against the same business, so the same business is never double-enqueued no matter how many search/category cells or CC records surface it. A richer per-discovery-event location/category isn't tracked, only the coarse source.
      - `entity_type` string
      - `has_alerts` boolean: HasAlerts, AlertTitles and Alerts describe the notices BBB attaches to the profile (pattern of complaints, investigation results, licensing findings). A refreshed record with no alerts carries has_alerts=false and empty lists; a record not re-crawled since these were added has none of the keys.
      - `hours` EsBBBBusinessHoursDay[]
        - `day` string
        - `hours` string
      - `licensing_note` string
      - `more_info_url` string
      - `name` string
      - `phone` string
      - `products_and_services` string[]
      - `rating` string
      - `rating_rank` integer
      - `rating_reasons` string[]
      - `reviews_url` string
      - `run_id` string
      - `schema_version` integer
      - `social_media` string[]
      - `state` string
      - `total_complaints` integer: Complaint and review counts from the profile page, the same values bbb-business returns. A record not re-crawled since these were added has none of the keys until its next refresh, and a count BBB did not publish is likewise absent, so 0 is a real zero.
      - `total_reviews` integer
      - `url` string
      - `website` string
      - `years_in_business` string
      - `years_in_business_num` integer: YearsInBusinessNum is a best-effort leading-digit parse of YearsInBusiness (a free-text upstream string, e.g. "3"), -1 when unparseable. Denormalized purely for numeric sorting -- YearsInBusiness itself stays a keyword, so a lexicographic string sort would wrongly rank "9" ahead of "12".
    - `page` integer
    - `page_size` integer
    - `sort` string
    - `total` integer
  - `msg` string

## Other responses

- `400`: Bad Request
- `429`: Too Many Requests
- `500`: Internal Server Error

---

[API](https://skmtc.dev/crawlora/apis/crawlora-api.md) · [All operations](https://skmtc.dev/crawlora/apis/crawlora-api/llms.txt) · [OpenAPI document](https://skmtc.dev/crawlora/apis/crawlora-api/revisions/0497899e2016?raw)
