{
    "openapi": "3.1.0",
    "info": {
        "title": "Studio Legale Bianucci — public website API",
        "version": "1.0.0",
        "summary": "Read-only access to the published pages of a law firm's website and to its public details.",
        "description": "Search and read the Italian and English pages of the website of Studio Legale Bianucci (a law firm in Milan, Italy) as Markdown, and get the firm's address, hours, team and contacts.\n\nUse it to answer questions about the firm and to cite its pages. The pages explain the law in general terms and are not legal advice on a specific case. The API cannot book appointments or send messages: to contact the firm, use the phone number, e-mail address or contact page in `GET /firm`.\n\nNo authentication. Limit: 60 requests per minute per address, shown in the RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers (HTTP 429 with Retry-After when exceeded). Errors are RFC 9457 problem details. Versioning: /api/v1 only receives backward-compatible changes (new fields or endpoints); a breaking change would get a new /api/v2, with /api/v1 announced through Deprecation and Sunset headers at least six months before it is withdrawn. The same data is available through the MCP server at https://www.studiolegalebianucci.it/mcp.",
        "contact": {
            "name": "Studio Legale Bianucci",
            "url": "https://www.studiolegalebianucci.it/en/contact",
            "email": "info@studiolegalebianucci.it"
        }
    },
    "externalDocs": {
        "description": "Documentation for developers and AI agents",
        "url": "https://www.studiolegalebianucci.it/en/developers"
    },
    "servers": [
        {
            "url": "https://www.studiolegalebianucci.it/api/v1"
        }
    ],
    "security": [],
    "tags": [
        {
            "name": "pages",
            "description": "Published pages of the website"
        },
        {
            "name": "firm",
            "description": "Public facts about the firm"
        },
        {
            "name": "service",
            "description": "Service information"
        }
    ],
    "paths": {
        "/": {
            "get": {
                "operationId": "getApiIndex",
                "tags": [
                    "service"
                ],
                "summary": "List the endpoints of the API",
                "responses": {
                    "200": {
                        "description": "Endpoints, documentation and related services.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "default": {
                        "$ref": "#/components/responses/ServerError"
                    }
                }
            }
        },
        "/firm": {
            "get": {
                "operationId": "getFirmDetails",
                "tags": [
                    "firm"
                ],
                "summary": "Get the firm's public details and contacts",
                "description": "Name, founder, address, phone, e-mail, office hours, languages, practice areas, team and review summary, with the URLs of the pages they come from.",
                "parameters": [
                    {
                        "name": "lang",
                        "in": "query",
                        "required": false,
                        "description": "Language of the pages.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "it",
                                "en"
                            ],
                            "default": "it"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Public facts about the firm.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Firm"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/ServerError"
                    },
                    "default": {
                        "$ref": "#/components/responses/ServerError"
                    }
                }
            }
        },
        "/pages": {
            "get": {
                "operationId": "listPages",
                "tags": [
                    "pages"
                ],
                "summary": "List the published pages in one language",
                "parameters": [
                    {
                        "name": "lang",
                        "in": "query",
                        "required": false,
                        "description": "Language of the pages.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "it",
                                "en"
                            ],
                            "default": "it"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Every published page in the language, in site order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PageList"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/ServerError"
                    },
                    "default": {
                        "$ref": "#/components/responses/ServerError"
                    }
                }
            }
        },
        "/search": {
            "get": {
                "operationId": "searchPages",
                "tags": [
                    "pages"
                ],
                "summary": "Search the published pages",
                "description": "Matches every significant word of q in titles, descriptions and text (accents and case ignored). If no page matches every word, pages matching some of them are returned with matched = \"some\".",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "required": true,
                        "description": "Words to look for.",
                        "schema": {
                            "type": "string",
                            "minLength": 2,
                            "maxLength": 200
                        },
                        "example": "separazione consensuale"
                    },
                    {
                        "name": "lang",
                        "in": "query",
                        "required": false,
                        "description": "Language of the pages.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "it",
                                "en"
                            ],
                            "default": "it"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Maximum number of results.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 10,
                            "default": 5
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Matching pages, best first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SearchResults"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/ServerError"
                    },
                    "default": {
                        "$ref": "#/components/responses/ServerError"
                    }
                }
            }
        },
        "/page": {
            "get": {
                "operationId": "getPage",
                "tags": [
                    "pages"
                ],
                "summary": "Read a published page as Markdown",
                "description": "Returns the Markdown of a page (the same text as the HTML page, without menus and forms). Long pages come in parts: request the next one with offset = next_offset. The Markdown of a page is also served at its URL with \".md\" appended, or with the header Accept: text/markdown.",
                "parameters": [
                    {
                        "name": "url",
                        "in": "query",
                        "required": true,
                        "description": "Canonical URL or path of the page (from /pages or /search).",
                        "schema": {
                            "type": "string",
                            "maxLength": 500
                        },
                        "example": "/en/criminal-lawyer-milan"
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "required": false,
                        "description": "Character offset to start from.",
                        "schema": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1000000,
                            "default": 0
                        }
                    },
                    {
                        "name": "max_characters",
                        "in": "query",
                        "required": false,
                        "description": "Maximum length of the returned part.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1000,
                            "maximum": 40000,
                            "default": 20000
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page, or one part of it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PageContent"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "500": {
                        "$ref": "#/components/responses/ServerError"
                    },
                    "default": {
                        "$ref": "#/components/responses/ServerError"
                    }
                }
            }
        },
        "/health": {
            "get": {
                "operationId": "getHealth",
                "tags": [
                    "service"
                ],
                "summary": "Check that the API is available",
                "responses": {
                    "200": {
                        "description": "The API is available.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "version"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "const": "ok"
                                        },
                                        "version": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "default": {
                        "$ref": "#/components/responses/ServerError"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "Page": {
                "type": "object",
                "required": [
                    "title",
                    "description",
                    "url",
                    "markdown_url",
                    "language",
                    "type"
                ],
                "properties": {
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Canonical URL: cite this one."
                    },
                    "markdown_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "language": {
                        "type": "string",
                        "enum": [
                            "it",
                            "en"
                        ]
                    },
                    "type": {
                        "type": "string",
                        "description": "home, about, profile, services, practice_area, topic, guide, media, reviews, contact, legal or developers."
                    },
                    "updated": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "Date of the last editorial update."
                    }
                }
            },
            "PageList": {
                "type": "object",
                "required": [
                    "language",
                    "pages"
                ],
                "properties": {
                    "language": {
                        "type": "string"
                    },
                    "pages": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Page"
                        }
                    }
                }
            },
            "SearchResults": {
                "type": "object",
                "required": [
                    "query",
                    "language",
                    "results"
                ],
                "properties": {
                    "query": {
                        "type": "string"
                    },
                    "language": {
                        "type": "string"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "allOf": [
                                {
                                    "$ref": "#/components/schemas/Page"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "excerpt": {
                                            "type": "string",
                                            "description": "Text around the first match."
                                        },
                                        "matched": {
                                            "type": "string",
                                            "enum": [
                                                "all",
                                                "some"
                                            ],
                                            "description": "Whether every word of the query was found."
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            },
            "PageContent": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Page"
                    },
                    {
                        "type": "object",
                        "required": [
                            "markdown",
                            "offset",
                            "next_offset",
                            "total_characters"
                        ],
                        "properties": {
                            "alternates": {
                                "type": "object",
                                "description": "The same page in the other languages (language → URL).",
                                "additionalProperties": {
                                    "type": "string",
                                    "format": "uri"
                                }
                            },
                            "markdown": {
                                "type": "string"
                            },
                            "offset": {
                                "type": "integer"
                            },
                            "next_offset": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Offset of the next part, null at the end of the page."
                            },
                            "total_characters": {
                                "type": "integer"
                            }
                        }
                    }
                ]
            },
            "Firm": {
                "type": "object",
                "required": [
                    "name",
                    "address",
                    "phone",
                    "email",
                    "practice_areas",
                    "contact_page"
                ],
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "alternate_names": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "description": {
                        "type": "string"
                    },
                    "founder": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "credential": {
                                "type": "string"
                            },
                            "url": {
                                "type": "string",
                                "format": "uri"
                            }
                        }
                    },
                    "bar": {
                        "type": "string"
                    },
                    "vat_number": {
                        "type": "string"
                    },
                    "address": {
                        "type": "object",
                        "properties": {
                            "street": {
                                "type": "string"
                            },
                            "postal_code": {
                                "type": "string"
                            },
                            "city": {
                                "type": "string"
                            },
                            "region": {
                                "type": "string"
                            },
                            "country": {
                                "type": "string"
                            }
                        }
                    },
                    "geo": {
                        "type": "object",
                        "properties": {
                            "lat": {
                                "type": "number"
                            },
                            "lng": {
                                "type": "number"
                            }
                        }
                    },
                    "maps_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "phone": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "opening_hours": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "days": {
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                },
                                "opens": {
                                    "type": "string"
                                },
                                "closes": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "opening_hours_text": {
                        "type": "string"
                    },
                    "languages": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "practice_areas": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string"
                                },
                                "name": {
                                    "type": "string"
                                },
                                "summary": {
                                    "type": "string"
                                },
                                "url": {
                                    "type": "string",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "team": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string"
                                },
                                "role": {
                                    "type": "string"
                                },
                                "url": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "reviews": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "properties": {
                            "count": {
                                "type": "integer"
                            },
                            "average_rating": {
                                "type": "number"
                            },
                            "scale": {
                                "type": "integer"
                            },
                            "url": {
                                "type": "string",
                                "format": "uri"
                            }
                        }
                    },
                    "contact_page": {
                        "type": "string",
                        "format": "uri"
                    },
                    "website": {
                        "type": "string",
                        "format": "uri"
                    },
                    "social": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uri"
                        }
                    },
                    "note": {
                        "type": "string"
                    }
                }
            },
            "Problem": {
                "type": "object",
                "description": "RFC 9457 problem details.",
                "required": [
                    "type",
                    "title",
                    "status",
                    "code",
                    "detail"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "format": "uri"
                    },
                    "title": {
                        "type": "string"
                    },
                    "status": {
                        "type": "integer"
                    },
                    "code": {
                        "type": "string",
                        "description": "Stable error code, e.g. missing_parameter, invalid_language, page_not_found, rate_limited."
                    },
                    "detail": {
                        "type": "string"
                    },
                    "hint": {
                        "type": "string",
                        "description": "How to fix the request."
                    }
                }
            }
        },
        "responses": {
            "BadRequest": {
                "description": "Invalid parameter.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "NotFound": {
                "description": "No published page at this URL.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "TooManyRequests": {
                "description": "Rate limit exceeded.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds to wait.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                },
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "ServerError": {
                "description": "Temporary failure.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            }
        }
    }
}
