{
  "openapi": "3.1.0",
  "info": {
    "title": "CuraVerto public content endpoints",
    "version": "1.1.0",
    "summary": "Read-only endpoints that return CuraVerto's own published pages in machine-readable form.",
    "description": "Read-only, unauthenticated endpoints that return CuraVerto's own published pages in machine-readable form. They return no patient or clinic data. CuraVerto does not offer an open self-serve API for clinic records; access to a clinic's own data is arranged per clinic under agreement (sales@curaverto.com).\n\nErrors: every error from the JSON endpoints and from `/{slug}.md` is an RFC 9457 `application/problem+json` document with `type`, `title`, `status`, `detail`, plus the extension members `code` (stable, machine-readable) and `resolution` (what to do next). Error bodies never repeat the request path or query.\n\nVersioning: the JSON endpoint is versioned in its path (`/api/public/v1/`). Within a version, changes are additive only: fields may be added, never renamed or removed. A breaking change ships under a new path version. A version being retired will send `Deprecation` and `Sunset` response headers; no version is deprecated today. The markdown and sitemap endpoints are conventions of the site and are not versioned.\n\nRate limits: no request quota is enforced by the application today, and no rate-limit headers are returned. Be considerate; responses are cached for an hour.",
    "contact": {
      "name": "CuraVerto",
      "email": "sales@curaverto.com",
      "url": "https://curaverto.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://curaverto.com"
    }
  ],
  "paths": {
    "/api/public/v1/pages": {
      "get": {
        "operationId": "listPages",
        "summary": "List the published pages",
        "description": "Returns every indexable marketing page with its title, section, canonical URL and markdown twin URL. Use the optional `section` filter to narrow the list.",
        "parameters": [
          {
            "name": "section",
            "in": "query",
            "required": false,
            "description": "Return only pages in this section, for example `Compare` or `Solutions`. The allowed values are returned in the `sections` field of an unfiltered response.",
            "schema": {
              "type": "string",
              "examples": [
                "Compare"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The page list",
            "headers": {
              "API-Version": {
                "description": "Major version of this endpoint.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "1"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageList"
                }
              }
            }
          },
          "400": {
            "description": "The `section` value is not one of the allowed sections.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Method other than GET or HEAD.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Allow": {
                "description": "Methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET, HEAD"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "The server could not build the list.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Site index for AI agents",
        "description": "A markdown index of the site, with guidance on when to use CuraVerto and how an agent should use the site.",
        "responses": {
          "200": {
            "description": "Markdown index",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "The index plus the full text of the main pages",
        "description": "The llms.txt index followed by the full markdown of the main pages. Larger than llms.txt.",
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/{slug}.md": {
      "get": {
        "operationId": "getPageMarkdown",
        "summary": "A marketing page as markdown",
        "description": "Returns the markdown twin of a marketing page. The home page is `/index.md`.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Page path without the .md suffix. Use `index` for the home page, for example `pricing`, `about`, `contact`, `developers`, `solutions/dental`.",
            "schema": {
              "type": "string",
              "examples": [
                "pricing"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Method other than GET.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Allow": {
                "description": "Methods this endpoint accepts.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "GET"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/{path}": {
      "get": {
        "operationId": "getPageNegotiated",
        "summary": "A page at its own URL: markdown when Accept asks for it, HTML otherwise",
        "description": "Send `Accept: text/markdown` to receive the markdown twin at the page's own URL. Without it the response is HTML. The response varies on Accept.",
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "description": "Page path, for example `pricing`. The home page is `/`.",
            "schema": {
              "type": "string",
              "examples": [
                "pricing"
              ]
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "Set to `text/markdown` to receive markdown.",
            "schema": {
              "type": "string",
              "examples": [
                "text/markdown"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Markdown with `Vary: Accept` when text/markdown was requested, otherwise HTML",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page. With `Accept: text/markdown` the body is markdown that links to llms.txt and the sitemap.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "Every indexable page",
        "description": "The XML sitemap of every indexable page.",
        "responses": {
          "200": {
            "description": "Sitemap XML",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "An RFC 9457 problem document with two extension members.",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "resolution"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI identifying the problem type; it resolves to the error list on /developers.",
            "examples": [
              "https://curaverto.com/developers#error-not_found"
            ]
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary.",
            "examples": [
              "Not found"
            ]
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code.",
            "examples": [
              404
            ]
          },
          "detail": {
            "type": "string",
            "description": "Fixed explanation of this occurrence. Never repeats request input.",
            "examples": [
              "No resource exists at this address."
            ]
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code.",
            "enum": [
              "not_found",
              "method_not_allowed",
              "invalid_parameter",
              "internal_error"
            ]
          },
          "resolution": {
            "type": "string",
            "description": "What to do next.",
            "examples": [
              "Fetch https://curaverto.com/openapi.json for the endpoints that exist."
            ]
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "path",
          "title",
          "section",
          "url",
          "markdown_url"
        ],
        "properties": {
          "path": {
            "type": "string",
            "description": "Path on curaverto.com.",
            "examples": [
              "/pricing"
            ]
          },
          "title": {
            "type": "string",
            "description": "Page title.",
            "examples": [
              "Pricing"
            ]
          },
          "section": {
            "type": "string",
            "description": "Site section the page belongs to.",
            "examples": [
              "Core"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical HTML URL."
          },
          "markdown_url": {
            "type": "string",
            "format": "uri",
            "description": "The markdown twin of the page."
          }
        }
      },
      "PageList": {
        "type": "object",
        "required": [
          "version",
          "count",
          "sections",
          "pages"
        ],
        "properties": {
          "version": {
            "type": "integer",
            "description": "Major version of this response shape.",
            "examples": [
              1
            ]
          },
          "count": {
            "type": "integer",
            "description": "Number of pages in `pages`."
          },
          "sections": {
            "type": "array",
            "description": "Every section name, whatever the filter.",
            "items": {
              "type": "string"
            }
          },
          "pages": {
            "type": "array",
            "description": "The pages, in site order.",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          }
        }
      }
    }
  }
}
