{
  "openapi": "3.1.0",
  "info": {
    "title": "NORDEN BUILD demo content API",
    "version": "1.0.0",
    "summary": "Read-only JSON access to the fictional demo content of building.adscaled.media.",
    "description": "Demo data: NORDEN BUILD is a fictional construction company on a portfolio website built by the AdScaled agency. Services, projects, prices and FAQ answers are invented and illustrative only.\n\nAll operations are read-only GET requests without authentication. Text content is Czech; keys are English. CORS is open (`Access-Control-Allow-Origin: *`). Rate limit: 60 requests per minute per IP, reported with the IETF `RateLimit` / `RateLimit-Policy` headers; over the limit the API answers 429 with `Retry-After`. Errors use RFC 9457 problem details.\n\nVersioning: the major version is in the path (`/api/v1/`). Additive changes (new fields, new operations) keep v1; breaking changes get a new path (`/api/v2/`). A deprecated operation is marked `deprecated: true`, answers with `Deprecation` (RFC 9745) and `Sunset` (RFC 8594) headers and stays available for at least 90 days after the deprecation is announced in these docs.",
    "contact": {
      "name": "AdScaled (operator of the demo)",
      "url": "https://www.adscaled.media",
      "email": "contact@adscaled.media"
    }
  },
  "servers": [
    {
      "url": "https://building.adscaled.media",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Human-readable API docs",
    "url": "https://building.adscaled.media/docs"
  },
  "tags": [
    {
      "name": "content",
      "description": "Fictional demo content (services, projects, FAQ)."
    },
    {
      "name": "meta",
      "description": "Health of the API."
    }
  ],
  "paths": {
    "/api/v1/health": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "meta"
        ],
        "summary": "API health and version",
        "description": "Returns `ok: true` and the API version when the API is up.",
        "responses": {
          "200": {
            "description": "API is up.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/services": {
      "get": {
        "operationId": "listServices",
        "tags": [
          "content"
        ],
        "summary": "List all services",
        "description": "All 10 construction services of the fictional company with indicative price and duration.",
        "responses": {
          "200": {
            "description": "List of services.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceList"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/services/{slug}": {
      "get": {
        "operationId": "getService",
        "tags": [
          "content"
        ],
        "summary": "Get one service",
        "description": "Full detail of one service: scope of work, steps, price note, text sections and service FAQ.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Service slug (from listServices).",
            "schema": {
              "type": "string",
              "enum": [
                "vystavba-rodinnych-domu",
                "rekonstrukce-bytu",
                "rekonstrukce-domu",
                "komercni-prostory",
                "koupelny",
                "elektroinstalace",
                "voda-a-topeni",
                "fasady",
                "strechy",
                "interiery"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The service.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/projects": {
      "get": {
        "operationId": "listProjects",
        "tags": [
          "content"
        ],
        "summary": "List projects",
        "description": "All 14 fictional reference projects, optionally filtered by category.",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Only projects of this category.",
            "schema": {
              "type": "string",
              "enum": [
                "novostavba",
                "rekonstrukce-bytu",
                "rekonstrukce-domu",
                "koupelna",
                "komercni"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of projects.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/projects/{slug}": {
      "get": {
        "operationId": "getProject",
        "tags": [
          "content"
        ],
        "summary": "Get one project",
        "description": "Full detail of one project: works, description, challenge, solution and image URLs.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Project slug (from listProjects).",
            "schema": {
              "type": "string",
              "enum": [
                "rodinny-dum-praha-6",
                "rekonstrukce-bytu-vinohrady",
                "moderni-vila-pruhonice",
                "kancelare-karlin",
                "byt-holesovice",
                "rodinny-dum-ricany",
                "podkrovni-byt-smichov",
                "rekonstrukce-domu-cernosice",
                "restaurace-vrsovice",
                "koupelna-dejvice",
                "fasada-bytoveho-domu-nusle",
                "nizkoenergeticky-dum-jesenice",
                "showroom-brandys",
                "vila-zbraslav"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The project.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/faq": {
      "get": {
        "operationId": "listFaq",
        "tags": [
          "content"
        ],
        "summary": "List general FAQ",
        "description": "General frequently asked questions and answers (Czech).",
        "responses": {
          "200": {
            "description": "List of questions and answers.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FaqList"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "headers": {
      "RateLimit": {
        "description": "Remaining quota: `\"api\";r=<remaining>;t=<seconds to reset>`.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitPolicy": {
        "description": "Quota policy: `\"api\";q=60;w=60`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid query parameter.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded.",
        "headers": {
          "Retry-After": {
            "description": "Seconds until the quota resets.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "RFC 9457 problem details. Used by every error response.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Problem type URI (`about:blank`)."
          },
          "title": {
            "type": "string",
            "description": "Short summary of the problem."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599,
            "description": "HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "Explanation of this occurrence."
          }
        }
      },
      "Health": {
        "type": "object",
        "description": "API health.",
        "required": [
          "ok",
          "version",
          "demo"
        ],
        "additionalProperties": false,
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "version": {
            "type": "string",
            "description": "API version."
          },
          "demo": {
            "type": "boolean",
            "const": true
          }
        }
      },
      "ServiceSummary": {
        "type": "object",
        "description": "Service in a list.",
        "required": [
          "slug",
          "title",
          "summary",
          "projectType",
          "priceFrom",
          "duration",
          "url",
          "markdownUrl",
          "apiUrl"
        ],
        "additionalProperties": false,
        "properties": {
          "slug": {
            "type": "string",
            "enum": [
              "vystavba-rodinnych-domu",
              "rekonstrukce-bytu",
              "rekonstrukce-domu",
              "komercni-prostory",
              "koupelny",
              "elektroinstalace",
              "voda-a-topeni",
              "fasady",
              "strechy",
              "interiery"
            ],
            "description": "Stable identifier."
          },
          "title": {
            "type": "string",
            "description": "Service name (Czech)."
          },
          "summary": {
            "type": "string",
            "description": "One-line description (Czech)."
          },
          "projectType": {
            "type": "string",
            "enum": [
              "novostavba",
              "rekonstrukce-bytu",
              "rekonstrukce-domu",
              "koupelna",
              "komercni"
            ],
            "description": "Project category the service belongs to."
          },
          "priceFrom": {
            "type": "string",
            "description": "Indicative starting price as displayed on the site (Czech, CZK, fictional)."
          },
          "duration": {
            "type": "string",
            "description": "Typical duration (Czech)."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Web page of the service."
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Markdown version of the web page."
          },
          "apiUrl": {
            "type": "string",
            "format": "uri",
            "description": "This resource in the API."
          }
        }
      },
      "Service": {
        "type": "object",
        "description": "Full service detail.",
        "required": [
          "slug",
          "title",
          "summary",
          "projectType",
          "priceFrom",
          "duration",
          "url",
          "markdownUrl",
          "apiUrl",
          "intro",
          "includes",
          "steps",
          "priceNote",
          "sections",
          "faq",
          "image"
        ],
        "additionalProperties": false,
        "properties": {
          "slug": {
            "type": "string",
            "enum": [
              "vystavba-rodinnych-domu",
              "rekonstrukce-bytu",
              "rekonstrukce-domu",
              "komercni-prostory",
              "koupelny",
              "elektroinstalace",
              "voda-a-topeni",
              "fasady",
              "strechy",
              "interiery"
            ],
            "description": "Stable identifier."
          },
          "title": {
            "type": "string",
            "description": "Service name (Czech)."
          },
          "summary": {
            "type": "string",
            "description": "One-line description (Czech)."
          },
          "projectType": {
            "type": "string",
            "enum": [
              "novostavba",
              "rekonstrukce-bytu",
              "rekonstrukce-domu",
              "koupelna",
              "komercni"
            ],
            "description": "Project category the service belongs to."
          },
          "priceFrom": {
            "type": "string",
            "description": "Indicative starting price as displayed on the site (Czech, CZK, fictional)."
          },
          "duration": {
            "type": "string",
            "description": "Typical duration (Czech)."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Web page of the service."
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Markdown version of the web page."
          },
          "apiUrl": {
            "type": "string",
            "format": "uri",
            "description": "This resource in the API."
          },
          "intro": {
            "type": "string",
            "description": "Lead paragraph (Czech)."
          },
          "includes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the service covers."
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TextBlock"
            },
            "description": "Stages of the service."
          },
          "priceNote": {
            "type": "string",
            "description": "What affects the price (Czech)."
          },
          "sections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TextBlock"
            },
            "description": "Longer text sections."
          },
          "faq": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FaqItem"
            },
            "description": "Service-specific FAQ."
          },
          "image": {
            "type": "string",
            "format": "uri",
            "description": "Main image (WebP, 1600 px wide)."
          }
        }
      },
      "ProjectSummary": {
        "type": "object",
        "description": "Project in a list.",
        "required": [
          "slug",
          "title",
          "type",
          "typeLabel",
          "summary",
          "location",
          "year",
          "areaM2",
          "duration",
          "budget",
          "url",
          "markdownUrl",
          "apiUrl"
        ],
        "additionalProperties": false,
        "properties": {
          "slug": {
            "type": "string",
            "enum": [
              "rodinny-dum-praha-6",
              "rekonstrukce-bytu-vinohrady",
              "moderni-vila-pruhonice",
              "kancelare-karlin",
              "byt-holesovice",
              "rodinny-dum-ricany",
              "podkrovni-byt-smichov",
              "rekonstrukce-domu-cernosice",
              "restaurace-vrsovice",
              "koupelna-dejvice",
              "fasada-bytoveho-domu-nusle",
              "nizkoenergeticky-dum-jesenice",
              "showroom-brandys",
              "vila-zbraslav"
            ],
            "description": "Stable identifier."
          },
          "title": {
            "type": "string",
            "description": "Project title (Czech)."
          },
          "type": {
            "type": "string",
            "enum": [
              "novostavba",
              "rekonstrukce-bytu",
              "rekonstrukce-domu",
              "koupelna",
              "komercni"
            ],
            "description": "Project category."
          },
          "typeLabel": {
            "type": "string",
            "description": "Czech label of the category."
          },
          "summary": {
            "type": "string",
            "description": "One-line description (Czech)."
          },
          "location": {
            "type": "string",
            "description": "Location (Czech)."
          },
          "year": {
            "type": "integer",
            "description": "Year of completion."
          },
          "areaM2": {
            "type": "number",
            "description": "Floor area in square metres."
          },
          "duration": {
            "type": "string",
            "description": "Construction time (Czech)."
          },
          "budget": {
            "type": "string",
            "description": "Budget range as displayed on the site (Czech, CZK, fictional)."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Web page of the project."
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Markdown version of the web page."
          },
          "apiUrl": {
            "type": "string",
            "format": "uri",
            "description": "This resource in the API."
          }
        }
      },
      "Project": {
        "type": "object",
        "description": "Full project detail.",
        "required": [
          "slug",
          "title",
          "type",
          "typeLabel",
          "summary",
          "location",
          "year",
          "areaM2",
          "duration",
          "budget",
          "url",
          "markdownUrl",
          "apiUrl",
          "client",
          "services",
          "works",
          "description",
          "challenge",
          "solution",
          "images"
        ],
        "additionalProperties": false,
        "properties": {
          "slug": {
            "type": "string",
            "enum": [
              "rodinny-dum-praha-6",
              "rekonstrukce-bytu-vinohrady",
              "moderni-vila-pruhonice",
              "kancelare-karlin",
              "byt-holesovice",
              "rodinny-dum-ricany",
              "podkrovni-byt-smichov",
              "rekonstrukce-domu-cernosice",
              "restaurace-vrsovice",
              "koupelna-dejvice",
              "fasada-bytoveho-domu-nusle",
              "nizkoenergeticky-dum-jesenice",
              "showroom-brandys",
              "vila-zbraslav"
            ],
            "description": "Stable identifier."
          },
          "title": {
            "type": "string",
            "description": "Project title (Czech)."
          },
          "type": {
            "type": "string",
            "enum": [
              "novostavba",
              "rekonstrukce-bytu",
              "rekonstrukce-domu",
              "koupelna",
              "komercni"
            ],
            "description": "Project category."
          },
          "typeLabel": {
            "type": "string",
            "description": "Czech label of the category."
          },
          "summary": {
            "type": "string",
            "description": "One-line description (Czech)."
          },
          "location": {
            "type": "string",
            "description": "Location (Czech)."
          },
          "year": {
            "type": "integer",
            "description": "Year of completion."
          },
          "areaM2": {
            "type": "number",
            "description": "Floor area in square metres."
          },
          "duration": {
            "type": "string",
            "description": "Construction time (Czech)."
          },
          "budget": {
            "type": "string",
            "description": "Budget range as displayed on the site (Czech, CZK, fictional)."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Web page of the project."
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Markdown version of the web page."
          },
          "apiUrl": {
            "type": "string",
            "format": "uri",
            "description": "This resource in the API."
          },
          "client": {
            "type": "string",
            "description": "Type of client (Czech, anonymous)."
          },
          "services": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "vystavba-rodinnych-domu",
                "rekonstrukce-bytu",
                "rekonstrukce-domu",
                "komercni-prostory",
                "koupelny",
                "elektroinstalace",
                "voda-a-topeni",
                "fasady",
                "strechy",
                "interiery"
              ]
            },
            "description": "Slugs of the services used."
          },
          "works": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Performed works."
          },
          "description": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Description paragraphs."
          },
          "challenge": {
            "type": "string",
            "description": "What was difficult."
          },
          "solution": {
            "type": "string",
            "description": "How it was solved."
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Image URLs (WebP, 1600 px wide), cover first."
          }
        }
      },
      "TextBlock": {
        "type": "object",
        "description": "Titled text.",
        "required": [
          "title",
          "text"
        ],
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "description": "Heading."
          },
          "text": {
            "type": "string",
            "description": "Text."
          }
        }
      },
      "FaqItem": {
        "type": "object",
        "description": "Question and answer.",
        "required": [
          "question",
          "answer"
        ],
        "additionalProperties": false,
        "properties": {
          "question": {
            "type": "string",
            "description": "Question (Czech)."
          },
          "answer": {
            "type": "string",
            "description": "Answer (Czech)."
          }
        }
      },
      "ServiceList": {
        "type": "object",
        "description": "List of services.",
        "required": [
          "demo",
          "notice",
          "count",
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "demo": {
            "type": "boolean",
            "const": true,
            "description": "Always true: the content is fictional demo data."
          },
          "notice": {
            "type": "string",
            "description": "Human-readable notice that the data is fictional."
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of items in `data`."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceSummary"
            }
          }
        }
      },
      "ServiceResponse": {
        "type": "object",
        "description": "One service.",
        "required": [
          "demo",
          "notice",
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "demo": {
            "type": "boolean",
            "const": true,
            "description": "Always true: the content is fictional demo data."
          },
          "notice": {
            "type": "string",
            "description": "Human-readable notice that the data is fictional."
          },
          "data": {
            "$ref": "#/components/schemas/Service"
          }
        }
      },
      "ProjectList": {
        "type": "object",
        "description": "List of projects.",
        "required": [
          "demo",
          "notice",
          "count",
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "demo": {
            "type": "boolean",
            "const": true,
            "description": "Always true: the content is fictional demo data."
          },
          "notice": {
            "type": "string",
            "description": "Human-readable notice that the data is fictional."
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of items in `data`."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectSummary"
            }
          }
        }
      },
      "ProjectResponse": {
        "type": "object",
        "description": "One project.",
        "required": [
          "demo",
          "notice",
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "demo": {
            "type": "boolean",
            "const": true,
            "description": "Always true: the content is fictional demo data."
          },
          "notice": {
            "type": "string",
            "description": "Human-readable notice that the data is fictional."
          },
          "data": {
            "$ref": "#/components/schemas/Project"
          }
        }
      },
      "FaqList": {
        "type": "object",
        "description": "List of FAQ items.",
        "required": [
          "demo",
          "notice",
          "count",
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "demo": {
            "type": "boolean",
            "const": true,
            "description": "Always true: the content is fictional demo data."
          },
          "notice": {
            "type": "string",
            "description": "Human-readable notice that the data is fictional."
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of items in `data`."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FaqItem"
            }
          }
        }
      }
    }
  }
}