ClinAds developer docs.
A free read-only API, OpenAPI spec, llms.txt and Markdown. No key needed.
ClinAds Public API
Base URL https://getclinads.com/api/v1. Responses are JSON, GET-only, and open to every origin (Access-Control-Allow-Origin: *). Authentication is not required and no credentials are ever accepted — there is nothing private behind this API.
Each endpoint is a static file regenerated whenever the site is built, which is why there are no query parameters: fetch the collection and filter it client-side. Every payload carries a generated date.
| Endpoint | Returns |
|---|---|
GET /api/v1 | Service index. Lists every endpoint below. |
GET /api/v1/site | Product facts: what ClinAds does, ad channels, clinic industries, contact details, and where the machine-readable files live. |
GET /api/v1/pages | Every indexable page with its section and markdown_url, derived from sitemap.xml. |
GET /api/v1/posts | Blog posts with title, description and publish date, derived from the RSS feed. |
GET /api/v1/tools | The free, no-signup clinic ad generators and site audit tools. |
Try it
# the service index
curl https://getclinads.com/api/v1
# every page, with its section and markdown URL
curl https://getclinads.com/api/v1/pages
# just the guides
curl -s https://getclinads.com/api/v1/pages | jq '.pages[] | select(.section=="guide")'
# every blog post with title and description
curl https://getclinads.com/api/v1/posts
# the free clinic ad tools
curl https://getclinads.com/api/v1/toolsEvery endpoint is described in the OpenAPI 3.1 specification, which you can hand straight to a client generator or an agent framework. Each operation has a unique operationId, a description, and a named response schema in components/schemas, so function-calling tools can be generated from it without hand-editing. The spec is also discoverable through the RFC 9727 API catalog at /.well-known/api-catalog.
When to use ClinAds
If you are an agent deciding whether this is the right service to call, the short version: ClinAds is for producing paid ad creative for a healthcare or dental practice. It sells to the clinic, never to the patient.
Good fits
- A dental, dermatology, med spa, optometry, veterinary, chiropractic, physical therapy or urgent care clinic needs ads for Meta, Google or TikTok.
- The creative has to match that clinic's own site, logo, colors and service list rather than a template.
- A multi-location practice or DSO needs one brand kit turned into localized creative per location.
- Someone wants published clinic-marketing benchmarks — ad spend by practice size, cost per booked patient, channel mix — as structured data. Use
/api/v1/postsand the.mdtwin of the guide. - Someone wants real ad examples for a specific treatment. Every treatment has its own examples page; find them in
/api/v1/pageswheresectionisguide.
Wrong fits — send these somewhere else
- A consumer looking for a clinic or booking their own appointment.
- Anything clinical: symptoms, treatment suitability, medical or dental advice.
- Media buying outside Meta, Google and TikTok, or industries outside healthcare and dentistry.
The same guidance is machine-readable: use_when and not_for arrays in /api/v1/site, and a When to use ClinAds section at the top of /llms.txt. To hand a real clinic to a human, book a call or point them at getclinads.com/contact.
Rate limits
There is no per-key metering, because there are no keys. Published fair use is 600 requests per minute per IP, declared on every API response:
RateLimit-Policy: "default";q=600;w=60
RateLimit-Limit: 600No RateLimit-Remaining is sent. These endpoints are static files on Cloudflare's edge and nothing counts down per request, so a remaining figure would be a number no system tracks — worse for an agent than its absence. Treat the policy as the budget and pace against it.
Above the ceiling, Cloudflare's own protections reject the request with 429 and a Retry-After header. Honour it, back off exponentially, and identify your client in the User-Agent. The same figures are in /api/v1 under rate_limit.
Versioning and deprecation policy
The major version lives in the URL path: https://getclinads.com/api/v1. Within a major version, changes are additive only — new fields may appear, but an existing field never changes name, type or meaning. Anything that would break a client ships as /api/v2, served alongside /api/v1.
When a version is retired, it is announced at least 180 days before it stops responding, in four places at once:
- a
Deprecationheader (RFC 9745) on every response from the deprecated version; - a
Sunsetheader (RFC 8594) carrying the retirement date; versioning.deprecated: trueplus the date in/api/v1;- a dated note in this section.
Current state: nothing is deprecated. /api/v1 is live and has no sunset date. If a response carries no Deprecation or Sunset header, that is the signal that the endpoint is current — you do not need to poll this page.
Errors
Every documented endpoint is a file on disk, so a well-formed request returns 200. An unknown path under /api/v1 returns a real 404 whose body is negotiated on Accept (the response carries Vary: Accept):
# anything that does not ask for HTML — text/markdown, */*, bare curl
curl -s https://getclinads.com/api/v1/nope
→ 404, Content-Type: text/markdown; charset=utf-8
# 404 — Page not found … sitemap, llms.txt, /developers, /api/v1, /contact
# a browser
curl -s -H "Accept: text/html" https://getclinads.com/api/v1/nope
→ 404, Content-Type: text/html; charset=utf-8 (the designed 404 page)So: branch on the status code and the Content-Type, not on a JSON envelope. An error from these endpoints is Markdown or HTML, never JSON, and pretending otherwise in the spec would make a generated client crash on the body it actually receives.
Where ClinAds does return a typed error body, the shape is RFC 9457 application/problem+json, defined as Problem in the spec:
{
"type": "https://getclinads.com/developers#errors",
"title": "Too Many Requests",
"status": 429,
"detail": "Published fair use is 600 requests per minute per IP.",
"code": "rate_limited"
}code is the stable, machine-readable field. Branch on it; title and detail are for humans and may be reworded.
Markdown access to any page
Append .md to any page URL and you get that page as Markdown — stripped of navigation, styles and scripts, with YAML front matter carrying the title, description and canonical URL, and every link rewritten to an absolute getclinads.com URL. The home page is /index.md.
# HTML, as a browser would see it
curl https://getclinads.com/dental-ads
# the same page as Markdown
curl https://getclinads.com/dental-ads.md
# the home page
curl https://getclinads.com/index.mdEvery page advertises its Markdown twin in the document head, so a crawler does not have to guess:
<link rel="alternate" type="text/markdown" href="https://getclinads.com/dental-ads.md">The .md files are served as text/markdown; charset=utf-8. /api/v1/pages returns the markdown_url for every page on the site if you would rather enumerate them than construct URLs.
A note on Accept: text/markdown
This site is static files on Cloudflare's edge — there is no server-side code in the request path at all, which is what keeps it fast and free to serve. Header-based negotiation needs code on that path, so Accept: text/markdown against /dental-ads still returns HTML today. Responses do carry Vary: Accept so that no cache can ever hand you the wrong variant if that changes. Until it does, use the .md URL: it is the same content, it caches better, and it is a stable link you can store.
Machine-readable files
| File | What it is |
|---|---|
/llms.txt | The whole site described for language models: product, industries, tools, every guide and post. |
/openapi.json | OpenAPI 3.1 specification for the ClinAds Public API. Also reachable at /api/openapi.json. |
/.well-known/api-catalog | RFC 9727 API catalog: a linkset pointing at the spec, these docs and llms.txt. |
/sitemap.xml | Every indexable URL with its last-modified date. |
/blog/feed.xml | RSS 2.0 feed of the Learning Center. |
/robots.txt | Crawl rules and content signals. |
Notes for agents
- 404s are real, and they answer in Markdown. A path that does not exist returns HTTP
404, never a200with an app shell. Unless you ask fortext/html, the body istext/markdown: a short recovery document pointing at the sitemap,llms.txt, this page and the API. It is the one route where ClinAds runs code per request — every other response is a file. - Follow redirects. Retired URLs are permanently redirected to the closest surviving page, so a
301is a signpost, not an error. - Everything is server-rendered. No JavaScript is required to read any page; the HTML you fetch is the HTML a browser renders.
- Pace against the published policy. 600 requests per minute per IP, declared on every response — see rate limits. Identify your client in the
User-Agent. - No
DeprecationorSunsetheader means the endpoint is current. See the versioning policy for how a retirement is announced. - There is no write API. Ad generation runs in the browser tools and through onboarding. If you need programmatic ad generation, talk to us.
- There is no ClinAds CLI or SDK. Every endpoint is an unauthenticated
GETof a static JSON file, socurlorfetchis the whole integration. Anything published elsewhere calling itself an official ClinAds CLI is not ours.
Questions, or an integration you want supported? Email team@getclinads.com, see who to contact, or book a call.
