openapi: 3.1.0 info: title: Aerin Medical Site API (WordPress REST) version: em-locator/v1 + aerin + wp/v2 summary: Anonymously callable REST surface served by aerinmedical.com — the ENT doctor locator (1,012 treating locations), site search, and the site's form-submission endpoints. description: 'Aerin Medical is a medical-device company and operates no developer API product: it publishes no developer portal, no API documentation, no keys, no SDKs and no terms of use for programmatic access. Its corporate site, aerinmedical.com, does however serve a WordPress REST API at `https://aerinmedical.com/wp-json` with 321 registered routes across 15 namespaces. Most of the standard `wp/v2` content routes (posts, pages, media, users, taxonomies, types) are BLOCKED to anonymous callers by the iThemes Security plugin and return HTTP 401 `itsec_rest_api_access_restricted` — so, unlike most WordPress sites, the content library here is not machine-readable. What IS anonymously readable is the company''s own first-party doctor-finder plugin (`em-locator/v1`, the surface behind https://aerinmedical.com/find-ent-doctor/), the cross-content `wp/v2/search` index, the route discovery documents, and a small set of `aerin`-namespace POST endpoints that back the site''s lead-capture and NOSE-score assessment forms. This document was DERIVED by API Evangelist from the provider''s own live route index (`GET https://aerinmedical.com/wp-json/`) plus direct anonymous probing of each route, on 2026-07-31. Every path, method, parameter name, enumeration and response field is taken from that index or from an observed HTTP 200 response; nothing was invented. Routes observed to return 401 anonymously are deliberately omitted. The `aerin` namespace POST routes are listed because they are really registered and really public, but they declare NO argument schema in the route index and they have side effects (they submit leads / contact requests / newsletter sign-ups into the company''s systems), so they were NOT invoked and no request body is documented for them. Treat this as an incidental site surface, not a supported product API. Aerin Medical offers no availability, versioning or support commitment for it.' contact: name: Aerin Medical, Inc. url: https://aerinmedical.com/contact-us/ email: customerservice@aerinmedical.com x-origin: - url: https://aerinmedical.com/wp-json/ format: wordpress-rest-route-index version: wp/v2 x-apievangelist-method: derived x-apievangelist-derived-from: https://aerinmedical.com/wp-json/ (live route index + per-route anonymous probes, fetched 2026-07-31) x-apievangelist-note: Incidental site API, not a product API. Derived by API Evangelist, not published by Aerin Medical. servers: - url: https://aerinmedical.com/wp-json description: aerinmedical.com WordPress REST API tags: - name: Discovery description: Route index / discovery documents. - name: Locator description: The Aerin doctor finder — treating ENT locations, filterable by product, designation, text and geography. - name: Search description: Cross-content-type site search. - name: Forms description: Site form-submission endpoints (lead capture, NOSE score assessments). Side-effecting; not invoked during derivation. - name: Embed description: oEmbed representations of aerinmedical.com URLs. paths: /: get: tags: [Discovery] operationId: getRouteIndex summary: Get the WordPress REST route index description: Returns the site's discovery document — name, home URL, the 15 registered namespaces, all 321 routes with their methods and declared arguments, and the supported authentication method (WordPress application passwords). responses: '200': description: The route index. content: application/json: schema: $ref: '#/components/schemas/RouteIndex' /aerin: get: tags: [Discovery] operationId: getAerinNamespaceIndex summary: Get the aerin namespace index description: Returns the route index scoped to Aerin Medical's own `aerin` namespace — the site's seven form-handling POST routes. parameters: - name: namespace in: query required: false schema: {type: string, default: aerin} - name: context in: query required: false schema: {type: string, default: view} responses: '200': description: The namespace index. content: application/json: schema: $ref: '#/components/schemas/RouteIndex' /em-locator/v1: get: tags: [Discovery] operationId: getLocatorNamespaceIndex summary: Get the em-locator namespace index responses: '200': description: The namespace index. content: application/json: schema: $ref: '#/components/schemas/RouteIndex' /em-locator/v1/locations: get: tags: [Locator] operationId: listTreatingLocations summary: List ENT locations trained on Aerin procedures description: 'Returns the treating locations behind https://aerinmedical.com/find-ent-doctor/ — 1,012 records as observed on 2026-07-31. Each record carries the practice name, formatted address, phone, latitude/longitude, the public location permalink, and pre-rendered HTML fragments used by the site''s map and result list. Pagination is standard WordPress: 10 records per page by default, with the total count in the `X-WP-Total` response header and the page count in `X-WP-TotalPages`. Supplying `lat` and `lng` switches the collection into proximity mode — results are ordered by distance and each record''s `distance` field becomes a number (miles) instead of `false`. The route index declares no arguments for this route; every parameter below was confirmed by observed behaviour (differing `X-WP-Total` / ordering / `distance` values) against the live endpoint. `product` and `designation` take the WordPress term IDs exposed by the locator form at `GET /em-locator/v1/locator`. CORS is open (`Access-Control-Allow-Origin: *`) and responses are cached (`Cache-Control: max-age=600, must-revalidate`).' parameters: - name: page in: query description: Page of the collection. Observed 102 pages at 10 per page. required: false schema: {type: integer, minimum: 1, default: 1} - name: per_page in: query description: Records per page. required: false schema: {type: integer, default: 10} - name: search in: query description: Free-text filter over practice name / city / state. Observed to narrow `X-WP-Total` (e.g. `search=Austin` → 44). required: false schema: {type: string} - name: lat in: query description: Latitude of the search origin. Supply together with `lng` to sort by proximity and populate `distance`. required: false schema: {type: number, format: double} - name: lng in: query description: Longitude of the search origin. Supply together with `lat`. required: false schema: {type: number, format: double} - name: product in: query description: Filter to locations offering one product, by term ID. Observed values — `697` RhinAer (783 locations), `698` VivAer (920 locations). required: false schema: type: string enum: ['697', '698'] x-enum-descriptions: {'697': RhinAer, '698': VivAer} - name: designation in: query description: Filter to Aerin Center of Excellence designations, by term ID or the `center-of-excellence` roll-up. Observed counts — any Center of Excellence 60, `699` Premier VivAer 17, `700` Advanced RhinAer 22, `701` Advanced VivAer 30, `702` Premier RhinAer 5. required: false schema: type: string enum: [center-of-excellence, '699', '700', '701', '702'] x-enum-descriptions: center-of-excellence: Any Center of Excellence '699': Premier VivAer '700': Advanced RhinAer '701': Advanced VivAer '702': Premier RhinAer responses: '200': description: 'A page of treating locations. `X-WP-Total` carries the full match count; an out-of-range page returns an empty array with `X-WP-Total: 0`.' headers: X-WP-Total: description: Total records matching the query. schema: {type: integer} X-WP-TotalPages: description: Total pages available. schema: {type: integer} Access-Control-Allow-Origin: description: Observed as `*`. schema: {type: string} content: application/json: schema: type: array items: $ref: '#/components/schemas/Location' /em-locator/v1/locator: get: tags: [Locator] operationId: getLocatorWidget summary: Get the rendered doctor-finder widget description: Returns the server-rendered HTML for the doctor-finder search widget, including the product and designation filter `