search_businesses
Search the CoreLoop business directory. Start here: every other tool on this endpoint needs a business, and each result carries the business_id and slug you pass to them as the business argument. business_id is a PUBLIC, OPAQUE, STABLE routing identifier: it is safe to store and re-use across sessions, it stays the same when a business renames itself or changes its slug, and it carries no sensitive information. Treat it as a token — do not parse it, do not derive meaning from its format, and do not construct one. Pass back exactly the value you were given. A result with asserts_no_physical_location: true has stated that it has no premises (consultants, trades, online-only) — it is intentionally absent from city search rather than missing data. false means no such statement was made; it does NOT imply premises. Results are returned in your requested language when the business has published a translation: send ?locale=<code> on the endpoint URL (takes precedence) or an Accept-Language header. Each result reports the language it is written in (locale), the business's original language (content_locale), and every language it is available in (available_locales). mcp_url, a2a_url and page_url — and every URL inside protocol_urls — are null when that surface is currently switched off for the business: a null is intentional (do not construct the URL yourself), and the business remains reachable through its non-null surfaces. data_source: "directory" marks these rows as the search projection; call get_business_info for the live profile. PAGING: one call returns at most limit results. Read has_more — a short page is not proof of the end — and pass next_cursor back as cursor for the next page. The cursor is opaque and bound to the filters and sort it was issued for: change any of them and it is rejected, so start a new search instead. limit may change between pages.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | Filter by city (case-insensitive exact match) | |
| limit | No | Maximum results per page (1-20). Out-of-range values are clamped, not rejected. | |
| query | No | Search query (business name or keyword) | |
| cursor | No | Continuation token from a previous response's `next_cursor`. Omit for the first page. It is opaque and bound to the filters and sort it was issued for: pass it back byte-for-byte, and change nothing except `limit` between pages — any other change makes it invalid and you must start a new search. At most 100 results are reachable by paging; narrow the filters to see beyond that. | |
| sort_by | No | Sort results. Default: relevance | |
| category | No | Filter by business category (case-insensitive exact match). Canonical categories: Accounting & Tax, Agriculture & Farming, Automotive, Beauty & Wellness, Childcare & Family, Cleaning Services, Construction & Renovation, Creative & Arts, Education & Training, Events & Entertainment, Financial Services, Fitness & Sports, Food & Beverage, Funeral & Memorial, Health & Medical, Home Services, Legal Services, Media & Photography, Nonprofit & Community, Personal Care & Therapy, Pets & Animals, Professional Services, Real Estate, Religious & Spiritual, Retail & Shopping, Security Services, Sports & Recreation, Technology & IT, Transportation & Logistics, Travel & Tourism, Other | |
| min_rating | No | Minimum average rating (0-5) | |
| capabilities | No | Filter by capability tags (e.g. real_time_booking, live_pricing, verified) | |
| service_type | No | Filter by service type keyword | |
| verified_only | No | Only show verified businesses | |
| has_live_booking | No | Only show businesses with real-time booking | |
| has_live_catalog | No | Only show businesses with live catalog pricing |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| has_more | No | True when more results exist beyond this page. Read this rather than inferring from `returned_count`: a short page is not proof of the end. | |
| businesses | No | ||
| next_cursor | No | Opaque continuation token, or null on the last page. Pass it back unchanged as `cursor` to get the next page. It is bound to this search's filters and sort — change them and it is rejected, so start a new search instead. Do not parse, modify or construct one. | |
| returned_count | No | ||
| requested_locale | No |