# PREISmonitoring public API contract changelog This changelog is written for integration partners. It records changes to the public REST and MCP contract — the behavior clients build against. The authoritative specification is `openapi.yaml` in this directory. It is available at `/openapi/openapi.yaml`, rendered at `/docs`, and accompanied by this changelog at `/openapi/CHANGELOG.md`. Version numbers below always refer to `info.version` in that specification. ## Scope This document records outward-facing contract changes, not implementation or operational history. The following identifiers have separate meanings: | Identifier | Meaning | Public source | | --- | --- | --- | | Contract version | Whether the behavior clients integrate against changed | `info.version` and `contractVersion` from `GET /healthz` | | Build version | Which service build responded | `build` from `GET /healthz` and MCP `serverInfo.version` from `initialize` | | Release | A deployment identifier | Not part of this public record | Every actual change to the published REST or MCP promise — including paths, parameters, response schemas, headers, error contracts, discovery, or authentication — appears here with a corresponding contract-version change. A release without outward contract effect does not appear here. ## Maintenance - Every actual public REST/MCP contract change increments `info.version` by exactly `0.01` under the established continuous versioning convention. - Build and release identifiers remain separate from the contract version. - A proven contract restoration may retain the existing version when it only aligns observed behavior with the already published promise; the rationale is recorded without exposing implementation or deployment details. - A wording or example change without semantic effect is not a contract change and does not require a new entry. The published contract is checked for consistency with its version. Changes to scope, pagination, time, completeness, or other behavior still require explicit classification even when the static contract shape is unchanged. ## 1.00 — 2026-09-10 ### Documentation accessibility restoration — 2026-09-13 The documentation landing page now links to a generated OpenAPI JSON representation alongside the authoritative YAML specification and exposes the contract version, documentation update time, authentication routes, and first request without requiring JavaScript. `llms.txt`, `llms-full.txt`, and the contract changelog use the broadly compatible `text/plain` media type while retaining their Markdown structure. This restores broadly compatible retrieval options for the already published contract at the API boundary. Individual external retrieval providers remain outside the server's control. REST and MCP domain behavior, authentication, authorization, and data semantics are unchanged, so the contract version remains `1.00`. Results requested with `includeExportFields=true` now expose `customerReferencePrices`, sourced exclusively from the authorized mandate's customer-specific reference-price data. Entries match the Result currency and either its exact site or the generic no-site context. Exact-site entries are listed first; all matching customer-defined price types and reference quantities remain available, while publicly identical entries are deduplicated. Each entry contains `value`, `amountMinor`, `currencyCode`, and—when present— `appliesToSite`, `referenceQuantity`, and `priceType`. `referenceQuantity` describes the packaging or reference quantity for that price; it is not by itself a minimum-order threshold. The existing singular `referencePrice` and `referencePriceMoney` fields now represent this same customer-specific source and are emitted only when exactly one matching entry is unambiguous. `get_market_price_position` uses the same rule when `includeCustomerReference=true`; multiple or missing matches retain the market median. Customer-data fields are no longer interpreted as reference prices. REST Results, Results streaming, and MCP `list_results` share these semantics. This corrective public contract change raises the shared contract version from `0.99` to `1.00`. Authentication and authorized item visibility are unchanged. ## 0.99 — 2026-08-30 Structured REST errors now use one strict Problem Details object. The shared `ErrorResponse` requires `type`, `title`, `status`, `detail`, and `code`, and rejects additional fields. The non-MCP transport-level request-body limit returns the same JSON shape with `413 PAYLOAD_TOO_LARGE`. The REST authentication endpoint maps JSON syntax, type, and content-type rejections to structured `400 MVP_VALIDATION_ERROR` responses. This contract restoration and schema clarification is published in contract version `0.99`; MCP body-limit and transport-envelope behavior remain unchanged. History operations now expose stable failure codes for the distinct cases of a missing order (`ORDER_NOT_FOUND`, HTTP 404), a missing matching history artifact (`HISTORY_ARTIFACT_NOT_FOUND`, HTTP 404), and a catalogued artifact whose content is absent from every configured archive (`HISTORY_ARTIFACT_CONTENT_MISSING`, HTTP 409). The latter applies to both export and import downloads. Authentication, permitted-scope checks, empty history responses, and other storage failures remain unchanged. MCP order artifact downloads now use the same configured raw-object limit as the REST archive download operations for both export and import history. The previous fixed 1 MiB MCP-only raw limit is removed. A standalone MCP tool call still uses a bounded serialized-response budget that accounts for Base64 expansion, the two published MCP representations, and a fixed envelope reserve; JSON-RPC batches keep their aggregate 64 MiB budget and give each successive response only the remaining share. Each download's raw fetch is capped before materialization at the largest raw value whose conservative double-representation budget fits within that remainder. Larger batch downloads are rejected in a controlled way. Valid UTF-8 remains UTF-8 when JSON escaping fits, otherwise the response uses the already published Base64 encoding without changing the raw `sizeBytes` value. A `413 PAYLOAD_TOO_LARGE` response now publishes the known or observed raw size as `actualBytes` and the permitted maximum as `maxBytes` in REST Problem Details and the structured MCP error; the detail also contains both values. REST paths, selectors, authentication, authorization scope, and history selection are unchanged. The shared REST error schema gains only the two optional size fields. The MCP export and import tools remain read-only and use the same metadata and output schema. This public MCP behavior change raises the shared contract version from `0.98` to `0.99`; all REST and MCP artifacts in this change use that same contract version. `latestPerPair=true` now returns a dedicated structured `400` `RESULTS_LATEST_PAIR_SCOPE_TOO_BROAD` error when a synchronous read covers more than 1,000 permitted item-site pairs. REST and MCP share these validation semantics while retaining their respective response envelopes: REST returns Problem Details and MCP returns its JSON-RPC tool error result with guidance to narrow by item, order, site, or product identifier. The 1,000-pair boundary, query limits, pagination behavior, authentication, and visibility rules remain unchanged. Results recovery guidance now distinguishes a rejected first request from a successful paginated read. `RESULTS_SCOPE_TOO_BROAD` documentation and MCP guidance direct clients to start a new request with narrower scope and/or capture bounds; cursors, sort order, and the NDJSON stream are not bypasses for an initial rejection. Existing REST/MCP parameters and data semantics are unchanged. The machine-readable capabilities response also declares the required `scopeGuard` object and its recovery fields for schema-aware clients. The scope recovery guidance is part of the shared contract version `0.99`. MCP `list_items(discoverCategories=true)` now returns a successful page with an empty `search.availableCategories` list when no usable category exists. The `ITEM_CATEGORY_NOT_AVAILABLE` error remains limited to explicit `category` filters. Category resolution adds the published `category` and `categories` mappings for Demo, TalDemo, and Tripuls. An already-visible customer namespace without an explicit mapping may contribute only a non-empty `category` string or string array. Resolution still reads exclusively from the caller's scope-projected customer data; categories from other customers remain invisible. The category discovery behavior is part of the shared contract version `0.99`; REST operations and authentication behavior are unchanged. ## 0.98 — 2026-08-21 Results now support an explicit bounded global read across all data visible to the authorized caller. REST `GET /v1/results` and `/v1/results/stream`, plus MCP `list_results`, accept `globalScope=true` only together with both `capturedFrom` and `capturedTo`, without a product, order, or site selector and with a maximum closed window of 168 hours. Authorization, pagination, sorting, and the existing synchronous response and request limits remain in force; the contract does not create a deferred job. Batch REST and MCP responses expose `query.scope` as `scoped` or `global`. The NDJSON stream exposes the same value through `X-Results-Scope`. The REST query object contains the documented scope marker; MCP retains its published query representation. An explicit unscoped window without `globalScope=true` remains a controlled validation error. A `globalScope=true` window above 168 hours returns `400 RESULTS_SCOPE_TOO_BROAD`. Time-only reads document both budget outcomes: a hard `504 RESULTS_QUERY_TIMEOUT` and a soft-deadline `200` partial page that must be followed through `paging.nextCursor`. This additive REST/MCP contract change raises the version from `0.97` to `0.98`. No other authentication or installation behavior changes. ## 0.97 — 2026-08-16 Export and import artifact downloads now guarantee a concrete `Content-Type` in REST and a concrete `contentType` in MCP, including the mirrored `metadata.contentType` field. The download filename determines the media type: CSV uses `text/csv; charset=utf-8`, XLSX uses `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`, ZIP uses `application/zip`, and other filenames use `application/octet-stream`. The same version also raises the shared serialized JSON response limit from `32 MiB` to `64 MiB` for REST JSON, complete NDJSON lines, and MCP responses and batches. `RESPONSE_TOO_LARGE` remains the structured protection response when that limit is exceeded. This contract change raises the version from `0.96` to `0.97`. No new endpoint, MCP tool, or OAuth scope is introduced. ## 0.96 — 2026-08-12 Results now offer the optional `productRating` object through the existing `includeExportFields=true` group in `GET /v1/results`, `GET /v1/results/stream`, and MCP `list_results`. The same field is described by the Results capabilities endpoint and MCP `describe_results_contract`. The first version is limited to canonical Idealo Germany observations. `value` is accepted only within the documented range from 0 to 5 and is rounded to one decimal place; the scale is returned as `scale: 5`. The object is absent for other platforms, including Idealo Austria and Idealo All Results Germany, and for missing, malformed, or out-of-range source values. It is an observation at `capturedAt`, not a permanent product-quality label; rating counts are not part of this release. This additive contract change raises the version from `0.95` to `0.96`. ## 0.95 — 2026-08-12 The `category` query argument has been removed from `GET /v1/results`, `GET /v1/results/stream`, and MCP `list_results`. Results do not carry a contractual category field, so sending `category` to a Results operation is now rejected as an unknown argument rather than being ignored. Category search remains available through MCP `list_items(category=...)`, where category discovery is explicit. Clients answer category questions by discovering visible products first and then querying Results for a selected product. All other Results offer filters remain unchanged. This breaking removal raises the contract from `0.94` to `0.95`. ## 0.94 — 2026-08-11 Results can now be filtered by customer-facing product entry points (`category`, `brand`), observed `manufacturer` and `merchant`, and exact observed `isPrime` or `isBuyBox` values. `GET /v1/results`, `GET /v1/results/stream`, and MCP `list_results` retain the same endpoint and tool. - **Observations, not master data.** Prime and Buy Box belong to a Result at `capturedAt`, not permanently to an item or merchant. Merchant-level Prime summaries aggregate matching observed Results. - **Exact Amazon flags.** `true` and `false` are separate filter values. Missing, null, and malformed source values are unknown rather than `false`. The flags are defined only for canonical Amazon country markets; other shops may omit them or use different semantics. - **Complete latest observation sets.** `latestObservationPerPair=true` selects the complete newest set per item/site before manufacturer, merchant, Prime, and Buy Box filters apply. It is different from `latestPerPair`. Clients must follow cursor pages completely and report an interrupted or incomplete read as incomplete. This additive change raises the contract from `0.93` to `0.94`. ## 0.93 — 2026-08-11 Results now optionally expose the observed Amazon Prime status `isPrime` through `includeExportFields=true` in `GET /v1/results`, `GET /v1/results/stream`, and MCP `list_results`. - The field is emitted only for canonical Amazon country markets. - “Amazon Top List”, other shops, and unknown sites remain excluded. - Both `true` and `false` are preserved as observations. Missing, null, and non-Boolean source values omit the field, so absence does not mean `false`. - `isPrime` and `isBuyBox` describe separate observations and may be present or absent independently. This additive change raises the contract from `0.92` to `0.93`. ## 0.92 — 2026-08-09 Orders now expose a customer-safe `qualitySummary` through `GET /v1/orders/{orderId}` and MCP `get_order_detail`. The summary maps the quality categories used by the customer view to stable API terminology. The paginated endpoint `GET /v1/orders/{orderId}/observation-quality` and MCP tool `list_order_observation_quality` expose the current observation snapshot per product and site. Technical retries do not inflate `configuredObservations` or `expectedProcessedByNow`. Temporary access restrictions use the neutral code `ACCESS_TEMPORARILY_RESTRICTED`. Historical membership data that cannot be resolved is reported as `UNKNOWN`. Conflicting source counters remain visible through `sourceCountsConsistent=false`. The MCP prompt catalog adds the `analyze-buybox` workflow. It begins with `list_sites`, proceeds automatically when exactly one visible Amazon country market is available, and requests a market selection before `list_results` when several are available. Multi-market analysis is performed separately per `site` only when requested. The workflow requests `includeExportFields=true` and `latestPerPair=true`, distinguishes `isBuyBox=true`, `false`, and missing, and returns a market-level summary rather than an unbounded item list. ## 0.91 — 2026-08-09 The modern MCP tool catalog now documents the effect and structured result of all 14 published tools. The extension is additive; tool names, inputs, and domain behavior remain unchanged. - `readOnlyHint: true` states that a tool does not change data visible through the API. - `openWorldHint: false` states that a tool does not change public or external state. - `destructiveHint: false` states that a tool does not delete, overwrite, or trigger an irreversible action. - Every tool now publishes an `outputSchema` describing the structured result returned by `tools/call`. - The legacy wire profile remains unchanged; the additional metadata is available only in the modern profile. ## 0.9 — 2026-08-06 The public AI-client entry points `GET /llms.txt` and `GET /llms-full.txt` are now part of the published API contract. The change is additive: existing paths, parameters, response fields, and error contracts remain unchanged. - **`GET /llms.txt`** provides concise orientation and links to the published contract and supporting integration material. - **`GET /llms-full.txt`** provides the complete API reference as Markdown, generated from the OpenAPI specification. ## 0.8 — 2026-08-06 The health endpoint now exposes contract and build diagnostics, and two integration artifacts are publicly available. - `GET /healthz` reports `contractVersion` and `build`. Both are diagnostic values and are not feature-detection signals. - This changelog is available at `GET /openapi/CHANGELOG.md`. - The REST read collection is available at `GET /openapi/postman/preismonitoring-rest-read.postman_collection.json`. MCP is documented in the shared reference instead of being duplicated there. The existing `status` field of the health response is unchanged. ## 0.7 — 2026-08-05 The modern MCP profile now clarifies the meaning of `readOnlyHint`. The change is additive: no path, parameter, response field, or error contract changes. - `readOnlyHint` describes whether a tool changes data that a caller can later read. All published tools use `readOnlyHint: true` in this sense. - `list_results` changes from `false` to `true` so its annotation matches the behavior of the other read-only tools. - Clients that automatically approve read-only tools can therefore treat `list_results` consistently with the rest of the catalog. ## 0.6 — 2026-08-05 The shared REST and MCP reference surface is now published in one OpenAPI document. The extension is additive: the existing REST contract remains under its `/v1/*` paths, while MCP has a clearly marked transport description. - **Shared API contract.** The title, summary, and introduction describe REST and MCP as two protocol surfaces sharing one domain context. - **MCP transport.** `POST /mcp` documents JSON-RPC 2.0, requests, notifications, and the boundary between transport and dynamic tool discovery. - **Authentication.** The reference describes the OAuth 2.1 authorization code flow with PKCE, the `mcp` scope, and the optional `offline_access` scope. - **Examples and discovery.** Examples cover `initialize`, `tools/list`, `resources/list`, `prompts/list`, and a `tools/call` workflow. Concrete tool names and JSON Schemas continue to be published through `tools/list`. - **Modern MCP metadata.** The transport documents `MCP-Protocol-Version`, `mcp-method`, `mcp-name`, and the modern wire profile `2026-07-28`. The REST collection remains limited to REST requests. Detailed domain workflows, scope rules, and tool semantics remain in the user documentation. ## 0.5 — 2026-08-04 First entry of this changelog. It describes the contract as a whole because continuous records start here. The contract covers: - **Authentication.** `POST /v1/auth/token` accepts `loginIdentifier` and `password`; domain endpoints use `Authorization: Bearer `. `POST /v1/auth/logout` ends a session early. Administrative accounts are not supported on this API. `Basic` authentication is not permitted on domain endpoints and returns `401 AUTH_SCHEME_NOT_ALLOWED`. - **Read endpoints.** `GET /v1/sites`, `GET /v1/items`, `GET /v1/items/asin-locales`, `GET /v1/orders`, `GET /v1/orders/{orderId}`, `GET /v1/results`, `GET /v1/results/capabilities`, `GET /v1/results/stream`, and the export and import history routes under `GET /v1/orders/{orderId}/exports…` and `GET /v1/orders/{orderId}/imports…`. - **Operational endpoints.** `GET /healthz` requires no authentication, and `GET /openapi/openapi.yaml` returns this specification. - **Pagination.** Cursor-based pagination uses `limit` and `cursor`. `paging.nextCursor` points to the following page and is absent on the last page. Cursor direction follows `sort`. - **Visibility.** Non-administrative accounts see only data within their authorized domain scope. The scope is part of the contract. - **Error contracts.** Structured error objects contain `type`, `title`, `status`, `detail`, and `code`; every response carries `X-Request-Id`. - **Rate limits.** Throttling-relevant responses expose `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`. Exceedance returns `429` with `Retry-After` in seconds. MCP access under `/mcp` was documented separately at the start of this record. Version 0.6 brings its transport surface into the shared public reference; detailed tool and workflow descriptions remain in the user documentation.