{
  "openapi": "3.1.0",
  "info": {
    "title": "PREISmonitoring API",
    "version": "1.00",
    "summary": "Programmatic access to observed prices, availability, and their history across the retail sites monitored for you",
    "contact": {
      "name": "PREISmonitoring API access",
      "url": "https://www.preismonitoring.de/kontakt"
    },
    "description": "## What this API gives you\n\nPREISmonitoring observes what products actually cost and whether they are\nactually in stock — across the online shops, marketplaces, and platforms\nthat matter to you — and it keeps the observation history. This API is\ndirect, programmatic access to that record.\n\nIt answers questions such as:\n\n* What is this product selling for right now, at every site monitored for\n  you, and where is it unavailable?\n* How has that price moved over the last seven days, quarter, or year?\n* What changed since my last synchronisation, so I only pull the delta?\n* Where does a candidate price sit among the current market offers, per\n  country and currency? (MCP tool `get_market_price_position`)\n* Which observation carried the Amazon Featured Offer?\n\nProducts are addressed by the identifiers you already work with: internal\nitem ID, EAN, PZN, and ASIN together with its marketplace locale.\nIntegrations typically feed pricing and repricing engines, BI and data\nwarehouses, ERP and PIM systems, MAP and margin monitoring — and, through\nMCP, AI agents that reason over market data directly.\n\nThe public API is read-only by design. Nothing you call here changes\nmonitoring configuration or platform state.\n\n## Two surfaces, one contract\n\n| | REST | MCP |\n| --- | --- | --- |\n| Built for | conventional HTTP clients | AI clients and agents |\n| Endpoint | `/v1/*` | `POST /mcp` |\n| Shape | resources and HTTP operations | JSON-RPC 2.0 over Streamable HTTP |\n| Authentication | bearer token from `POST /v1/auth/token` | OAuth 2.1 authorization code flow with PKCE |\n\nBoth surfaces are first-class, both are described by this single\nspecification, and both read the same data under the same visibility rules\nand the same domain semantics. They keep their own protocol contracts:\nREST describes resources and HTTP operations directly, while MCP describes\nthe transport envelope and leaves the live tool catalog and its JSON\nSchemas to runtime discovery.\n\n## For AI clients and agents\n\n`POST /mcp` is a native surface, not a wrapper around REST. Point an\nMCP-capable client at it and it discovers everything it needs:\n\n* `tools/list` — the current tool catalog with input schemas, covering\n  monitored sites, products, monitoring orders, observation results,\n  change deltas since a timestamp, export and import history, and market\n  price position.\n* `prompts/list` — server-authored workflows for the questions this data\n  is usually asked: `analyze-buybox`, `check-price-availability`,\n  `inspect-observation`, `analyze-market-price-position`, and\n  `review-observed-shops`. Fetching\n  one with `prompts/get` returns a ready-to-run task description, so an\n  agent does not have to invent a query strategy.\n* `resources/list` and `resources/templates/list` — stable reference\n  material such as `pmon://reference/sites`,\n  `pmon://reference/asin-locales`, and\n  `pmon://reference/results-contract`, plus templated reads for a single\n  site, a single monitoring order, or a single product.\n\nAuthorization uses OAuth 2.1 with PKCE and the `mcp` scope. Clients\ndiscover the protected resource and the authorization server through the\nstandard `/.well-known/` metadata endpoints before starting the flow;\n`offline_access` is available where refresh access is required.\n\nThe endpoint accepts protocol versions `2025-03-26`, `2025-06-18`, and\n`2025-11-25`, as well as the modern `2026-07-28` wire profile with request\nmetadata headers and `_meta` fields. Every published tool is annotated\n`readOnlyHint: true`, `openWorldHint: false`, and\n`destructiveHint: false`. The read-only annotation describes the domain\neffect: no call changes data a client can read afterwards. Every modern\ntool descriptor also publishes an `outputSchema` for its structured result.\n\nNo tool, prompt, or resource widens your scope. An agent sees exactly what\nthe authenticated account is allowed to see, and nothing beyond it.\n\n### Agent-executable specifications\n\nA task is executable by an agent only when it states the product decision\nthat resolves otherwise equivalent outcomes, the expected behavior for\nloading, success, empty, error, and recovery states, testable acceptance criteria,\na behavior contract, the required context, and an explicit blast radius.\nHigh-level objectives, evals, and state recovery complement this decision;\nthey do not replace it when more than one end state would pass the evals.\n\nA short orientation for agents that fetch a URL rather than render a page is\nserved at `llms.txt`, next to this reference. It links to this contract\ninstead of restating it, so the specification stays the single source of\ntruth. `llms-full.txt` carries the whole reference as one Markdown document\nfor clients that ingest documentation in a single fetch; it is generated\nfrom this specification at build time and therefore cannot fall behind it.\n\n### Connecting a client\n\nThe quickest route is the **official PREISmonitoring agent plugin**:\n\n<https://github.com/PREISmonitoring/preismonitoring-mcp-plugin>\n\nInstall it in your client and the endpoint is configured — no hand-written\nJSON, no copied URLs. The package contains no credentials: sign-in, consent,\nand token storage stay in your client. The repository README carries the\nper-client install commands and the clients we have verified ourselves.\n\n#### What an agent plugin is\n\n[Agent Plugins](https://agent-plugins.org/specification) is an open,\nvendor-neutral packaging standard for extending AI agents. Its purpose is\nportability: instead of every client inventing its own configuration format,\na plugin is a directory with a `plugin.json` manifest and fixed locations for\nits components. Version 1.0 defines exactly two portable component types —\nAgent Skills and MCP servers — and its Technical Steering Committee includes\nmaintainers from Amazon, Cursor, Microsoft, OpenAI, and Vercel.\n\nTwo properties matter for a published integration like this one. First, the\nformat deliberately carries **no** credential or OAuth configuration:\nauthorization discovery, user interaction, and token storage are the client's\njob, and any headers in a plugin are literal, publicly visible package data.\nA plugin can therefore be distributed openly without becoming a secret\nstore. Second, clients adopt the component types and MCP transports\nincrementally and document what they support — so plugin support is not a\nsingle yes or no.\n\nWhich clients currently consume the format, and which parts of it, is tracked\nupstream: <https://agent-plugins.org/compatible-clients>\n\nClients that do not consume plugins are not excluded. They configure the same\nendpoint directly, and the examples below show how.\n\nIf your client does not install plugins, configure the endpoint directly.\nIt speaks Streamable HTTP with OAuth discovery, so a capable client needs\nthe base URL and nothing else — no pre-registration, no manually issued\nkey. Configuration examples for clients we have connected:\n\nCodex — `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.preismonitoring]\nurl = \"https://api.preismonitoring.de/mcp\"\n```\n\nGoose — `~/.config/goose/config.yaml`:\n\n```yaml\nextensions:\n  preismonitoring:\n    type: streamable_http\n    uri: https://api.preismonitoring.de/mcp\n    enabled: true\n```\n\nVisual Studio Code — `.vscode/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"preismonitoring\": {\n      \"type\": \"http\",\n      \"url\": \"https://api.preismonitoring.de/mcp\"\n    }\n  }\n}\n```\n\nOn first connection the client receives `401`, follows the protected-resource\nmetadata to the authorization server, registers itself dynamically, and opens\na browser for login and consent. The client therefore has to accept a\nloopback callback on `127.0.0.1` and be able to open a browser.\n\nThese are configuration examples, not a compatibility guarantee. Which\nclients we have actually connected and verified ourselves is listed in the\nuser documentation; the most common failure among other clients is their own\ndynamic client registration, not the token exchange.\n\n## Getting started\n\n1. `GET /healthz` — confirm the runtime is reachable.\n2. `POST /v1/auth/token` for a bearer token, or run the MCP OAuth flow.\n3. `GET /v1/sites` — see which shops and platforms are monitored for you.\n4. `GET /v1/results?limit=10` — read observations, then narrow by product\n   identifier, site, or capture window.\n\nTypical read flows are `list_sites` → `list_orders` and\n`list_sites` → `list_results`. A product-identifier read without an\nexplicit capture window defaults to the last 168 hours.\n\nFor an agent-oriented time-only request, first enumerate the visible sites\nand then issue one site-scoped `list_results` read per site with an initial\n24-hour window. If the scope exceeds the available query budget, reduce\nthe window in the order 24, 12, 6, and 1 hour before reducing the site\nselection. Preserve successful per-site results, but label the combined\nresponse incomplete when a site or cursor cannot be completed. Keep\nprices, unavailable products, and products with no result at a requested\nsite as distinct outcomes; the agent workflow does not expand the\nauthenticated scope.\n\nIf `RESULTS_SCOPE_TOO_BROAD` rejects the initial request before its first\npage, start a new request with a narrower scope and/or capture window.\nA cursor, sort order, or the NDJSON stream cannot resume or bypass that\nrejected first request; those mechanisms apply only after an accepted read.\n\nNo access yet? A time-limited free API account can be requested at\n<https://www.preismonitoring.de/kontakt>.\n\n## Scale, limits, and guarantees\n\nResult reads page up to 10,000 records per request with cursor pagination,\nand `GET /v1/results/stream` delivers larger extracts as NDJSON. Complete\nJSON responses and complete NDJSON lines are limited to 64 MiB and fail\nwith the structured `RESPONSE_TOO_LARGE` contract rather than returning\ntruncated JSON. Scope-budget codes such as `ITEM_SCOPE_TOO_BROAD`,\n`HISTORY_SCOPE_TOO_BROAD`, `RESULTS_SCOPE_TOO_BROAD`, and\n`RESULTS_LATEST_PAIR_SCOPE_TOO_BROAD` say plainly when a query is too wide,\ninstead of failing late or silently.\n\nREST archive downloads and the MCP tools `download_order_export_file` and\n`download_order_import_file` use the same configured raw-object limit,\n`RUST_API_ARCHIVE_DOWNLOAD_MAX_BYTES`. A standalone MCP tool call derives\nits bounded JSON budget from the Base64 upper bound, the two published MCP\nrepresentations, and a fixed envelope reserve; a JSON-RPC batch keeps the\naggregate 64-MiB budget and gives each successive response only the still\navailable remainder. Each download's raw fetch is capped before\nmaterialization at the largest value whose conservative\ndouble-representation budget fits that remainder. Larger batch downloads\nare rejected in a controlled way. The MCP download\nresponse preserves UTF-8 when JSON escaping fits and otherwise uses the\ndocumented Base64 encoding. A raw-size overflow returns\n`413 PAYLOAD_TOO_LARGE`; `actualBytes` states the known total size or the\nsize observed when streaming stopped, and `maxBytes` states the permitted\nmaximum. Both values are also included in the detail.\n\nResponses subject to the REST rate-limit contract report rate limits through\nthe `X-RateLimit-*` headers. Public documentation and health endpoints are\noutside that contract. Every response carries `X-Request-Id` so client and server\nlogs can be correlated. Every response also carries the defense-in-depth\nheaders `Content-Security-Policy`, `X-Content-Type-Options`,\n`X-Frame-Options`, and `Referrer-Policy`. CORS responses compose `Vary`\nwithout replacing existing values.\n\n## Versioning\n\nThe version above is the version of **this contract**: it answers the one\nquestion an integrator has, namely whether what they build against has\nchanged. It is deliberately neither the build version nor the release\nnumber. Additive changes raise the minor version and leave existing\nintegrations working; breaking changes raise the major version. Rewording\na description is not a contract change and does not move the number.\n\nWhat changed between versions is published at `openapi/CHANGELOG.md`.\n`GET /healthz` reports the contract version together\nwith the running build, so a support case can name both.\n\nA ready-to-import Postman collection for the REST read surface is available\nat `openapi/postman/preismonitoring-rest-read.postman_collection.json`.\n"
  },
  "servers": [
    {
      "url": "https://api.preismonitoring.de",
      "description": "Live"
    }
  ],
  "tags": [
    {
      "name": "Public",
      "description": "Public unauthenticated utility endpoints"
    },
    {
      "name": "Auth",
      "description": "Authentication endpoints for bearer-token access"
    },
    {
      "name": "Items",
      "description": "Monitored product records"
    },
    {
      "name": "Orders",
      "description": "Monitoring orders and related export/import history"
    },
    {
      "name": "Results",
      "description": "Observed price and availability records"
    },
    {
      "name": "Sites",
      "description": "Monitored retail sites"
    },
    {
      "name": "MCP",
      "description": "AI-oriented access through MCP over JSON-RPC 2.0"
    }
  ],
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Runtime health check and version diagnostics",
        "description": "Reports reachability plus the two version numbers a support case needs.\n\n`contractVersion` is the version of this specification and answers \"has\nwhat I integrate against changed?\". `build` is the running server build\nand answers \"which build did I actually reach?\" — until now only MCP\nclients could see it, through `serverInfo.version` on `initialize`.\n\nBoth fields are diagnostic. Do not use them for feature detection: the\ncontract describes what exists, and the build number carries no promise\nabout behaviour.\n",
        "operationId": "getHealthz",
        "responses": {
          "200": {
            "description": "Runtime is reachable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/openapi/openapi.yaml": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the OpenAPI specification as YAML",
        "operationId": "getOpenApiSpec",
        "responses": {
          "200": {
            "description": "Current OpenAPI specification",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              }
            },
            "content": {
              "application/yaml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/openapi/openapi.json": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the OpenAPI specification as JSON",
        "description": "A JSON representation generated at build time from the authoritative\nYAML specification. It exists as a compatibility fallback for clients\nwhose retrieval layer does not ingest YAML reliably.\n",
        "operationId": "getOpenApiSpecJson",
        "responses": {
          "200": {
            "description": "Current OpenAPI specification as JSON",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/openapi/CHANGELOG.md": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the contract changelog",
        "description": "How this contract has changed over time, written for integrators. Every\nentry belongs to a contract version and states whether the change is\nadditive or breaking. Rewording a description is not a contract change\nand does not appear here.\n",
        "operationId": "getContractChangelog",
        "responses": {
          "200": {
            "description": "Current contract changelog",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/openapi/postman/preismonitoring-rest-read.postman_collection.json": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the Postman collection for the REST read surface",
        "description": "A ready-to-import Postman collection covering the REST read endpoints.\nMCP is deliberately not duplicated here; its transport is described in\nthis reference and its tool catalog is discovered at runtime.\n",
        "operationId": "getPostmanCollection",
        "responses": {
          "200": {
            "description": "Postman collection",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the concise AI-client orientation as plain text",
        "description": "A deliberately concise, curated orientation for AI clients and agents.\nIt links to this authoritative contract rather than restating it.\n",
        "operationId": "getLlmsTxt",
        "responses": {
          "200": {
            "description": "AI-client orientation",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Download the complete API reference as plain text",
        "description": "The complete contract as one Markdown document for clients that ingest\ndocumentation in a single fetch. It is generated from this specification\nat build time.\n",
        "operationId": "getLlmsFullTxt",
        "responses": {
          "200": {
            "description": "Complete API reference",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": [
          "MCP"
        ],
        "summary": "MCP JSON-RPC endpoint for AI clients",
        "description": "Accepts MCP messages as JSON-RPC 2.0 over HTTP POST. The endpoint is\nprotected by OAuth 2.1 authorization code flow with PKCE and the\n`mcp` scope. Clients should use protected-resource metadata and\nauthorization-server metadata discovery before starting the flow.\n\nThis operation documents the MCP transport envelope; it intentionally\ndoes not turn every tool into a synthetic REST path. Discover the\ncurrent tool catalog and JSON Schemas with `tools/list`. Discover\nresources and prompts with `resources/list`, `resources/templates/list`,\nand `prompts/list`; invoke a tool with `tools/call`.\n\nTool annotations in the modern wire profile explicitly carry\n`readOnlyHint`, `openWorldHint`, and `destructiveHint`. Every published\ntool is read-only in the domain sense, does not change public or\nthird-party systems, and performs no destructive action. Internal\nserver-side usage accounting is not a domain effect and does not make a\ntool non-read-only. Each modern tool descriptor additionally publishes\nan `outputSchema` for the structured result returned by `tools/call`.\n\nThe endpoint accepts the legacy protocol versions `2025-03-26`,\n`2025-06-18`, and `2025-11-25`. The modern wire profile\n`2026-07-28` additionally uses request metadata headers and `_meta`\nfields as described by the MCP implementation. Notifications are\nacknowledged with HTTP 202 and no response body. JSON-RPC requests\nreturn HTTP 200 with a JSON response; malformed HTTP messages return\nHTTP 400.\n\nThe header parameters below are optional at the OpenAPI operation\nlevel because this operation covers both protocol eras. Legacy\nrequests omit `mcp-method` and `mcp-name`. Modern requests must send\n`MCP-Protocol-Version: 2026-07-28` and a matching `mcp-method`; a\nmatching `mcp-name` is additionally required for `tools/call`,\n`prompts/get`, and `resources/read`.\n",
        "operationId": "postMcp",
        "security": [
          {
            "McpOAuth": [
              "mcp"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/McpProtocolVersion"
          },
          {
            "$ref": "#/components/parameters/McpMethod"
          },
          {
            "$ref": "#/components/parameters/McpName"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/McpJsonRpcMessage"
                  },
                  {
                    "$ref": "#/components/schemas/McpJsonRpcBatch"
                  }
                ]
              },
              "examples": {
                "initialize": {
                  "summary": "Negotiate the MCP protocol version",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "initialize",
                    "params": {
                      "protocolVersion": "2025-11-25",
                      "capabilities": {},
                      "clientInfo": {
                        "name": "example-client",
                        "version": "1.0.0"
                      }
                    }
                  }
                },
                "serverDiscover": {
                  "summary": "Discover the modern MCP server capabilities",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": "discover-1",
                    "method": "server/discover",
                    "params": {
                      "_meta": {
                        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
                        "io.modelcontextprotocol/clientCapabilities": {}
                      }
                    }
                  }
                },
                "toolsList": {
                  "summary": "Discover the current tool catalog",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 2,
                    "method": "tools/list",
                    "params": {}
                  }
                },
                "resourcesList": {
                  "summary": "Discover available resources",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 3,
                    "method": "resources/list",
                    "params": {}
                  }
                },
                "promptsList": {
                  "summary": "Discover available prompts",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 4,
                    "method": "prompts/list",
                    "params": {}
                  }
                },
                "listResults": {
                  "summary": "Invoke a domain workflow tool",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 5,
                    "method": "tools/call",
                    "params": {
                      "name": "list_results",
                      "arguments": {
                        "site": "docmorris-de-482731",
                        "limit": 5,
                        "includeCoverage": true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result for a request",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/McpJsonRpcResponse"
                    },
                    {
                      "$ref": "#/components/schemas/McpJsonRpcResponseBatch"
                    }
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Accepted notification with no response body"
          },
          "400": {
            "description": "Invalid JSON-RPC message or invalid MCP transport metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/McpUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/auth/token": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Request a bearer token",
        "description": "Authenticates a user with `loginIdentifier` and `password` and returns a bearer token for REST reads. The issued token is bound to the authenticated user's permitted PREISmonitoring read scope. Use the returned `expiresIn` value to determine token lifetime (default 4 hours). Tokens can be invalidated before expiry via `POST /v1/auth/logout`. MCP uses the OAuth-based flow documented on `POST /mcp` and does not use this bearer-token issuance endpoint.\n",
        "operationId": "postAuthToken",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthTokenRequest"
              },
              "example": {
                "loginIdentifier": "user@example.com",
                "password": "secret-password"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bearer token created successfully",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthTokenResponse"
                },
                "example": {
                  "tokenType": "Bearer",
                  "accessToken": "eyJhbGciOi...",
                  "expiresIn": 14400
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON, JSON values with the wrong field types, or a missing or non-JSON `Content-Type` returns structured `ErrorResponse` with status `400` and code `MVP_VALIDATION_ERROR`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/RequestBodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Revoke the presented bearer token",
        "description": "Invalidates the bearer token presented in the `Authorization` header server-side. Subsequent requests with the same token are rejected with `401`. The route is protected, so a second logout with the same token also returns `401`. Tokens issued before revocation support carry no token id and cannot be revoked individually; for those the response reports `revoked: false` and the token ages out via its expiry. Valid MCP OAuth access tokens are not REST tokens and return `400`; revoke them through the MCP OAuth flow instead. Expired or malformed credentials return `401`. If the revocation write fails, the endpoint returns `500` and the token may remain valid until expiry.\n",
        "operationId": "postAuthLogout",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Revocation processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "revoked"
                  ],
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "revoked": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/LogoutRevocationFailed"
          }
        }
      }
    },
    "/v1/sites": {
      "get": {
        "tags": [
          "Sites"
        ],
        "summary": "List monitored retail sites",
        "operationId": "listSites",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "site",
            "in": "query",
            "description": "Public site key",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Monitored retail sites",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SitesPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/items/asin-locales": {
      "get": {
        "tags": [
          "Items"
        ],
        "summary": "List supported ASIN locales",
        "description": "Returns at most 256 unique ASIN locale keys visible in the authenticated item scope. A 257th key is rejected with `ITEM_SCOPE_TOO_BROAD`; the response is never silently truncated.\n",
        "operationId": "listAsinLocales",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Supported ASIN locales for accessible item and result queries",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportedAsinLocalesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/items": {
      "get": {
        "tags": [
          "Items"
        ],
        "summary": "List monitored product records",
        "description": "Lists monitored products visible in the authenticated account's authorized visibility context; every account has a limited scope. The number of visible items depends on the account's booked package and service scope as well as the observation and filter scope chosen by the customer or agent. This is not a query over the complete PREISmonitoring catalog, so a small or empty result does not prove that a product does not exist or is not monitored globally. Filters never expand the account scope. For reference-backed scopes, identifier searches inspect at most 10,000 item candidates in fixed authorization batches and retain only the requested page plus lookahead. Candidate 10,001 before a complete page is rejected with `ITEM_SCOPE_TOO_BROAD`; clients can narrow the identifier or continue from a later opaque cursor.\n",
        "operationId": "listItems",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "itemId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pzn",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ean",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asinLocale",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asin",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Monitored product records",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemsPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List monitoring orders",
        "description": "Lists monitoring orders in the authenticated scope. Optional monitoring enrichment matches only configured order-site pairs and supports at most 10,000 candidates per request; broader requests are rejected with `ORDER_COVERAGE_SCOPE_TOO_BROAD` and should be narrowed with `orderId`, a lower `limit`, or without `includeMonitoring`.\n",
        "operationId": "listOrders",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "orderId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "alias",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeMonitoring",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeCoverage",
            "in": "query",
            "description": "Includes coverage and health summaries. Requests spanning more than 10,000 active order-item references or 10,000 unique item-site candidates are rejected with `ORDER_COVERAGE_SCOPE_TOO_BROAD`; narrow by `orderId` or a lower `limit`, or omit this enrichment.\n",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Monitoring orders",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrdersPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Get order details",
        "description": "Includes coverage and health summaries. An order spanning more than 10,000 active order-item references or 10,000 unique item-site candidates are rejected with `ORDER_COVERAGE_SCOPE_TOO_BROAD`. Monitoring is likewise restricted to at most 10,000 configured order-site candidates.\n",
        "operationId": "getOrder",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Order details",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderDetailResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/observation-quality": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List current order observation quality",
        "description": "Lists the current ReporterV3 snapshot for configured product/site pairs of the authorized order. Counts and reason codes map one-to-one to the categories in the customer dashboard. Technical crawler retries do not create additional configured or expected observations. Missing or malformed legacy membership data is returned as `UNKNOWN`. `PRODUCT_NOT_FOUND` is a regular negative market observation that can be valuable for a shop's assortment-depth analysis; by itself, it is not an API, crawler, shop, provider, or system error. It is a quality problem only as a false negative, when the product actually existed at the observation time but was classified as missing. The API reports the observed classification and cannot prove a false negative without external ground truth.\n",
        "operationId": "listOrderObservationQuality",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "site",
            "in": "query",
            "description": "Optional public site key.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reasonCode",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/OrderObservationReasonCode"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current order observation quality page",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderObservationQualityPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/exports": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List order exports",
        "description": "Streams ordered export candidates and retains only the requested page. If candidate 10,001 is reached before the page is complete, the request fails with `ORDER_SCOPE_TOO_BROAD` and does not return a partial page.\n",
        "operationId": "listOrderExports",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "exportName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order exports",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NamedHistoryPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/exports/history": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List order export history",
        "description": "Scans at most 1,000 archive documents and 10,000 nested file candidates before applying filters and page selection. A wider catalog fails with `HISTORY_SCOPE_TOO_BROAD` and never returns a partial history page.\n",
        "operationId": "listOrderExportHistory",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "name": "exportName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Export history",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoryPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/exports/history/latest": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Get latest matching export history entry",
        "description": "Selects the newest matching entry while enforcing the same 1,000 source document and 10,000 nested candidate budgets as the list endpoint. Overflow fails with `HISTORY_SCOPE_TOO_BROAD`.\n",
        "operationId": "getOrderExportHistoryLatest",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "name": "exportName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latest",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Single export history entry",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistorySingleResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/exports/history/download": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Download export artifact",
        "description": "Returns the matching export artifact as a direct binary response within the authenticated user's permitted scope. The selectors narrow the matching history entries for the given order, and `latest=true` streams the newest matching artifact. `Content-Disposition` carries the download filename returned by the service. The media type is derived from that filename and never from the object store's own metadata: CSV artifacts are served as `text/csv; charset=utf-8`, XLSX artifacts as `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`, ZIP artifacts as `application/zip`, and every other filename as `application/octet-stream`. The media types listed below are therefore the complete set this operation can return.\n",
        "operationId": "downloadOrderExportHistoryArtifact",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "name": "exportName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latest",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File content of the matching export artifact",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDispositionAttachment"
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              },
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              },
              "application/zip": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/HistoryArtifactContentMissing"
          },
          "413": {
            "$ref": "#/components/responses/ArchivePayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/imports": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List order imports",
        "description": "Evaluates the order-dependent `name` filter before querying imports and applies the requested page limit directly to the ordered MongoDB find.\n",
        "operationId": "listOrderImports",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order imports",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NamedHistoryPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/imports/history": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List order import history",
        "description": "Scans at most 1,000 archive documents and 10,000 nested file candidates before applying filters and page selection. A wider catalog fails with `HISTORY_SCOPE_TOO_BROAD` and never returns a partial history page.\n",
        "operationId": "listOrderImportHistory",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Import history",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoryPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/imports/history/latest": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Get latest matching import history entry",
        "description": "Selects the newest matching entry while enforcing the same 1,000 source document and 10,000 nested candidate budgets as the list endpoint. Overflow fails with `HISTORY_SCOPE_TOO_BROAD`.\n",
        "operationId": "getOrderImportHistoryLatest",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latest",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Single import history entry",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistorySingleResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/orders/{orderId}/imports/history/download": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Download import artifact",
        "description": "Returns the matching import artifact as a direct binary response within the authenticated user's permitted scope. The selectors narrow the matching history entries for the given order, and `latest=true` streams the newest matching artifact. `Content-Disposition` carries the download filename returned by the service. The media type is derived from that filename and never from the object store's own metadata: CSV artifacts are served as `text/csv; charset=utf-8`, XLSX artifacts as `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`, ZIP artifacts as `application/zip`, and every other filename as `application/octet-stream`. The media types listed below are therefore the complete set this operation can return.\n",
        "operationId": "downloadOrderImportHistoryArtifact",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latest",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File content of the matching import artifact",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDispositionAttachment"
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              },
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              },
              "application/zip": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryPayload"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/HistoryArtifactContentMissing"
          },
          "413": {
            "$ref": "#/components/responses/ArchivePayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/results": {
      "get": {
        "tags": [
          "Results"
        ],
        "summary": "List observed price and availability records",
        "description": "Returns observed price and availability records (an ad-hoc observation view over scrape captures) for the authenticated user's permitted scope. Filters combine as an intersection across the supplied criteria. `capturedFrom`/`capturedTo` form a closed window over `capturedAt` and accept RFC3339 timestamps or `YYYY-MM-DD` dates (a bare date upper bound is inclusive of the whole day). An explicit window requires a scope (`itemId`, `pzn`, `ean`, `asin`, `orderId` or `site`), unless the explicit opt-in `globalScope=true` is supplied. Global scope requires both bounds, forbids those scope selectors, and is limited to 168 hours. `sort` (`asc`/`desc`, default `desc`) orders by `capturedAt`. `timezone` (IANA, default `UTC`) interprets date-only bounds and renders `capturedAt` in that zone. `latestPerPair=true` returns the newest visible record for each permitted item-site pair. The synchronous latest-per-pair scope is limited to 1,000 permitted item-site pairs; larger scopes return `400 RESULTS_LATEST_PAIR_SCOPE_TOO_BROAD`. Narrow that request with `itemId`, `orderId`, `site`, or a product identifier (`pzn`, `ean`, or `asin`). If no explicit product filter and no explicit window are supplied, the service may apply an operational default time filter. Product-history reads scoped by `itemId`, `pzn`, `ean`, or `asinLocale` plus `asin` use the last 168 hours when neither boundary is supplied; one or both explicit boundaries preserve the explicit query behavior. The lean core is always returned; `includeExportFields`, `includeIdentity`, `includeCoverage`, `includeOrderIds`, and `includeCustomerData` explicitly request the corresponding optional field groups. The flat per-line export with all fields is served separately via the order export-history endpoints. Agent workflows can use `globalScope=true` for one bounded cross-site read; the response exposes `query.scope=global`. There is no deferred job in this contract. Two outcomes must be handled: a hard budget failure is a structured error (`504 RESULTS_QUERY_TIMEOUT`), while a soft deadline ends the page early and returns `200` with fewer rows than `limit` **and** a `paging.nextCursor`. Clients must therefore follow `nextCursor` as long as it is present and must not stop at `returned < limit`; stopping early silently drops rows. If a global read keeps hitting the budget, narrow `capturedFrom`/`capturedTo` (for example 24, 12, 6, then 1 hour) or fall back to `/v1/sites` plus one site-scoped read per visible site. A partial set of independent reads stays usable but must be reported as incomplete when cursors or sites were left unprocessed. A stream exposes the same scope marker in the `X-Results-Scope` response header. Distinct-pair enrichment checks at most 250,000 item-site candidates; larger or arithmetically unrepresentable products fail with `RESULTS_SCOPE_TOO_BROAD` before aggregation. If that rejection occurs before the first page, `cursor`, `sort`, and `/v1/results/stream` cannot resume or bypass a rejected first request; they apply only after an accepted read. Start a new request with a narrower scope (`itemId`, `pzn`, `ean`, `asinLocale` together with `asin`, `orderId`, or `site`) and/or narrower `capturedFrom`/`capturedTo` bounds. For `globalScope=true`, keep both bounds, omit product/order/site selectors, and keep the closed window at or below 168 hours; remove `globalScope` when an identifier- or site-scoped recovery is needed. There is no deferred job fallback.\n",
        "operationId": "listResults",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "orderId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pzn",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ean",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asinLocale",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asin",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "site",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "globalScope",
            "in": "query",
            "description": "Explicit `globalScope=true` opt-in for one synchronous read across all authorized item/site pairs. Requires both `capturedFrom` and `capturedTo`, forbids item/order/site scope selectors, and limits the closed window to 168 hours.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "description": "Customer-visible product brand. Resolves permitted items first; combines with every other supplied filter as an intersection.\n",
            "schema": {
              "type": "string"
            },
            "example": "Example brand"
          },
          {
            "name": "manufacturer",
            "in": "query",
            "description": "Observed Result manufacturer filter. This is a Result observation, not an Item-master attribute.\n",
            "schema": {
              "type": "string"
            },
            "example": "Example manufacturer"
          },
          {
            "name": "merchant",
            "in": "query",
            "description": "Observed Result merchant/seller filter. Merchant-level Prime summaries are aggregations of matching Result observations, not a permanent merchant attribute.\n",
            "schema": {
              "type": "string"
            },
            "example": "Example merchant"
          },
          {
            "name": "isPrime",
            "in": "query",
            "description": "Exact observed Amazon Prime Boolean filter. `true` and `false` are distinct values; missing, null, and malformed source values are unknown and do not match `false`. Available only for canonical Amazon country markets (trimmed ASCII-casefolded `name=amazon` and a non-empty `country`); other shops have absent or different semantics.\n",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "isBuyBox",
            "in": "query",
            "description": "Exact observed Amazon Featured Offer (Buy Box) Boolean filter. `true` and `false` are distinct values; missing, null, and malformed source values are unknown and do not match `false`. Available only for canonical Amazon country markets (trimmed ASCII-casefolded `name=amazon` and a non-empty `country`); other shops have absent or different semantics.\n",
            "schema": {
              "type": "boolean"
            },
            "example": false
          },
          {
            "name": "coverageState",
            "in": "query",
            "description": "Coverage filter for the current result scope. Current documented values are `covered` and `missing_result`.\n",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "capturedFrom",
            "in": "query",
            "description": "Lower bound of the capturedAt window. RFC3339 or `YYYY-MM-DD`. Requires a scope (itemId/pzn/ean/asin/orderId/site), unless `globalScope=true` is supplied with both bounds.\n",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "capturedTo",
            "in": "query",
            "description": "Upper bound of the capturedAt window (inclusive day-end for a bare date). RFC3339 or `YYYY-MM-DD`. Requires a scope unless `globalScope=true` is supplied; global windows are limited to 168 hours.\n",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Orders by `capturedAt`. `asc` or `desc`; default `desc`.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "description": "IANA timezone (e.g. `Europe/Berlin`). Interprets date-only window bounds and renders `capturedAt` in that zone. Default `UTC`.\n",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latestPerPair",
            "in": "query",
            "description": "Returns the newest visible result for each permitted item-site pair in the filtered scope.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "latestObservationPerPair",
            "in": "query",
            "description": "Selects the complete newest observation set for each permitted item-site pair first, then applies manufacturer, merchant, isPrime, and isBuyBox filters. This differs from `latestPerPair` and must not be combined with it. Follow `paging.nextCursor` until exhausted; a scope guard, cursor, or incomplete traversal makes any summary incomplete.\n",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "includeCoverage",
            "in": "query",
            "description": "Includes optional coverage fields such as `coverageState`, `observedSites`, and `missingResultSites`. With an explicit `site` filter, coverage is derived from the paginated result set.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeOrderIds",
            "in": "query",
            "description": "Includes `orderId` on each result record.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeCustomerData",
            "in": "query",
            "description": "Includes the permitted `customerData` subset on each result record.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeExportFields",
            "in": "query",
            "description": "Includes the observation export fields `merchant`, `sku`, `breadcrumbs`, `customerReferencePrices`, `referencePrice`, `referencePriceMoney`, `isBuyBox`, `isPrime`, `productRating`, `brand`, and `manufacturer`. `isPrime` is independent from `isBuyBox` and is emitted as the observed Boolean `true` or `false` only for canonical Amazon country markets. It is omitted for other shops, unknown sites, and missing, null, or non-Boolean source values. `productRating` is emitted only for canonical Idealo DE with `value` validated in the documented 0 to 5 range and rounded to one decimal place; `scale` is 5. It is omitted for other platforms, including Idealo AT and Idealo All Results DE, and missing, malformed, or out-of-range source values.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeIdentity",
            "in": "query",
            "description": "Includes canonical external product identifiers `gtin` and `asin` from the item master.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Observed price and availability records",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultsPage"
                },
                "example": {
                  "data": [
                    {
                      "id": "69f31917d3206be0d39af1ad",
                      "itemId": "606c202ad2f81bb58a5d0a4c",
                      "site": "mycare-de-127122",
                      "capturedAt": "2026-04-30T08:55:49.815Z",
                      "name": "Example product",
                      "pzn": "14167086",
                      "brand": "Example brand",
                      "manufacturer": "Example manufacturer",
                      "merchant": "Example merchant",
                      "isBuyBox": true,
                      "isPrime": false,
                      "price": 2595,
                      "priceMoney": {
                        "amountMinor": 2595,
                        "currencyCode": "EUR",
                        "fractionDigits": 2,
                        "rawCurrency": "EUR",
                        "normalizationState": "resolved"
                      },
                      "currency": "EUR",
                      "availability": "In stock",
                      "offerUrl": "https://shop.example/items/example-product"
                    }
                  ],
                  "paging": {
                    "limit": 50,
                    "returned": 1,
                    "nextCursor": "eyJraW5kIjoicmVzdWx0cyIsImRhdGVNcyI6MTc3NzUzODQ3MDAwNywiaWQiOiI2OWYzMTVhNzkzM2JkNWE5M2U3ZDc5NTQifQ"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters. `code` is `MVP_VALIDATION_ERROR` for ordinary validation failures, including a `globalScope=true` request that omits `capturedFrom` or `capturedTo` or that also carries a product, order or site selector. `code` = `RESULTS_LATEST_PAIR_SCOPE_TOO_BROAD` is returned when `latestPerPair=true` covers more than 1,000 permitted item-site pairs; narrow the request with `itemId`, `orderId`, `site`, or a product identifier (`pzn`, `ean`, or `asin`). `code` = `RESULTS_SCOPE_TOO_BROAD` is returned in two independent cases. First, always and regardless of configuration, when a `globalScope=true` window exceeds 168 hours; shorten the window. Second, when the optional results scan guard is enabled (env `RUST_API_RESULTS_SCAN_GUARD_MAX_SCOPE_PAIRS` / `_MAX_WINDOW_HOURS`, disabled by default) and a query whose authorized scope and capturedAt window are jointly too broad to serve within budget is rejected up front. `cursor`, `sort`, and `/v1/results/stream` cannot resume or bypass a rejected first request; they apply only after an accepted read. Start a new request with a narrower scope (`itemId`, `pzn`, `ean`, `asinLocale` together with `asin`, `orderId`, or `site`) and/or narrower `capturedFrom`/`capturedTo` bounds. For `globalScope=true`, keep both bounds, omit product/order/site selectors, and keep the closed window at or below 168 hours; remove `globalScope` when an identifier- or site-scoped recovery is needed. There is no deferred job fallback.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/results/capabilities": {
      "get": {
        "tags": [
          "Results"
        ],
        "summary": "Describe the results contract (self-describing capabilities)",
        "description": "Returns a machine-readable description of the results export-read contract: lean core fields, opt-in include groups (includeExportFields, includeIdentity, includeCustomerData, includeCoverage, includeOrderIds), filterable parameters, sort, the capturedAt window, and timezone behavior, plus `scopeGuard` recovery guidance for broad historical reads. Generated from the same contract definition that drives the response shape and the MCP `describe_results_contract` tool.\n",
        "operationId": "getResultsCapabilities",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Results contract capabilities",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "scopeGuard"
                  ],
                  "properties": {
                    "scopeGuard": {
                      "$ref": "#/components/schemas/ResultsScopeGuard"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/v1/results/stream": {
      "get": {
        "tags": [
          "Results"
        ],
        "summary": "Stream observed price and availability records as NDJSON",
        "description": "Streams the same filter semantics as `GET /v1/results`, but returns the matching result records as newline-delimited JSON. This endpoint is intended for large result sets that are consumed incrementally. The stream remains subject to the authenticated user's permitted scope and the same filter semantics, including `capturedFrom`, `capturedTo`, `sort`, `timezone`, and `latestPerPair`. `globalScope=true` enables the same bounded cross-site read as the batch endpoint and requires both bounds with a maximum of 168 hours. The response carries `X-Results-Scope: scoped` or `global`. For an implicit 168-hour product-history window, all server-internal stream pages use one fixed logical UTC request time, so the window does not drift during the stream. If `RESULTS_SCOPE_TOO_BROAD` rejects the stream's initial request before its first page, `cursor`, `sort`, and the stream itself cannot resume or bypass a rejected first request; they apply only after an accepted read. Start a new request with a narrower scope (`itemId`, `pzn`, `ean`, `asinLocale` together with `asin`, `orderId`, or `site`) and/or narrower `capturedFrom`/`capturedTo` bounds. For `globalScope=true`, keep both bounds, omit product/order/site selectors, and keep the closed window at or below 168 hours; remove `globalScope` when an identifier- or site-scoped recovery is needed. There is no deferred job fallback.\n",
        "operationId": "streamResults",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "orderId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pzn",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ean",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asinLocale",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asin",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "site",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "globalScope",
            "in": "query",
            "description": "Explicit `globalScope=true` opt-in for one synchronous read across all authorized item/site pairs. Requires both `capturedFrom` and `capturedTo`, forbids item/order/site scope selectors, and limits the closed window to 168 hours.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "description": "Customer-visible product brand. Resolves permitted items first; combines with every other supplied filter as an intersection.\n",
            "schema": {
              "type": "string"
            },
            "example": "Example brand"
          },
          {
            "name": "manufacturer",
            "in": "query",
            "description": "Observed Result manufacturer filter. This is a Result observation, not an Item-master attribute.\n",
            "schema": {
              "type": "string"
            },
            "example": "Example manufacturer"
          },
          {
            "name": "merchant",
            "in": "query",
            "description": "Observed Result merchant/seller filter. Merchant-level Prime summaries are aggregations of matching Result observations, not a permanent merchant attribute.\n",
            "schema": {
              "type": "string"
            },
            "example": "Example merchant"
          },
          {
            "name": "isPrime",
            "in": "query",
            "description": "Exact observed Amazon Prime Boolean filter. `true` and `false` are distinct values; missing, null, and malformed source values are unknown and do not match `false`. Available only for canonical Amazon country markets (trimmed ASCII-casefolded `name=amazon` and a non-empty `country`); other shops have absent or different semantics.\n",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "isBuyBox",
            "in": "query",
            "description": "Exact observed Amazon Featured Offer (Buy Box) Boolean filter. `true` and `false` are distinct values; missing, null, and malformed source values are unknown and do not match `false`. Available only for canonical Amazon country markets (trimmed ASCII-casefolded `name=amazon` and a non-empty `country`); other shops have absent or different semantics.\n",
            "schema": {
              "type": "boolean"
            },
            "example": false
          },
          {
            "name": "coverageState",
            "in": "query",
            "description": "Coverage filter for the current result scope. Current documented values are `covered` and `missing_result`.\n",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "capturedFrom",
            "in": "query",
            "description": "Lower bound of the capturedAt window. RFC3339 or `YYYY-MM-DD`. Requires a scope (itemId/pzn/ean/asin/orderId/site), unless `globalScope=true` is supplied with both bounds.\n",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "capturedTo",
            "in": "query",
            "description": "Upper bound of the capturedAt window (inclusive day-end for a bare date). RFC3339 or `YYYY-MM-DD`. Requires a scope unless `globalScope=true` is supplied; global windows are limited to 168 hours.\n",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Orders by `capturedAt`. `asc` or `desc`; default `desc`.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "description": "IANA timezone (e.g. `Europe/Berlin`). Interprets date-only window bounds and renders `capturedAt` in that zone. Default `UTC`.\n",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latestPerPair",
            "in": "query",
            "description": "Returns the newest visible result for each permitted item-site pair in the filtered scope.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "latestObservationPerPair",
            "in": "query",
            "description": "Selects the complete newest observation set for each permitted item-site pair first, then applies manufacturer, merchant, isPrime, and isBuyBox filters. This differs from `latestPerPair` and must not be combined with it. The stream itself has no page cursor; an interrupted stream, scope guard, or partial read makes a summary incomplete.\n",
            "schema": {
              "type": "boolean"
            },
            "example": true
          },
          {
            "name": "includeCoverage",
            "in": "query",
            "description": "Includes optional coverage fields such as `coverageState`, `observedSites`, and `missingResultSites`. With an explicit `site` filter, coverage is derived from the paginated result set.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeOrderIds",
            "in": "query",
            "description": "Includes `orderId` on each streamed result record.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeExportFields",
            "in": "query",
            "description": "Includes the observation export fields `merchant`, `sku`, `breadcrumbs`, `customerReferencePrices`, `referencePrice`, `referencePriceMoney`, `isBuyBox`, `isPrime`, `productRating`, `brand`, and `manufacturer`. `isBuyBox` is the observed Amazon Featured Offer indicator and is omitted for missing, null, or non-Boolean source values. `isPrime` is independent from `isBuyBox` and is emitted as the observed Boolean `true` or `false` only for canonical Amazon country markets. It is omitted for other shops, unknown sites, and missing, null, or non-Boolean source values. `productRating` is emitted only for canonical Idealo DE with `value` validated in the documented 0 to 5 range and rounded to one decimal place; `scale` is 5. It is omitted for other platforms, including Idealo AT and Idealo All Results DE, and missing, malformed, or out-of-range source values.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeIdentity",
            "in": "query",
            "description": "Includes canonical external product identifiers `gtin` and `asin`.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeCustomerData",
            "in": "query",
            "description": "Includes the permitted `customerData` subset on each streamed result record.\n",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Observed price and availability records as newline-delimited JSON",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControlNoStore"
              },
              "X-Results-Scope": {
                "description": "Whether the stream was evaluated as the default scoped read or the explicit global read.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "scoped",
                    "global"
                  ]
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters. `code` is `MVP_VALIDATION_ERROR` for ordinary validation failures, including a `globalScope=true` request that omits `capturedFrom` or `capturedTo` or that also carries a product, order or site selector. The stream's first page goes through the same results read as `GET /v1/results`, so `code` = `RESULTS_LATEST_PAIR_SCOPE_TOO_BROAD` is returned when `latestPerPair=true` covers more than 1,000 permitted item-site pairs; narrow the request with `itemId`, `orderId`, `site`, or a product identifier (`pzn`, `ean`, or `asin`). `code` = `RESULTS_SCOPE_TOO_BROAD` is returned in the same two independent cases. First, always and regardless of configuration, when a `globalScope=true` window exceeds 168 hours; shorten the window. Second, when the optional results scan guard is enabled (env `RUST_API_RESULTS_SCAN_GUARD_MAX_SCOPE_PAIRS` / `_MAX_WINDOW_HOURS`, disabled by default) and the authorized scope and capturedAt window are jointly too broad, the stream's initial request is rejected before its first page. `cursor`, `sort`, and the stream itself cannot resume or bypass a rejected first request; they apply only after an accepted read. Start a new request with a narrower scope (`itemId`, `pzn`, `ean`, `asinLocale` together with `asin`, `orderId`, or `site`) and/or narrower `capturedFrom`/`capturedTo` bounds. For `globalScope=true`, keep both bounds, omit product/order/site selectors, and keep the closed window at or below 168 hours; remove `globalScope` when an identifier- or site-scoped recovery is needed. There is no deferred job fallback.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      },
      "McpOAuth": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code flow with PKCE for MCP clients. Clients should discover the protected resource and authorization server before starting the flow. `offline_access` is optional when refresh access is required.\n",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.preismonitoring.de/oauth/authorize",
            "tokenUrl": "https://api.preismonitoring.de/oauth/token",
            "refreshUrl": "https://api.preismonitoring.de/oauth/token",
            "scopes": {
              "mcp": "Access to PREISmonitoring MCP tools, resources, and prompts",
              "offline_access": "Request a refresh token for continued access"
            }
          }
        }
      }
    },
    "parameters": {
      "McpProtocolVersion": {
        "name": "MCP-Protocol-Version",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "2026-07-28",
            "2025-11-25",
            "2025-06-18",
            "2025-03-26"
          ]
        },
        "description": "MCP protocol version selected by the client. Legacy requests may omit this header according to the server compatibility behavior. The modern `2026-07-28` wire profile requires the MCP request metadata headers.\n"
      },
      "McpMethod": {
        "name": "mcp-method",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "MCP method metadata for the modern `2026-07-28` wire profile. When the profile is used, it is required and must match the JSON-RPC `method` value. Legacy requests omit this header.\n"
      },
      "McpName": {
        "name": "mcp-name",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "MCP name or resource-URI metadata for the modern `2026-07-28` wire profile. It is required for `tools/call`, `prompts/get`, and `resources/read` and must match the corresponding JSON-RPC parameter; legacy requests and other modern methods omit this header.\n"
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1
        },
        "description": "Maximum page size. Default is 50 when the client does not provide a value. Effective maximums depend on the endpoint: up to 1,000 for items, 100 for sites, orders, and history resources, and `RUST_API_RESULTS_MAX_LIMIT` for results endpoints (default and absolute maximum of 10,000).\n"
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "An opaque cursor from a previous page. Clients must not construct or inspect cursor values and should treat them as implementation-defined pagination tokens.\n"
      },
      "OrderIdPath": {
        "name": "orderId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "DateFrom": {
        "name": "dateFrom",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "DateTo": {
        "name": "dateTo",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "headers": {
      "ContentSecurityPolicy": {
        "description": "Browser content policy; OAuth HTML pages use a nonce-based variant",
        "schema": {
          "type": "string"
        }
      },
      "ReferrerPolicy": {
        "schema": {
          "type": "string",
          "const": "no-referrer"
        }
      },
      "XContentTypeOptions": {
        "schema": {
          "type": "string",
          "const": "nosniff"
        }
      },
      "XFrameOptions": {
        "schema": {
          "type": "string",
          "const": "DENY"
        }
      },
      "CacheControlNoStore": {
        "schema": {
          "type": "string",
          "const": "no-store"
        }
      },
      "XRequestId": {
        "description": "Correlation ID for client and server logs",
        "schema": {
          "type": "string"
        }
      },
      "WWWAuthenticate": {
        "description": "OAuth protected-resource challenge",
        "schema": {
          "type": "string"
        }
      },
      "XRateLimitLimit": {
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitRemaining": {
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitReset": {
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "schema": {
          "type": "integer"
        }
      },
      "ContentDispositionAttachment": {
        "description": "Safe attachment metadata. The service limits the UTF-8 filename to 255 bytes, emits a conservative ASCII `filename` fallback, and adds an RFC-5987 UTF-8 `filename*` value. Path segments and control characters cannot inject response headers.\n",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request parameters or a terminal resource-budget rejection. Stable budget codes include `RESPONSE_TOO_LARGE`, `AUTH_SCOPE_TOO_BROAD`, `HISTORY_SCOPE_TOO_BROAD`, `ITEM_SCOPE_TOO_BROAD`, `ORDER_SCOPE_TOO_BROAD`, `RESULTS_SCOPE_TOO_BROAD`, `RESULTS_LATEST_PAIR_SCOPE_TOO_BROAD`, and `ORDER_COVERAGE_SCOPE_TOO_BROAD`. Budget rejections never return truncated JSON or partial pages.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid authentication",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "McpUnauthorized": {
        "description": "Missing or invalid OAuth authentication for the MCP endpoint",
        "headers": {
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WWWAuthenticate"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Access outside the permitted scope. For history operations, an `orderId` that is not listed in the explicitly authorized `order_ids` is rejected with `AUTH_SCOPE_DENIED` and HTTP 403.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Requested resource was not found. History operations use `ORDER_NOT_FOUND` only when mandate-based filtering finds no active order in an authorized mandate. An `orderId` outside an explicit `order_ids` scope is instead rejected with `AUTH_SCOPE_DENIED` (HTTP 403), while a scope-valid order with no matching history artifact returns `HISTORY_ARTIFACT_NOT_FOUND`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "HistoryArtifactContentMissing": {
        "description": "The selected history artifact is present in the history catalog, but its referenced content is absent from every configured archive. The JSON error code is `HISTORY_ARTIFACT_CONTENT_MISSING`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "LogoutRevocationFailed": {
        "description": "The server could not persist the logout revocation. The presented token may remain valid until its expiry; clients should retry logout and continue treating the token as active until a successful response is received.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RequestBodyTooLarge": {
        "description": "REST request body exceeds the 65,536-byte transport limit. The non-MCP transport-level rejection uses the structured `ErrorResponse` with status `413` and code `PAYLOAD_TOO_LARGE`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ArchivePayloadTooLarge": {
        "description": "The matching archive object exceeds the configured download limit (128 MiB by default). The JSON error code is `PAYLOAD_TOO_LARGE`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "McpJsonRpcMessage": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "server/discover",
              "initialize",
              "tools/list",
              "tools/call",
              "resources/list",
              "resources/read",
              "resources/templates/list",
              "prompts/list",
              "prompts/get"
            ]
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "McpJsonRpcBatch": {
        "type": "array",
        "minItems": 1,
        "maxItems": 32,
        "items": {
          "$ref": "#/components/schemas/McpJsonRpcMessage"
        },
        "description": "JSON-RPC batch accepted only for the legacy `2025-03-26` protocol version. Newer protocol versions reject arrays.\n"
      },
      "McpJsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ]
          },
          "result": {
            "type": "object",
            "additionalProperties": true
          },
          "error": {
            "$ref": "#/components/schemas/McpJsonRpcError"
          }
        },
        "additionalProperties": true
      },
      "McpJsonRpcResponseBatch": {
        "type": "array",
        "minItems": 1,
        "maxItems": 32,
        "items": {
          "$ref": "#/components/schemas/McpJsonRpcResponse"
        },
        "description": "JSON-RPC response batch for legacy `2025-03-26` requests"
      },
      "McpJsonRpcErrorResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "error"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "$ref": "#/components/schemas/McpJsonRpcError"
          }
        },
        "additionalProperties": true
      },
      "McpJsonRpcError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "contractVersion",
          "build"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "ok"
          },
          "contractVersion": {
            "type": "string",
            "description": "Version of this OpenAPI contract, identical to `info.version`. Diagnostic only; not a feature-detection signal.\n",
            "examples": [
              "0.92"
            ]
          },
          "build": {
            "type": "string",
            "description": "Version of the running server build, the same value MCP clients receive as `serverInfo.version`. Diagnostic only.\n",
            "examples": [
              "0.128.0"
            ]
          }
        }
      },
      "AuthTokenRequest": {
        "type": "object",
        "required": [
          "loginIdentifier",
          "password"
        ],
        "properties": {
          "loginIdentifier": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "AuthTokenResponse": {
        "type": "object",
        "required": [
          "tokenType",
          "accessToken",
          "expiresIn"
        ],
        "properties": {
          "tokenType": {
            "type": "string",
            "const": "Bearer"
          },
          "accessToken": {
            "type": "string"
          },
          "expiresIn": {
            "type": "integer"
          }
        }
      },
      "Paging": {
        "type": "object",
        "required": [
          "limit",
          "returned"
        ],
        "properties": {
          "limit": {
            "type": "integer"
          },
          "returned": {
            "type": "integer"
          },
          "nextCursor": {
            "type": "string",
            "description": "`nextCursor` is an opaque cursor for the next page when more data is available.\n"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "actualBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Determined or observed raw payload size for a size-specific error."
          },
          "maxBytes": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Permitted raw payload size for a size-specific error."
          }
        }
      },
      "Site": {
        "type": "object",
        "properties": {
          "site": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "country": {
            "type": "string"
          }
        }
      },
      "SitesPage": {
        "type": "object",
        "required": [
          "data",
          "paging"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Site"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        }
      },
      "SupportedAsinLocalesResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "supportedAsinLocales"
            ],
            "properties": {
              "supportedAsinLocales": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Item": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "pzn": {
            "type": "string"
          },
          "ean": {
            "type": "string"
          },
          "asin": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "brand": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "customerData": {
            "type": "object",
            "additionalProperties": true
          },
          "customerAliases": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "directLinkSites": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "imageCount": {
            "type": "integer"
          }
        }
      },
      "ItemsPage": {
        "type": "object",
        "required": [
          "data",
          "paging"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Item"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        }
      },
      "OrderListItem": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "alias": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "siteCount": {
            "type": "integer"
          },
          "itemCount": {
            "type": "integer"
          },
          "maxItems": {
            "type": "integer"
          }
        }
      },
      "OrdersPage": {
        "type": "object",
        "required": [
          "data",
          "paging"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderListItem"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        }
      },
      "OrderDetailResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/OrderDetail"
          }
        }
      },
      "OrderDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/OrderListItem"
          },
          {
            "type": "object",
            "required": [
              "priority",
              "spread",
              "sites",
              "monitoring",
              "coverageSummary",
              "healthSummary",
              "qualitySummary",
              "monitoringSites"
            ],
            "properties": {
              "priority": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "spread": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "sites": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "monitoring": {
                "$ref": "#/components/schemas/OrderMonitoringSummary"
              },
              "coverageSummary": {
                "$ref": "#/components/schemas/OrderCoverageSummary"
              },
              "healthSummary": {
                "$ref": "#/components/schemas/OrderHealthSummary"
              },
              "qualitySummary": {
                "$ref": "#/components/schemas/OrderQualitySummary"
              },
              "monitoringSites": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OrderMonitoringSite"
                }
              }
            }
          }
        ]
      },
      "OrderMonitoringSummary": {
        "type": "object",
        "required": [
          "state",
          "reportedSites",
          "criticalSites",
          "warningSites",
          "noticeSites",
          "okSites",
          "lastReportAt"
        ],
        "properties": {
          "state": {
            "type": "string"
          },
          "reportedSites": {
            "type": "integer",
            "minimum": 0
          },
          "criticalSites": {
            "type": "integer",
            "minimum": 0
          },
          "warningSites": {
            "type": "integer",
            "minimum": 0
          },
          "noticeSites": {
            "type": "integer",
            "minimum": 0
          },
          "okSites": {
            "type": "integer",
            "minimum": 0
          },
          "lastReportAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "OrderCoverageSummary": {
        "type": "object",
        "required": [
          "trackedSites",
          "missingResultSites",
          "resultCoverageState"
        ],
        "properties": {
          "trackedSites": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "missingResultSites": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "resultCoverageState": {
            "type": "string"
          }
        }
      },
      "OrderHealthSummary": {
        "type": "object",
        "required": [
          "resultHealth",
          "lowHitAlert"
        ],
        "properties": {
          "resultHealth": {
            "type": "string"
          },
          "lowHitAlert": {
            "type": "boolean"
          }
        }
      },
      "OrderMonitoringSite": {
        "type": "object",
        "required": [
          "site",
          "siteName",
          "state",
          "capturedAt",
          "intervalHours",
          "total",
          "expected",
          "completed",
          "found",
          "toDo",
          "issues",
          "warnings",
          "lag",
          "botProtection",
          "notFound",
          "ambiguous",
          "notEnoughInfo",
          "noPriceFound",
          "notAvailable",
          "others",
          "reportId"
        ],
        "properties": {
          "site": {
            "type": "string"
          },
          "siteName": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string"
          },
          "capturedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "intervalHours": {
            "type": [
              "integer",
              "null"
            ]
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "expected": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "completed": {
            "type": "integer",
            "minimum": 0
          },
          "found": {
            "type": "integer",
            "minimum": 0
          },
          "toDo": {
            "type": "integer",
            "minimum": 0
          },
          "issues": {
            "type": "integer",
            "minimum": 0
          },
          "warnings": {
            "type": "integer",
            "minimum": 0
          },
          "lag": {
            "type": "integer",
            "minimum": 0
          },
          "botProtection": {
            "type": "integer",
            "minimum": 0
          },
          "notFound": {
            "type": "integer",
            "minimum": 0
          },
          "ambiguous": {
            "type": "integer",
            "minimum": 0
          },
          "notEnoughInfo": {
            "type": "integer",
            "minimum": 0
          },
          "noPriceFound": {
            "type": "integer",
            "minimum": 0
          },
          "notAvailable": {
            "type": "integer",
            "minimum": 0
          },
          "others": {
            "type": "integer",
            "minimum": 0
          },
          "reportId": {
            "type": "string"
          }
        }
      },
      "OrderQualitySummary": {
        "type": "object",
        "required": [
          "configuredObservations",
          "expectedProcessedByNow",
          "processedObservations",
          "successfulObservations",
          "pendingObservations",
          "temporarilyAccessRestricted",
          "ambiguousMatch",
          "productNotFound",
          "insufficientInformation",
          "priceNotDetermined",
          "productUnavailable",
          "otherCollectionIssue",
          "sourceCountsConsistent",
          "reportedSites",
          "lastSnapshotAt"
        ],
        "properties": {
          "configuredObservations": {
            "type": "integer",
            "minimum": 0
          },
          "expectedProcessedByNow": {
            "type": "integer",
            "minimum": 0
          },
          "processedObservations": {
            "type": "integer",
            "minimum": 0
          },
          "successfulObservations": {
            "type": "integer",
            "minimum": 0
          },
          "pendingObservations": {
            "type": "integer",
            "minimum": 0
          },
          "temporarilyAccessRestricted": {
            "type": "integer",
            "minimum": 0
          },
          "ambiguousMatch": {
            "type": "integer",
            "minimum": 0
          },
          "productNotFound": {
            "type": "integer",
            "minimum": 0
          },
          "insufficientInformation": {
            "type": "integer",
            "minimum": 0
          },
          "priceNotDetermined": {
            "type": "integer",
            "minimum": 0
          },
          "productUnavailable": {
            "type": "integer",
            "minimum": 0
          },
          "otherCollectionIssue": {
            "type": "integer",
            "minimum": 0
          },
          "sourceCountsConsistent": {
            "type": "boolean",
            "description": "True when the unchanged source categories reconcile with the configured and processed totals of every included site snapshot.\n"
          },
          "reportedSites": {
            "type": "integer",
            "minimum": 0
          },
          "lastSnapshotAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "OrderObservationReasonCode": {
        "type": "string",
        "description": "`PRODUCT_NOT_FOUND` is a regular negative market observation that can be valuable for assortment-depth analysis, not an API, crawler, shop, provider, or system error by itself. It is a quality problem only as a false negative, when the product actually existed at the observation time but was classified as missing. The API reports the observed classification and cannot prove a false negative without external ground truth.\n",
        "enum": [
          "SUCCESSFUL",
          "NOT_YET_PROCESSED",
          "ACCESS_TEMPORARILY_RESTRICTED",
          "AMBIGUOUS_MATCH",
          "PRODUCT_NOT_FOUND",
          "INSUFFICIENT_INFORMATION",
          "PRICE_NOT_DETERMINED",
          "PRODUCT_UNAVAILABLE",
          "COLLECTION_ERROR",
          "UNKNOWN"
        ]
      },
      "OrderObservationQuality": {
        "type": "object",
        "required": [
          "itemId",
          "site",
          "observationState",
          "reasonCode",
          "snapshotAt",
          "reportId"
        ],
        "properties": {
          "itemId": {
            "type": "string"
          },
          "site": {
            "type": "string"
          },
          "observationState": {
            "type": "string",
            "enum": [
              "successful",
              "pending",
              "delayed",
              "unresolved",
              "unknown"
            ]
          },
          "reasonCode": {
            "$ref": "#/components/schemas/OrderObservationReasonCode"
          },
          "snapshotAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "reportId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "OrderObservationQualityPage": {
        "type": "object",
        "required": [
          "data",
          "paging"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderObservationQuality"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        }
      },
      "NamedHistoryEntry": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "lastExportDate": {
            "type": "string",
            "format": "date-time"
          },
          "lastImportDate": {
            "type": "string",
            "format": "date-time"
          },
          "nextExpected": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "NamedHistoryPage": {
        "type": "object",
        "required": [
          "data",
          "paging"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NamedHistoryEntry"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        }
      },
      "HistoryEntry": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          }
        }
      },
      "HistoryPage": {
        "type": "object",
        "required": [
          "data",
          "paging"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HistoryEntry"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        }
      },
      "HistorySingleResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/HistoryEntry"
          }
        }
      },
      "CustomerReferencePrice": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "value",
          "amountMinor",
          "currencyCode"
        ],
        "properties": {
          "value": {
            "type": "string",
            "description": "Original decimal value in major currency units."
          },
          "amountMinor": {
            "type": "integer",
            "description": "The same value normalized to the smallest currency unit."
          },
          "currencyCode": {
            "type": "string",
            "description": "Uppercase ISO 4217 currency code."
          },
          "appliesToSite": {
            "type": "string",
            "description": "Public site key; absent when the reference price applies generically."
          },
          "referenceQuantity": {
            "type": "integer",
            "minimum": 1,
            "description": "Packaging or reference quantity to which the price applies; absent when unspecified."
          },
          "priceType": {
            "type": "string",
            "description": "Customer-defined reference-price type; absent when unspecified."
          }
        }
      },
      "Result": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "itemId": {
            "type": "string"
          },
          "orderId": {
            "type": "string"
          },
          "site": {
            "type": "string"
          },
          "capturedAt": {
            "type": "string",
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "pzn": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "price": {
            "type": "integer",
            "description": "Price in the smallest unit of the reported currency, for example cents for EUR.\n"
          },
          "priceMoney": {
            "$ref": "#/components/schemas/CanonicalMoney"
          },
          "currency": {
            "type": "string"
          },
          "availability": {
            "type": "string"
          },
          "offerUrl": {
            "type": "string",
            "description": "External offer/detail page URL of the result."
          },
          "coverageState": {
            "type": "string"
          },
          "observedSites": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "missingResultSites": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "customerData": {
            "type": "object",
            "additionalProperties": true
          },
          "manufacturer": {
            "type": "string",
            "description": "includeExportFields. Manufacturer as observed on this Result at `capturedAt`; not an Item-master attribute.\n"
          },
          "merchant": {
            "type": "string",
            "description": "includeExportFields. Merchant/seller on the platform (distinct from `site`); absent for direct shops.\n"
          },
          "sku": {
            "type": "string",
            "description": "includeExportFields. Shop SKU as observed."
          },
          "breadcrumbs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "includeExportFields. Category/breadcrumb path."
          },
          "referencePrice": {
            "type": "integer",
            "description": "includeExportFields. Customer-specific reference price from the authorized mandate's reference-price collection, in the smallest currency unit. Emitted only when exactly one entry matches the Result currency and its exact or generic site context.\n"
          },
          "referencePriceMoney": {
            "$ref": "#/components/schemas/CanonicalMoney"
          },
          "customerReferencePrices": {
            "type": "array",
            "description": "includeExportFields. All customer-specific reference prices from the authorized mandate that match the Result currency and either its exact site or no site. Exact-site entries precede generic entries. Different price types and reference quantities remain distinct; publicly identical entries are deduplicated.\n",
            "items": {
              "$ref": "#/components/schemas/CustomerReferencePrice"
            }
          },
          "isBuyBox": {
            "type": "boolean",
            "description": "includeExportFields. Amazon Featured Offer (Buy Box) Boolean observed on this Result at `capturedAt`, not an Item or Merchant master attribute. The source value is emitted unchanged as `true` or `false` only for canonical Amazon country markets. It is unknown and omitted for other shops, unknown sites, and missing, null, or non-Boolean source values. This does not expose merchant or Buy Box price fields.\n"
          },
          "isPrime": {
            "type": "boolean",
            "description": "includeExportFields. Amazon Prime Boolean observed on this Result at `capturedAt`, not an Item or Merchant master attribute, and independent from `isBuyBox`. The source value is emitted unchanged as `true` or `false` only for canonical Amazon country markets. It is unknown and omitted for other shops, unknown sites, and missing, null, or non-Boolean source values.\n"
          },
          "productRating": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "value"
            ],
            "description": "includeExportFields. Product rating observed on this Result at `capturedAt`, not an Item-master quality label. Emitted only for canonical Idealo DE when the source value is in the documented 0 to 5 range and rounded to one decimal place. Omitted for other platforms, including Idealo AT and Idealo All Results DE, and missing, malformed, or out-of-range source values.\n",
            "properties": {
              "value": {
                "type": "number",
                "minimum": 0,
                "maximum": 5,
                "description": "Observed Idealo DE rating, validated in the documented 0 to 5 range and rounded to one decimal place."
              },
              "scale": {
                "type": "number",
                "enum": [
                  5
                ],
                "description": "Documented rating scale; emitted when proven by the source contract."
              }
            }
          },
          "gtin": {
            "type": "string",
            "description": "includeIdentity. Canonical GTIN/EAN from the item master."
          },
          "asin": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "includeIdentity. ASIN per locale from the item master."
          }
        }
      },
      "CanonicalMoney": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "amountMinor",
          "currencyCode",
          "fractionDigits",
          "rawCurrency",
          "normalizationState"
        ],
        "properties": {
          "amountMinor": {
            "type": "integer",
            "description": "Unchanged source amount in minor units; no conversion is performed."
          },
          "currencyCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO-4217 code when normalization is unambiguous; otherwise null."
          },
          "fractionDigits": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "ISO-4217 minor-unit exponent when normalization is resolved; otherwise null."
          },
          "rawCurrency": {
            "type": [
              "string",
              "null"
            ],
            "description": "Currency value as observed in the source, preserved without rewriting."
          },
          "normalizationState": {
            "type": "string",
            "enum": [
              "resolved",
              "unresolved"
            ],
            "description": "Resolved only for an explicit supported ISO code or an unambiguous symbol-country mapping."
          }
        }
      },
      "ResultsPage": {
        "type": "object",
        "required": [
          "data",
          "paging",
          "query"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Result"
            }
          },
          "paging": {
            "$ref": "#/components/schemas/Paging"
          },
          "query": {
            "$ref": "#/components/schemas/ResultsQueryScope"
          }
        }
      },
      "ResultsQueryScope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "scope"
        ],
        "properties": {
          "scope": {
            "type": "string",
            "enum": [
              "scoped",
              "global"
            ],
            "description": "Whether the read used the normal authorized scope or the explicit `globalScope=true` opt-in. This object carries the scope marker only; server-internal query planning is not part of the REST contract.\n"
          }
        }
      },
      "ResultsScopeGuard": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "errorCode",
          "rejectedBeforeFirstPage",
          "recoveryAction",
          "narrowerScopeFields",
          "narrowerWindowFields",
          "cursorCanResumeRejectedRequest",
          "sortCanBypassRejectedRequest",
          "streamCanBypassRejectedRequest"
        ],
        "properties": {
          "errorCode": {
            "type": "string",
            "const": "RESULTS_SCOPE_TOO_BROAD"
          },
          "rejectedBeforeFirstPage": {
            "type": "boolean",
            "const": true
          },
          "recoveryAction": {
            "type": "string",
            "const": "newRequest"
          },
          "narrowerScopeFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "const": [
              "itemId",
              "pzn",
              "ean",
              "asinLocale",
              "asin",
              "orderId",
              "site"
            ]
          },
          "narrowerWindowFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "const": [
              "capturedFrom",
              "capturedTo"
            ]
          },
          "cursorCanResumeRejectedRequest": {
            "type": "boolean",
            "const": false
          },
          "sortCanBypassRejectedRequest": {
            "type": "boolean",
            "const": false
          },
          "streamCanBypassRejectedRequest": {
            "type": "boolean",
            "const": false
          }
        }
      },
      "BinaryPayload": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}