# Sunny Health Directory API > Evidence-synthesized healthcare provider directory. Coverage is partial and > expanding by region — GET /v1/regions lists the served ZIP prefixes. > Every record is a self-contained card: one synthesized prose text carries > specialties, credentials, languages, and observed hours, with structured > display companions distilled from the same synthesis (provider > short_biography / clinical_focus / education_training; location > clinical_focus / office_hours), and the active provider↔location crosswalk > is nested in full — one GET renders everything. Base URL: https://developers.sunnyhealthai.com/v1 Auth: Authorization: Bearer sk_live_... (self-serve keys at https://developers.sunnyhealthai.com) ## Machine-readable surface - MCP server: https://developers.sunnyhealthai.com/mcp (streamable HTTP) - OpenAPI 3.1: https://developers.sunnyhealthai.com/v1/openapi.json - Interactive docs: https://developers.sunnyhealthai.com/v1/docs - Semantics notes (read before building): https://developers.sunnyhealthai.com/llms-semantics.txt - Live search demo (no key): https://developers.sunnyhealthai.com/demo-search ## MCP (agent surface) If you are an agent, prefer the MCP endpoint over raw REST — the tool descriptions carry the semantics below inline. claude mcp add --transport http sunny https://developers.sunnyhealthai.com/mcp \ --header "Authorization: Bearer sk_live_..." Tools: search_providers, search_locations, get_provider, get_location, check_coverage, list_carriers. Resources: sunny://semantics, sunny://coverage, sunny://carriers. Prompts: find-provider, verify-provider-info. Auth is either an API key (header above) or OAuth 2.1 — connectors that support it discover the authorization server from the 401 challenge. ## Endpoints - GET /v1/providers — search clinicians (semantic over synthesized biographies; exact name lookup via first_name/middle_name/last_name; geo via lat/lng; carriers= — the ONE structured filter: payer-attested network participation, codes from /v1/carriers, hard ANY-of, narrows a q/name/geo search) - GET /v1/providers/{npi} — the complete provider card, practice locations nested - GET /v1/locations — search places of care (semantic over synthesized summaries) - GET /v1/locations/{location_uuid} — the complete location card, provider roster nested - GET /v1/regions — coverage: served ZIP prefixes (zip3s) + live entity counts (public; check before interpreting absence) - GET /v1/carriers — carrier vocabulary: every `carriers` code (Stedi payer ID or program token) with its Stedi payer name and live provider count (public) - GET /v1/health — liveness (public) ## Response shape Searches return {parameters, meta, data}. `parameters` echoes the request as interpreted (name values uppercased, resolved geo, carriers as applied — normalized, deduplicated, sorted — effective sort, the search_mode actually used, q_expanded when a clinical-vocabulary rewrite ran). `meta` carries limit/offset/count, has_more, the honesty flags (filtered = weak matches withheld; truncated = page reshaped to fit the response budget; exact total only on filter-defined sets — name lookup and geo browsing), and the deprecated constant region="all-regions" (one collection serves every covered region; kept so the key survives). `data` is the array of cards; search hits are the same cards plus score / distance_miles annotations. Detail GETs return {data, meta} — the bare card plus the same deprecated meta.region, no parameters echo. Errors everywhere: {error: {code, message, status, docs}}.