{
    "openapi": "3.1.0",
    "info": {
        "title": "Caspar Manufaktur API – Materialien, NLWeb und Projektübergaben",
        "description": "Public B2B material information, recommendations, NLWeb queries and human-reviewed project handoffs. No autonomous ordering or pricing. API versioning: /v1/. Deprecation policy: planned breaking changes use a new major version; planned sunsets are announced at least 90 days in advance. No v1 sunset is currently scheduled. See /api-policy/. Stable API base: https://www.caspar-manufaktur.de/api/v1/",
        "version": "1.4.0",
        "x-deprecation-policy": "https://www.caspar-manufaktur.de/api-policy/",
        "contact": {
            "name": "Caspar Manufaktur",
            "url": "https://www.caspar-manufaktur.de/kontakt/",
            "email": "info@caspar-manufaktur.de"
        }
    },
    "servers": [
        {
            "url": "https://www.caspar-manufaktur.de",
            "description": "Production; public read-only access and human-reviewed handoffs"
        }
    ],
    "paths": {
        "/wp-json/nlweb/v1/ask": {
            "get": {
                "operationId": "askQuestion",
                "summary": "Natural language query about Caspar products",
                "description": "Ask any question about Caspar Manufaktur products, materials, ordering process, or B2B services.",
                "parameters": [
                    {
                        "name": "query",
                        "in": "query",
                        "required": true,
                        "description": "Natural language question",
                        "schema": {
                            "type": "string",
                            "example": "Welche Materialien bietet Caspar an?"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful answer",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AskResponse"
                                }
                            }
                        },
                        "headers": {
                            "RateLimit-Policy": {
                                "description": "IETF rate limit policy, e.g. 100;w=3600.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "RateLimit": {
                                "description": "IETF rate limit status: limit, remaining, reset (seconds).",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad request — missing or invalid query parameter",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Endpoint not found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded — retry after 60 seconds",
                        "headers": {
                            "Retry-After": {
                                "schema": {
                                    "type": "integer"
                                },
                                "description": "Seconds to wait before retrying"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                },
                "tags": [
                    "NLWeb"
                ]
            },
            "post": {
                "operationId": "askQuestionPost",
                "summary": "Natural language query (POST)",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "query"
                                ],
                                "properties": {
                                    "query": {
                                        "type": "string",
                                        "description": "Natural language question"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Successful answer",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AskResponse"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponse"
                                }
                            }
                        }
                    }
                },
                "tags": [
                    "NLWeb"
                ]
            }
        },
        "/wp-json/nlweb/v1/ask/stream": {
            "get": {
                "operationId": "askQuestionStream",
                "summary": "Streaming natural language query (SSE)",
                "description": "Server-Sent Events streaming endpoint. Returns start, result, and complete events.",
                "parameters": [
                    {
                        "name": "query",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "SSE stream",
                        "content": {
                            "text/event-stream": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "tags": [
                    "NLWeb",
                    "Streaming"
                ]
            }
        },
        "/.well-known/mcp": {
            "get": {
                "operationId": "getMcpInfo",
                "summary": "MCP server discovery",
                "responses": {
                    "200": {
                        "description": "MCP server info",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "tags": [
                    "MCP"
                ]
            }
        },
        "/wp-json/caspar-agent/v1/materials": {
            "get": {
                "summary": "List Caspar wallpaper materials and their verified technical characteristics.",
                "operationId": "listMaterials",
                "responses": {
                    "200": {
                        "description": "Complete curated API material selection.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/CasparMaterial"
                                    }
                                }
                            }
                        },
                        "headers": {
                            "X-Total-Count": {
                                "description": "Total number of materials matching the filters.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Link": {
                                "description": "RFC 8288 pagination links (rel=next, rel=prev).",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "description": "Returns the current 12 published Caspar materials and variants as one JSON array, shared with MCP list_materials and caspar://materials. Existing material IDs remain stable. Datasheet links and weight qualifications are optional fields. Suitability requires project-specific human review; no prices or autonomous ordering.",
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Page size (1-50, default 50).",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 50,
                            "default": 50
                        }
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "required": false,
                        "description": "Number of materials to skip (default 0).",
                        "schema": {
                            "type": "integer",
                            "minimum": 0,
                            "default": 0
                        }
                    },
                    {
                        "name": "priority",
                        "in": "query",
                        "required": false,
                        "description": "Filter by priority tag.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "id",
                        "in": "query",
                        "required": false,
                        "description": "Return only the material with this id.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ]
            }
        },
        "/wp-json/caspar-agent/v1/materials/recommendation": {
            "get": {
                "summary": "Recommend one material for a declared project priority.",
                "operationId": "recommendMaterial",
                "parameters": [
                    {
                        "name": "priority",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "brandschutz",
                                "robust",
                                "effekt",
                                "nachhaltig",
                                "feuchtraum"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Project-related material recommendation; suitability requires human review.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparRecommendation"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Missing or unknown priority.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparRestError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/caspar-agent/v1/handoffs": {
            "post": {
                "summary": "Create a safe, human-reviewed next-step URL for a project enquiry, sample request or Wallcheck.",
                "operationId": "createProjectHandoff",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "Client-generated key. Reuse only for the same next_step. The response is stored in a WordPress transient with a 24-hour expiration (86400 seconds); early cache eviction is possible. Replay is available only while the record exists. No orders or personal data are submitted.",
                        "schema": {
                            "type": "string",
                            "minLength": 8,
                            "maxLength": 255,
                            "pattern": "^[A-Za-z0-9._:-]{8,255}$"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "next_step"
                                ],
                                "properties": {
                                    "next_step": {
                                        "type": "string",
                                        "enum": [
                                            "project_enquiry",
                                            "sample_request",
                                            "wallcheck"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "New handoff link created. This is not an order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparHandoff"
                                }
                            }
                        },
                        "headers": {
                            "Idempotency-Replayed": {
                                "description": "true for a stored replay, false for a new handoff.",
                                "schema": {
                                    "type": "string",
                                    "enum": [
                                        "true",
                                        "false"
                                    ]
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Stored handoff replayed while its transient exists.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparHandoff"
                                }
                            }
                        },
                        "headers": {
                            "Idempotency-Replayed": {
                                "description": "true for a stored replay, false for a new handoff.",
                                "schema": {
                                    "type": "string",
                                    "enum": [
                                        "true",
                                        "false"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid next_step or missing/invalid Idempotency-Key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparRestError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/caspar-agent/v1/company": {
            "get": {
                "summary": "Get company information and human handoff links.",
                "operationId": "getCompanyInformation",
                "responses": {
                    "200": {
                        "description": "Company information.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparCompany"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1": {
            "get": {
                "operationId": "getApiIndex",
                "summary": "API index with all public Caspar Manufaktur endpoints.",
                "description": "Stable, versioned entry point of the Caspar Manufaktur REST API. Lists every public endpoint under /api/v1/ with its canonical /wp-json/ route. No API key required.",
                "tags": [
                    "API"
                ],
                "responses": {
                    "200": {
                        "description": "API index.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparApiIndex"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/health": {
            "get": {
                "operationId": "getApiHealth",
                "summary": "Health check of the Caspar Manufaktur API.",
                "description": "Returns status ok when the API is reachable. No API key required.",
                "tags": [
                    "API"
                ],
                "responses": {
                    "200": {
                        "description": "API is reachable.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CasparApiHealth"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "AskResponse": {
                "type": "object",
                "required": [
                    "_meta",
                    "answer"
                ],
                "properties": {
                    "_meta": {
                        "type": "object",
                        "properties": {
                            "response_type": {
                                "type": "string",
                                "example": "answer"
                            },
                            "version": {
                                "type": "string",
                                "example": "1.0"
                            },
                            "query": {
                                "type": "string"
                            }
                        }
                    },
                    "answer": {
                        "type": "string"
                    },
                    "sources": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "format": "uri"
                                }
                            }
                        }
                    }
                }
            },
            "ErrorResponse": {
                "type": "object",
                "required": [
                    "code",
                    "message"
                ],
                "properties": {
                    "code": {
                        "type": "string",
                        "example": "invalid_request"
                    },
                    "message": {
                        "type": "string",
                        "example": "Missing required parameter: query"
                    },
                    "retry_after": {
                        "type": "integer",
                        "description": "Seconds to wait before retrying (rate limit errors only)"
                    }
                }
            },
            "CasparMaterial": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "priority": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "surface": {
                        "type": "string"
                    },
                    "width_cm": {
                        "type": "number"
                    },
                    "weight_g_m2": {
                        "type": "number",
                        "description": "Weight in g/m². Read weight_note: where the datasheet specifies only carrier weight, this is not a total finished-material weight."
                    },
                    "datasheet_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Official material datasheet linked from the Caspar website."
                    },
                    "weight_note": {
                        "type": "string",
                        "description": "Qualification of weight_g_m2 when needed. For Peel & Stick, the numeric value refers to the nonwoven carrier, not the finished adhesive-backed material."
                    },
                    "processing_guide_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Official processing guide, if available."
                    }
                },
                "required": [
                    "id",
                    "name",
                    "priority",
                    "surface",
                    "width_cm",
                    "weight_g_m2"
                ]
            },
            "CasparRecommendation": {
                "type": "object",
                "properties": {
                    "material": {
                        "type": "string"
                    },
                    "reason": {
                        "type": "string"
                    },
                    "materials_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "sample_url": {
                        "type": "string",
                        "format": "uri"
                    }
                },
                "required": [
                    "material",
                    "reason",
                    "materials_url",
                    "sample_url"
                ]
            },
            "CasparHandoff": {
                "type": "object",
                "properties": {
                    "handoff_id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "next_step": {
                        "type": "string",
                        "enum": [
                            "project_enquiry",
                            "sample_request",
                            "wallcheck"
                        ]
                    },
                    "url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "note": {
                        "type": "string"
                    },
                    "idempotent_replay": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "handoff_id",
                    "next_step",
                    "url",
                    "note",
                    "idempotent_replay"
                ]
            },
            "CasparRestError": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string"
                    },
                    "message": {
                        "type": "string"
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "integer"
                            }
                        }
                    }
                },
                "required": [
                    "code",
                    "message"
                ]
            },
            "CasparCompany": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "website": {
                        "type": "string",
                        "format": "uri"
                    },
                    "contact_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "wallcheck_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "materials_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "developers_url": {
                        "type": "string",
                        "format": "uri"
                    }
                },
                "required": [
                    "name",
                    "description",
                    "website",
                    "contact_url",
                    "wallcheck_url",
                    "materials_url",
                    "developers_url"
                ]
            },
            "CasparApiIndex": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "version": {
                        "type": "string",
                        "example": "v1"
                    },
                    "status": {
                        "type": "string",
                        "example": "ok"
                    },
                    "base_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "authentication": {
                        "type": "string"
                    },
                    "endpoints": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "method": {
                                    "type": "string"
                                },
                                "path": {
                                    "type": "string"
                                },
                                "href": {
                                    "type": "string",
                                    "format": "uri"
                                },
                                "description": {
                                    "type": "string"
                                },
                                "canonical": {
                                    "type": "string",
                                    "format": "uri"
                                }
                            },
                            "required": [
                                "method",
                                "path",
                                "href",
                                "description"
                            ]
                        }
                    },
                    "links": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string",
                            "format": "uri"
                        }
                    }
                },
                "required": [
                    "name",
                    "version",
                    "status",
                    "base_url",
                    "endpoints"
                ]
            },
            "CasparApiHealth": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string",
                        "example": "ok"
                    },
                    "api": {
                        "type": "string"
                    },
                    "version": {
                        "type": "string",
                        "example": "v1"
                    },
                    "time": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "status",
                    "version",
                    "time"
                ]
            }
        }
    },
    "tags": [
        {
            "name": "API",
            "description": "Stable API entry point under /api/v1/"
        },
        {
            "name": "NLWeb",
            "description": "Natural language query endpoints"
        },
        {
            "name": "Streaming",
            "description": "SSE streaming endpoints"
        },
        {
            "name": "MCP",
            "description": "Model Context Protocol discovery"
        }
    ],
    "externalDocs": {
        "description": "API versioning, deprecation, error handling and idempotency policy",
        "url": "https://www.caspar-manufaktur.de/api-policy/"
    }
}
