{
  "openapi": "3.1.0",
  "info": {
    "title": "Studio Dentistico Di Mauro - API pubblica",
    "version": "1.0.0",
    "summary": "Recapiti, orari, trattamenti e pagine dello Studio Dentistico Di Mauro (Nola, NA).",
    "description": "API pubblica in sola lettura, senza autenticazione. Rate limit: 60 richieste ogni 60 secondi per IP, comunicato su ogni risposta con gli header IETF RateLimit-Policy e RateLimit; oltre il limite risposta 429 con Retry-After. Errori in application/problem+json (RFC 9457). Versioning: la versione e' nel path (/api/v1), stabile; le modifiche incompatibili usciranno solo su /api/v2. Una versione deprecata viene segnalata con gli header Deprecation (RFC 9745) e Sunset (RFC 8594) e resta attiva almeno 6 mesi dopo l'annuncio. Policy completa: https://odontoiatriadimauro.it/docs#versioning. Per prenotare una visita usare la pagina /contatti o il telefono: l'API non prenota.",
    "contact": {
      "name": "Studio Dentistico Di Mauro",
      "url": "https://odontoiatriadimauro.it/contact",
      "email": "odontoiatriadimauro@gmail.com"
    },
    "x-api-lifecycle": {
      "status": "stable",
      "versioning": "url-path",
      "deprecationHeader": "Deprecation (RFC 9745)",
      "sunsetHeader": "Sunset (RFC 8594)",
      "minimumDeprecationNoticeDays": 180,
      "policy": "https://odontoiatriadimauro.it/docs#versioning"
    }
  },
  "externalDocs": {
    "url": "https://odontoiatriadimauro.it/docs"
  },
  "servers": [
    {
      "url": "https://odontoiatriadimauro.it"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "studio",
      "description": "Dati dello studio"
    },
    {
      "name": "sito",
      "description": "Pagine del sito"
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "Indice dell'API",
        "description": "Restituisce versione, link alla documentazione e l'elenco degli endpoint disponibili.",
        "tags": [
          "sito"
        ],
        "responses": {
          "200": {
            "description": "Indice dell'API.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/info": {
      "get": {
        "operationId": "getStudioInfo",
        "summary": "Recapiti e orari dello studio",
        "description": "Restituisce nome, indirizzo, telefoni, email, orari di apertura, team, zone servite e profili social dello studio.",
        "tags": [
          "studio"
        ],
        "responses": {
          "200": {
            "description": "Dati dello studio.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioInfo"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/treatments": {
      "get": {
        "operationId": "listTreatments",
        "summary": "Trattamenti offerti",
        "description": "Elenca i trattamenti odontoiatrici e di medicina estetica offerti, con il link alla pagina di ciascuno.",
        "tags": [
          "studio"
        ],
        "responses": {
          "200": {
            "description": "Elenco dei trattamenti.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TreatmentList"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "listPages",
        "summary": "Pagine pubbliche del sito",
        "description": "Elenca tutte le pagine pubbliche del sito, le stesse della sitemap. Ogni pagina si puo' ottenere in markdown con l'header Accept: text/markdown.",
        "tags": [
          "sito"
        ],
        "responses": {
          "200": {
            "description": "Elenco delle pagine.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageList"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "components": {
    "headers": {
      "RateLimit-Policy": {
        "description": "Politica di rate limit (IETF draft-ietf-httpapi-ratelimit-headers): \"default\";q=60;w=60 = 60 richieste in 60 secondi.",
        "schema": {
          "type": "string",
          "example": "\"default\";q=60;w=60"
        }
      },
      "RateLimit": {
        "description": "Stato corrente del limite: r = richieste rimaste, t = secondi al reset.",
        "schema": {
          "type": "string",
          "example": "\"default\";r=59;t=60"
        }
      },
      "Retry-After": {
        "description": "Secondi da attendere prima di riprovare.",
        "schema": {
          "type": "integer",
          "example": 30
        }
      },
      "Deprecation": {
        "description": "RFC 9745. Presente solo su endpoint deprecati: data (structured field) da cui l'endpoint e' deprecato.",
        "schema": {
          "type": "string",
          "example": "@1798761600"
        }
      },
      "Sunset": {
        "description": "RFC 8594. Presente solo su endpoint deprecati: data HTTP dopo la quale l'endpoint verra' rimosso.",
        "schema": {
          "type": "string",
          "example": "Sat, 01 Jan 2028 00:00:00 GMT"
        }
      }
    },
    "schemas": {
      "ApiIndex": {
        "type": "object",
        "required": [
          "name",
          "version",
          "documentation",
          "openapi",
          "endpoints"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string",
            "example": "v1"
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "mcp": {
            "type": "string",
            "format": "uri"
          },
          "endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "method",
                "path"
              ],
              "properties": {
                "method": {
                  "type": "string",
                  "enum": [
                    "GET"
                  ]
                },
                "path": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PostalAddress": {
        "type": "object",
        "required": [
          "streetAddress",
          "postalCode",
          "addressLocality",
          "addressCountry"
        ],
        "properties": {
          "streetAddress": {
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "addressLocality": {
            "type": "string"
          },
          "addressRegion": {
            "type": "string"
          },
          "addressCountry": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2"
          }
        }
      },
      "OpeningHours": {
        "type": "object",
        "required": [
          "days",
          "opens",
          "closes"
        ],
        "properties": {
          "days": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "opens": {
            "type": "string",
            "pattern": "^\\d{2}:\\d{2}$"
          },
          "closes": {
            "type": "string",
            "pattern": "^\\d{2}:\\d{2}$"
          }
        }
      },
      "TeamMember": {
        "type": "object",
        "required": [
          "name",
          "role"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string"
          }
        }
      },
      "StudioInfo": {
        "type": "object",
        "required": [
          "name",
          "url",
          "address",
          "phones",
          "email",
          "openingHours"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "alternateName": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "foundingYear": {
            "type": "integer"
          },
          "address": {
            "$ref": "#/components/schemas/PostalAddress"
          },
          "geo": {
            "type": "object",
            "required": [
              "latitude",
              "longitude"
            ],
            "properties": {
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              }
            }
          },
          "phones": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "openingHours": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpeningHours"
            }
          },
          "closedDays": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "booking": {
            "type": "object",
            "required": [
              "page",
              "phone"
            ],
            "properties": {
              "page": {
                "type": "string",
                "format": "uri"
              },
              "phone": {
                "type": "string"
              }
            }
          },
          "team": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeamMember"
            }
          },
          "areaServed": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sameAs": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "Treatment": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "path",
          "url"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "TreatmentList": {
        "type": "object",
        "required": [
          "treatments"
        ],
        "properties": {
          "treatments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Treatment"
            }
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "lastModified": {
            "type": "string",
            "description": "Data dell'ultima modifica (ISO 8601)."
          }
        }
      },
      "PageList": {
        "type": "object",
        "required": [
          "pages"
        ],
        "properties": {
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "Errore RFC 9457 (application/problem+json).",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "resolution"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "not_found",
              "rate_limited",
              "invalid_path",
              "upstream_error",
              "method_not_allowed",
              "internal_error"
            ]
          },
          "resolution": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "TooManyRequests": {
        "description": "Limite di richieste superato.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "InternalError": {
        "description": "Errore interno.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    }
  }
}