Best.Dentist — For AI Agents
Best.Dentist is an independent U.S. directory of dental practices, and an enquiry routing service, operated by ADPLUS MEDIA INC. It is not a dental practice, and it is not affiliated with the practices it lists. ("Best.Dentist" is a brand name, not a claim about any dentist.) The directory currently lists 65 practices in 13 cities, with 259 published fees collected from the practices' own websites.
If you are an AI assistant helping a user find a dentist, compare fees, or send an enquiry, this page documents exactly what you can do programmatically, what each response means, and the limits of the service. Please respect the limits: they are part of how the service works, not fine print.
What an agent can do
- Look up practices, services, cities and published fees through the JSON data feeds and the full-text dump listed below. No key or signup is required.
- Send an enquiry for your user by POSTing one JSON request. The enquiry is delivered to one matched practice — the exclusive partner for that city and service — and that practice contacts your user directly.
- Claim a profile on behalf of a practice (for practice owners or their representatives) by POSTing a claim. Claims are reviewed manually by a person.
- Add a new practice listing (for practices not yet listed) by POSTing a submission — see Action 3. New listings cost a flat $299 one-time fee and are verified manually before anything is published.
What this service does not do
- It does not confirm bookings or appointments. Submitting an enquiry is not a booking. The practice offers times and confirms any appointment when it contacts your user.
- It does not quote fees itself. The only fees here are the practices' own published fees (see the fee feeds). A fee for a specific user comes from the practice after contact.
- It does not provide dental or medical advice, diagnoses, or treatment recommendations.
- It never sells or shares a user's contact details with a list of practices. With the user's consent, details go to one matched practice (plus at most one backup practice if the first does not respond and the user agreed — see Timing).
Action 1: Send an enquiry
Send a POST request with a JSON body to the enquiry API:
- Canonical endpoint: POST https://best.dentist/api/enquiry
- Content type: application/json (form-encoded bodies are also accepted)
Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | Yes | The user's full name. |
| string | One of email or phone | Must be a valid email address if given. | |
| phone | string | One of email or phone | The user's phone number; at least 7 digits. |
| city_id | string | Yes | Must be a city_id from the cities feed, for example denver. |
| service_id | string | Yes | Must be a service_id from the services feed, for example implants. |
| practice_id | string | No | A specific practice_id from the practices feed, if the user picked one practice. Routing is still by city and service. |
| area | string | No | The user's neighbourhood or area of the city. Passed to the practice with the message. |
| message | string | No | Anything else the user wants the practice to know. Do not include detailed health information. |
| coverage | string | Yes | One of no, yes, unsure: whether the visit will be covered by Medicare, Medicaid or CHIP. If yes, the enquiry is routed as a free direct contact and is never billed. |
| source_page | string | No | URL the enquiry originated from, for attribution. |
| consent_collect | boolean | Yes, must be true | The user agreed Best.Dentist may collect their details and contact them about the enquiry. |
| consent_share | boolean | Yes, must be true | The user agreed Best.Dentist may share their details with the one named practice. |
| consent_backup | boolean | No | If true, the user agreed the enquiry may pass to one backup practice if the first does not confirm. |
| cf-turnstile-response | string | Yes | A valid Cloudflare Turnstile token. See the spam protection note below. |
| hp | string | No | Honeypot field. Leave it empty; filled honeypots are silently discarded. |
Example request
{
"name": "Jordan Example",
"email": "[email protected]",
"phone": "+1 303 555 0123",
"city_id": "denver",
"service_id": "implants",
"area": "Cherry Creek",
"message": "Interested in the published fee for a single implant.",
"coverage": "no",
"consent_collect": true,
"consent_share": true,
"consent_backup": false,
"cf-turnstile-response": "TURNSTILE_TOKEN"
}
Responses
| HTTP status | Body | Meaning |
|---|---|---|
| 200 | ok true, matched true, delivered true | A partner practice exists for this city and service, and the enquiry was delivered to it. The practice will contact the user directly. |
| 200 | ok true, matched true, delivered false | A partner practice exists, but live delivery failed and is being retried automatically. Do not resubmit. |
| 200 | ok true, matched false | There is no partner practice for this city and service yet. The enquiry is held, not discarded: if a partner practice later joins, the held enquiry is routed to it and that practice may contact the user. Do not promise the user they will be contacted. |
| 200 | ok true, consumer_direct true | The user said the visit may be covered by Medicare, Medicaid or CHIP. The enquiry is passed to the practice without charge; tell the user to contact the practice directly using its profile details. |
| 400 | ok false, errors list | Validation failed. Possible codes: name_required, phone_or_email_required, email_invalid, phone_invalid, city_invalid, service_invalid, practice_invalid, coverage_required, consent_required. Fix the fields and resubmit. |
| 403 | ok false, errors verification_failed | The Turnstile token was missing or invalid. Obtain a fresh token and resubmit. |
| 500 | ok false, error server_error | Temporary server problem. Wait and retry once. |
Success bodies are JSON objects with the fields shown; for example the delivered case returns an object with ok, matched and delivered all true.
Timing: what happens after a matched enquiry
- The matched practice is notified immediately (SMS and email) and is asked to accept the enquiry within about 15 business minutes. Business hours are 08:00 to 20:00 in the practice's local time, and the clock pauses outside business hours.
- If the practice does not accept in time, and the user gave backup consent, the enquiry cascades to one backup practice for that city and service, if one exists. A cascaded enquiry is never billed and never goes to more than two practices in total. Only the first successful delivery to the primary practice is ever billed.
- After accepting, the practice contacts your user directly — that is when fees, appointment times and any booking happen. Best.Dentist is not part of that conversation and cannot confirm, change or cancel appointments.
- There is no status-check endpoint yet. If your user has not heard from the practice within one business day, they can contact us at [email protected] and we will follow up.
Spam protection note (Turnstile)
The API is protected by Cloudflare Turnstile because it delivers messages to real businesses. The Turnstile site key is embedded in every enquiry form on best.dentist: load a form page, complete the Turnstile widget as the page presents it, and include the resulting token as cf-turnstile-response. Tokens are short-lived and single-use. If you cannot complete Turnstile, direct your user to the enquiry form on the relevant page of best.dentist instead of retrying the API.
Action 2: Claim a practice profile (for practices)
Practices can claim their free listing to correct it, add contact details, and receive enquiries from their profile page. Send a POST request with a JSON body:
- Canonical endpoint: POST https://best.dentist/api/claim
| Field | Type | Required | Notes |
|---|---|---|---|
| practice_id | string | Yes | Must be a practice_id from the practices feed. |
| contact_name | string | Yes | Name of the person claiming on behalf of the practice. |
| string | Yes | Business email; ownership is verified against the practice's own published contact details. | |
| phone | string | No | Optional contact phone. |
| cf-turnstile-response | string | Yes | Valid Cloudflare Turnstile token, as above. |
Responses: 200 with ok true when the claim is recorded (status pending). 400 with errors among practice_invalid, contact_name_required and email_invalid. 403 with verification_failed for a bad Turnstile token. Claims are reviewed manually; a submitted claim changes nothing on the listing until a person verifies ownership and approves it.
Action 3: Add a new practice listing (for practices not yet listed)
A practice that is not in the practices feed at all can be added as a new listing. New listings are paid: a flat $299 USD one-time fee covering manual verification against the practice's own website plus a full profile build-out (services, published fees, photos, hours). There is no free lane for new listings; claiming an existing listing (Action 2) is free. Human form: https://best.dentist/add-practice/. Send a POST request with a JSON body:
- Canonical endpoint: POST https://best.dentist/api/submit-practice
| Field | Type | Required | Notes |
|---|---|---|---|
| practice_name | string | Yes | The practice's trading name. |
| city_id | string | Yes | A city_id from the cities feed, or "other" if the city is not covered yet. |
| address | string | Yes | Street address. |
| website | string | Yes | The practice's own website URL — verification is done against it. |
| string | Yes | Public email; also becomes the practice's dashboard login. | |
| contact_name | string | Yes | Person submitting on behalf of the practice. |
| authorized | boolean | Yes | Must be true: the submitter is authorized to submit this practice and the information is accurate. |
| consent | boolean | Yes | Must be true: consent to store the details for verification and publication. |
| neighbourhood | string | No | Neighbourhood within the city. |
| zip | string | No | U.S. ZIP. |
| phone | string | No | Public phone number. |
| services | string[] | No | Service ids from the services feed that the practice offers. |
| fee_page_url | string | No | URL of the practice's published fee page (speeds up the build-out). |
| notes | string | No | Anything else the reviewer should know. |
| cf-turnstile-response | string | Yes | Valid Cloudflare Turnstile token, as above. |
Responses: 200 with ok true, status "pending_payment", listing_fee_usd 299 and payment_link (the Stripe checkout URL for the fee). Review starts only once the payment is confirmed; nothing is published before verification + approval. If the practice cannot be verified, or is already listed, the fee is refunded in full. 400 with errors among practice_name_required, city_invalid, address_required, website_invalid, email_invalid, contact_name_required, service_invalid, authorization_required, consent_required. 403 verification_failed (Turnstile). 409 duplicate_pending when a live submission already exists for the same website domain or email. 429 rate_limited (max 5 submissions per hour per IP).
Newly approved listings are published immediately as dynamic profiles and appear in the runtime practices feed below; they join the static practices feed at the next site rebuild.
Data feeds (no key required)
- Practices JSON: https://best.dentist/data/practices.json — every listed practice with its public fields and services. Phone numbers and websites appear only for practices that have claimed their profile; unclaimed practices are contacted through the enquiry API.
- Practices (runtime) JSON: GET https://best.dentist/api/practices-runtime — practices added between site rebuilds (approved new listings). Merge with the static practices feed on practice_id for the complete, current directory.
- Services JSON: https://best.dentist/data/services.json — the service taxonomy with ADA CDT examples and per-enquiry tiers.
- Cities JSON: https://best.dentist/data/cities.json — covered cities and metros.
- Fees JSON: https://best.dentist/data/fees.json — every published fee collected, per practice and service, in USD, with the source page and capture date for each row.
- Full text: https://best.dentist/llms-full.txt — the complete directory in one markdown file: every service with per-city published-fee counts from real published fees, and every practice with its fees.
- Summary: https://best.dentist/llms.txt — a short index of the site.
- API description: GET https://best.dentist/api/agent-info returns the machine-readable version of this page, and https://best.dentist/api/openapi.json is the OpenAPI 3 specification for the three POST endpoints.
Reading the fees
Fees in the feeds are the practices' own published fees, collected from their websites with the source URL and capture date on each row. They are comparison data, not quotes: practices confirm final pricing before treatment. In Florida and North Carolina, fees are shown with the practice's ADA CDT wording, as those states require.
Contact
- Human contact page (patients, practices, corrections and privacy requests): https://best.dentist/contact/
- Contact for agents, practices and users: [email protected] (the only public email for this service)
- This documentation in raw markdown: https://best.dentist/agents.md
This page is also available as raw markdown at /agents.md.