{
  "openapi": "3.0.3",
  "info": {
    "title": "kwery API Reference",
    "version": "4.0",
    "license": {
      "name": "Proprietary",
      "url": "https://kwery.co"
    },
    "description": "Real-time price data across major European and global marketplaces.\n\nNew here? Start with the **[Guides](https://docs.kwery.co/)** — getting started,\nauthentication, webhooks, and per-source field reference.\n\n## Try it — no account needed\n\nA **mock server** is built into this reference: send requests to\n`https://docs.kwery.co/_mock/api-reference` and get back correctly-shaped example\nresponses — no signup, no API key (any dummy `Authorization` header passes),\nand no credits consumed. Select **Mock server** in the Servers panel and the\ncode samples switch to it automatically.\n\n```bash\ncurl -X POST https://docs.kwery.co/_mock/api-reference/job \\\n  -H \"Authorization: Bearer test123\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"source\":\"idealo\",\"country\":\"de\",\"key\":\"gtin\",\"values\":[\"4006381333962\"]}'\n```\n\nThe data returned is static example data from this specification, not a live\ncrawl — but the response shapes are exactly what production returns, so you can\nbuild and test your integration end-to-end before creating an account.\n\n## Source and key reference\n\nEach source supports a fixed set of `key` types. The `key` field\ndetermines what goes in `values`.\n\n| Source | Key | Values format | Supported countries |\n|--------|-----|---------------|---------------------|\n| `idealo` | `term` | Free-text search | de at uk (gb) fr it es |\n| `idealo` | `id` | Idealo product ID (numeric) | de at uk (gb) fr it es |\n| `idealo` | `gtin` | EAN / GTIN-13 | de at uk (gb) fr it es |\n| `idealo` | `pzn` | Pharmacy product number | de |\n| `amazon` | `term` | Free-text search | us ca mx br uk (gb) de at ch es fr it jp in ae au nl se pl be sg tr |\n| `amazon` | `asin` | Amazon ASIN (10 chars) | us ca mx br uk (gb) de at ch es fr it jp in ae au nl se pl be sg tr |\n| `amazon` | `gtin` | EAN / GTIN-13 | us ca mx br uk (gb) de at ch es fr it jp in ae au nl se pl be sg tr |\n| `google` | `term` | Free-text search | us de uk (gb) au at br ca cz dk fr in ie it jp mx no pl nz nl ru sg za es se fi ch tr ar cl co be gr hu pt ro sk hk id il my ph sa kr tw th ua vn ae |\n| `google` | `id` | Google Shopping product ID | us de uk (gb) au at br ca cz dk fr in ie it jp mx no pl nz nl ru sg za es se fi ch tr ar cl co be gr hu pt ro sk hk id il my ph sa kr tw th ua vn ae |\n| `google` | `product` | Pipe-separated product record — see `GoogleProductValue` | us de uk (gb) au at br ca cz dk fr in ie it jp mx no pl nz nl ru sg za es se fi ch tr ar cl co be gr hu pt ro sk hk id il my ph sa kr tw th ua vn ae |\n| `ebay` | `term` | Free-text search | au at be ca fr de ie it hk my nl pl sg es ch uk (gb) us |\n| `ebay` | `id` | eBay item ID (numeric) | au at be ca fr de ie it hk my nl pl sg es ch uk (gb) us |\n| `ebay` | `gtin` | EAN / GTIN-13 | au at be ca fr de ie it hk my nl pl sg es ch uk (gb) us |\n| `kaufland` | `term` | Free-text search | de cz sk pl at fr it |\n| `kaufland` | `id` | Kaufland product ID | de cz sk pl at fr it |\n| `kaufland` | `gtin` | EAN / GTIN-13 | de cz sk pl at fr it |\n| `otto` | `term` | Free-text search | de |\n| `otto` | `id` | Otto product ID | de |\n| `billiger` | `term` | Free-text search | de |\n| `billiger` | `id` | billiger.de product ID | de |\n| `billiger` | `gtin` | EAN / GTIN-13 | de |\n| `guenstiger` | `term` | Free-text search | de |\n| `guenstiger` | `id` | guenstiger.de product ID (numeric) | de |\n| `guenstiger` | `gtin` | EAN / GTIN-13 | de |\n| `walmart` | `term` | Free-text search | us |\n| `walmart` | `id` | Walmart item ID | us |\n| `walmart` | `gtin` | EAN / UPC / GTIN | us |\n| `lidl` | `term` | Free-text search | de at fr it nl pl uk … |\n| `lidl` | `id` | Lidl product ID | de at fr it nl pl uk … |\n| `aliexpress` | `term` | Free-text search | us |\n| `aliexpress` | `id` | AliExpress product ID | us |\n| `rakuten` | `term` | Free-text search | jp |\n| `rakuten` | `id` | Rakuten item ID | jp |\n\n> `uk (gb)` means `uk` and `gb` are two codes for the **same** UK marketplace —\n> pass either one, it is not a separate locale. For Amazon, `at` and `ch` are\n> served from the amazon.de storefront with Austria/Switzerland localization.\n\n## Authentication\n\nSign up at [kwery.co](https://kwery.co); the dashboard issues your API key. Send it on\nevery data-API request as either:\n- **Bearer** — `Authorization: Bearer kwy_live_...`\n- **API key header** — `x-api-key: kwy_live_...`\n\nLegacy/enterprise accounts provisioned before self-serve may still use HTTP Basic\n(username + password) or a Bearer JWT issued directly by us. See\n[Authentication](guides/authentication.md) for details.\n\nAccess is controlled per `source.country` pair. A `not subscribed to source`\nerror means your account is not provisioned for the requested combination.\n\n## Response envelope\n\nValidation errors return **HTTP 200** with `\"error\": true`. Always check the\n`error` field before consuming a response:\n\n```json\n{ \"error\": true, \"message\": \"country not supported by source\" }\n```\n\nInfrastructure errors (auth, 5xx) use standard HTTP status codes.\n\n## Stream API\n\nFor large batches (up to **100 000 values**), use the Stream endpoint.\nResults are pushed to your `callback_url` as they complete — no polling needed.\n\n1. `POST /stream` — submit values with a `callback_url`\n2. Results arrive at `callback_url` in batches as they complete\n3. `GET /stream/{id}` — optional progress check\n\n## Batch API\n\nFor standard batches (up to **1 000 values**), use the Batch endpoint.\nResults are retained for **72 hours**.\n\n1. `POST /job` — submit a list of values, receive a job ID\n2. `GET /job/{id}` — poll until `status` is `finished`\n3. `GET /job/{id}/download` — retrieve structured results\n"
  },
  "servers": [
    {
      "url": "https://api.kwery.co",
      "description": "Production"
    }
  ],
  "x-tagGroups": [
    {
      "name": "Stream API",
      "tags": [
        "stream"
      ]
    },
    {
      "name": "Batch API",
      "tags": [
        "jobs"
      ]
    }
  ],
  "tags": [
    {
      "name": "stream",
      "x-displayName": "Stream endpoints",
      "description": "Large-scale crawls with incremental webhook delivery. Supports up to\n**100 000 values** per job. Results are pushed to your endpoint as they\ncomplete — no polling required.\n"
    },
    {
      "name": "jobs",
      "x-displayName": "Batch endpoints",
      "description": "Standard batches up to **1 000 values**. Poll for results, then download.\nResults are retained for **72 hours**.\n"
    },
    {
      "name": "account",
      "x-displayName": "Account endpoints",
      "description": "Self-serve account: credit balance, API keys, and billing. These endpoints\nare authenticated with your **kwery.co dashboard session** (Supabase JWT)\nand are used by the dashboard UI — not called directly with your API key.\n"
    }
  ],
  "paths": {
    "/job": {
      "post": {
        "operationId": "submitJob",
        "x-seo": {
          "title": "Submit a Batch Job — kwery Docs",
          "description": "POST /job — submit up to 1,000 values for crawling and get a job id to poll."
        },
        "summary": "Submit a batch job",
        "description": "Submit a list of values to crawl. Returns immediately with a job\nobject; results are assembled asynchronously.\n\nThe request schema is discriminated on `source`. Select the source tab\nbelow to see the valid `key`, `topic`, and `country` values for that source.\n",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobSubmitRequest"
              },
              "examples": {
                "idealo_gtin": {
                  "summary": "Idealo — GTIN lookup",
                  "value": {
                    "source": "idealo",
                    "country": "de",
                    "key": "gtin",
                    "values": [
                      "4006381333962",
                      "4719512101148"
                    ]
                  }
                },
                "amazon_asin_with_offers": {
                  "summary": "Amazon — ASIN with all seller offers",
                  "value": {
                    "source": "amazon",
                    "country": "de",
                    "key": "asin",
                    "values": [
                      "B0847ZTV5Q"
                    ],
                    "topic": "search_and_offers"
                  }
                },
                "google_term": {
                  "summary": "Google Shopping — keyword search",
                  "value": {
                    "source": "google",
                    "country": "de",
                    "key": "term",
                    "values": [
                      "Tissot T-Touch Expert Solar"
                    ]
                  }
                },
                "google_product": {
                  "summary": "Google Shopping — product record lookup",
                  "value": {
                    "source": "google",
                    "country": "de",
                    "key": "product",
                    "values": [
                      "Tissot T-Touch Expert Solar||Tissot||7611608277942||850.00||https://www.zeitlounge.de/tissot-t-touch-expert-solar||",
                      "Seiko Prospex Alpinist||Seiko||4954628232342||450.00||||"
                    ]
                  }
                },
                "ebay_gtin": {
                  "summary": "eBay — GTIN search",
                  "value": {
                    "source": "ebay",
                    "country": "de",
                    "key": "gtin",
                    "values": [
                      "4006381333962"
                    ]
                  }
                },
                "kaufland_offers": {
                  "summary": "Kaufland — GTIN search with seller offers (Czech market)",
                  "value": {
                    "source": "kaufland",
                    "country": "cz",
                    "key": "gtin",
                    "topic": "search_and_offers",
                    "values": [
                      "4006381333962"
                    ]
                  }
                },
                "guenstiger_term": {
                  "summary": "Guenstiger — keyword search with offers",
                  "value": {
                    "source": "guenstiger",
                    "country": "de",
                    "key": "term",
                    "topic": "search_and_offers",
                    "values": [
                      "Tissot T-Touch Expert Solar"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job created. **Always check the `error` field** — validation failures\nalso return HTTP 200.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/JobSubmitResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                },
                "examples": {
                  "success": {
                    "value": {
                      "error": false,
                      "job": {
                        "_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                        "source": "idealo",
                        "country": "de",
                        "key": "gtin",
                        "topic": "search",
                        "values": [
                          "4006381333962"
                        ],
                        "max_pages": 1,
                        "max_age": 1200,
                        "timeout": 1440,
                        "status": "new",
                        "createdAt": "2026-04-03T10:00:00.000Z"
                      }
                    }
                  },
                  "validation_error": {
                    "value": {
                      "error": true,
                      "message": "country not supported by source"
                    }
                  },
                  "wait": {
                    "summary": "`wait` settled — results inline",
                    "description": "Mock server: send `x-redocly-response-body-example: wait` to get this\nshape instead of the default job object.\n",
                    "value": {
                      "error": false,
                      "job": {
                        "_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                        "source": "idealo",
                        "country": "de",
                        "key": "gtin",
                        "topic": "search",
                        "values": [
                          "4006381333962"
                        ],
                        "max_pages": 1,
                        "max_age": 1200,
                        "timeout": 1440,
                        "status": "finished",
                        "createdAt": "2026-04-03T10:00:00.000Z"
                      },
                      "results": [
                        {
                          "key": "4006381333962",
                          "success": true,
                          "reason": null,
                          "content": {
                            "product_id": "205062515",
                            "name": "Festool Bit PZ1 -25/10",
                            "price_min": 4.9,
                            "price_max": 19.85,
                            "price_avg": 12.34,
                            "offers_count": 5,
                            "offers": [
                              {
                                "position": 1,
                                "price": 4.9,
                                "currency": "EUR",
                                "seller_name": "mima.de",
                                "seller_url": "https://www.mima.de",
                                "shipping": 5.95,
                                "total": 10.85
                              }
                            ]
                          },
                          "served_from": "live",
                          "observed_at": "2026-04-03T10:00:04.000Z",
                          "trust": {
                            "score": 0.92,
                            "components": {
                              "identity": 1,
                              "completeness": 0.89,
                              "price_integrity": 0.95,
                              "offer_contamination": 1,
                              "freshness": 0.75
                            },
                            "flagged_offers": []
                          }
                        }
                      ]
                    }
                  },
                  "wait_timed_out": {
                    "summary": "`wait` elapsed — job still running",
                    "value": {
                      "error": false,
                      "job": {
                        "_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                        "source": "idealo",
                        "country": "de",
                        "key": "gtin",
                        "topic": "search",
                        "values": [
                          "4006381333962"
                        ],
                        "status": "working",
                        "createdAt": "2026-04-03T10:00:00.000Z"
                      },
                      "wait_timed_out": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/job/{id}": {
      "get": {
        "operationId": "getJob",
        "x-seo": {
          "title": "Poll Job Status — kwery Docs",
          "description": "GET /job/{id} — check whether a batch job is finished, with optional wait."
        },
        "summary": "Poll job status",
        "description": "Returns current status and progress counters.\n\n**Status lifecycle:** `new` → `working` → `finished` (or `failed`)\n\nWhen `status` is `finished`, use `GET /job/{id}/download` to retrieve results.\n",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/jobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Job status",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/JobStatusResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                },
                "examples": {
                  "working": {
                    "value": {
                      "error": false,
                      "job": {
                        "_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                        "status": "working",
                        "done": 45,
                        "all": 100
                      }
                    }
                  },
                  "finished": {
                    "value": {
                      "error": false,
                      "job": {
                        "_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                        "status": "finished",
                        "done": 100,
                        "all": 100
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "put": {
        "operationId": "updateJob",
        "x-seo": {
          "title": "Update an Interval Job — kwery Docs",
          "description": "PUT /job/{id} — change the values or schedule of a recurring job."
        },
        "summary": "Update an interval job",
        "description": "Replaces the value list and parameters of an existing **interval job**.\nAll previous results for this job are cleared.\n\nOnly the fields listed in `JobUpdateRequest` can be updated.\nOmitted fields retain their current values.\n",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/jobId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated job or error",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/JobSubmitResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "delete": {
        "operationId": "deleteJob",
        "x-seo": {
          "title": "Delete an Interval Job — kwery Docs",
          "description": "DELETE /job/{id} — stop and remove a recurring job."
        },
        "summary": "Delete an interval job",
        "description": "Permanently deletes a job and all its results. Only interval jobs\ncan be deleted via this endpoint.\n",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/jobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion confirmed or error",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "boolean",
                          "example": false
                        },
                        "message": {
                          "type": "string",
                          "example": "job 64f1c2d3e4b5a6c7d8e9f0a1 removed"
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/job/{id}/download": {
      "get": {
        "operationId": "downloadJob",
        "x-seo": {
          "title": "Download Results — kwery Docs",
          "description": "GET /job/{id}/download — fetch the full results payload for a finished job."
        },
        "summary": "Download results",
        "description": "Returns the complete result set for a finished job.\n\nResults are cached after the first download; subsequent requests are\nserved from cache regardless of result size.\n\nAppend `.csv` to the URL or pass `?format=csv` to receive a CSV file.\n\n> Results are retained for **72 hours** from job creation.\n",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/jobId"
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "Response format. Defaults to `json`."
          }
        ],
        "responses": {
          "200": {
            "description": "Full result set",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobDownloadResponse"
                },
                "example": {
                  "job_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                  "status": "finished",
                  "results": [
                    {
                      "key": "4006381333962",
                      "success": true,
                      "reason": null,
                      "content": {
                        "product_id": "205062515",
                        "name": "Festool Bit PZ1 -25/10",
                        "price_min": 4.9,
                        "price_max": 19.85,
                        "price_avg": 12.34,
                        "offers_count": 5,
                        "offers": [
                          {
                            "position": 1,
                            "price": 4.9,
                            "currency": "EUR",
                            "seller_name": "mima.de",
                            "seller_url": "https://www.mima.de",
                            "shipping": 5.95,
                            "total": 10.85
                          }
                        ]
                      }
                    },
                    {
                      "key": "0000000000000",
                      "success": false,
                      "reason": "not found"
                    }
                  ]
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "CSV with one row per result value."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/stream": {
      "post": {
        "operationId": "submitStreamJob",
        "x-seo": {
          "title": "Submit a Stream Job — kwery Docs",
          "description": "POST /stream — submit up to 100,000 values with webhook delivery as results complete."
        },
        "summary": "Submit a stream job",
        "description": "Submit a large batch for incremental webhook delivery. Results are\npushed to `callback_url` in batches as they complete.\n\n## Webhook payload\n\n```json\n{\n  \"job_id\": \"...\",\n  \"client_ref\": \"...\",\n  \"batch_sequence\": 1,\n  \"is_final\": false,\n  \"results\": [ ... ]\n}\n```\n\n## Signature verification\n\nEach delivery is signed with HMAC-SHA256. Verify using the\n`webhook_secret` returned at submission:\n\n```\nX-Signature: sha256=<hex digest>\n```\n\nCompute `HMAC-SHA256(webhook_secret, raw_request_body)` and compare.\n\n## Fallback\n\nIf webhook delivery fails after all retries, use `POST /stream/{id}/replay-all`\nto re-queue dead-lettered deliveries, or retrieve results directly via\n`GET /stream/{id}/results`.\n\n## Limits\n\n| Parameter | Default | Maximum |\n|-----------|---------|---------|\n| `values` | — | 100 000 |\n| `delivery_batch_size` | 100 | 200 |\n| Job timeout | 1 440 min | 1 440 min |\n",
        "tags": [
          "stream"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StreamSubmitRequest"
              },
              "example": {
                "source": "idealo",
                "country": "de",
                "key": "gtin",
                "values": [
                  "4006381333962",
                  "4719512101148"
                ],
                "callback_url": "https://your-server.example.com/webhooks/prices",
                "client_ref": "batch-2026-04-03",
                "delivery_batch_size": 50
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stream job created",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/StreamSubmitResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                },
                "example": {
                  "error": false,
                  "job_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                  "webhook_secret": "a3f8c2d1e9b4...",
                  "client_ref": "batch-2026-04-03"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/stream/{id}": {
      "get": {
        "operationId": "getStreamJob",
        "x-seo": {
          "title": "Stream Job Status — kwery Docs",
          "description": "GET /stream/{id} — progress counters for a running stream job."
        },
        "summary": "Stream job status",
        "description": "Returns progress counters for a stream job. Poll to track completion\nwithout consuming webhook deliveries.\n",
        "tags": [
          "stream"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/streamId"
          }
        ],
        "responses": {
          "200": {
            "description": "Stream job status",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/StreamStatusResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                },
                "example": {
                  "error": false,
                  "job_id": "64f1c2d3e4b5a6c7d8e9f0a1",
                  "status": "working",
                  "source": "idealo",
                  "country": "de",
                  "values_total": 1000,
                  "values_done": 452,
                  "values_errors": 3,
                  "is_final": false,
                  "created_at": "2026-04-03T10:00:00.000Z",
                  "finished_at": null,
                  "client_ref": "batch-2026-04-03"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/stream/{id}/results": {
      "get": {
        "operationId": "getStreamResults",
        "x-seo": {
          "title": "Poll Stream Results — kwery Docs",
          "description": "GET /stream/{id}/results — polling fallback for stream webhook deliveries."
        },
        "summary": "Poll stream results",
        "description": "Retrieve completed results without relying on webhook delivery.\nUseful as a fallback or when `callback_url` was not provided.\n\n**Offset/limit** — page through results in completion order.\n\n**Batch lookup** — request a specific webhook delivery batch by\nsequence number (useful for reconciling against webhook history).\nWhen `batch` is provided, `offset` and `limit` are ignored.\n",
        "tags": [
          "stream"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/streamId"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Number of results to skip."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            },
            "description": "Maximum results to return."
          },
          {
            "name": "batch",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Return results from a specific delivery batch (1-based).\nOverrides `offset` and `limit`.\n"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated results",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/StreamResultsResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/stream/{id}/replay-all": {
      "post": {
        "operationId": "replayAllDeliveries",
        "x-seo": {
          "title": "Replay Dead-Lettered Deliveries — kwery Docs",
          "description": "POST /stream/{id}/replay-all — re-send every failed webhook delivery of a job."
        },
        "summary": "Replay dead-lettered deliveries",
        "description": "Re-enqueues all `dead_lettered` webhook deliveries for this job.\nUse after fixing a webhook endpoint that was temporarily unreachable.\n",
        "tags": [
          "stream"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/streamId"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Number of deliveries re-enqueued",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "boolean",
                          "example": false
                        },
                        "replayed": {
                          "type": "integer",
                          "description": "Deliveries moved back to `pending`.",
                          "example": 3
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/stream/{id}/deliveries": {
      "get": {
        "operationId": "listDeliveries",
        "x-seo": {
          "title": "Webhook Delivery History — kwery Docs",
          "description": "GET /stream/{id}/deliveries — list webhook deliveries and their status."
        },
        "summary": "List webhook delivery history",
        "description": "Returns the last 200 webhook delivery attempts for this job, newest first.\nUseful for diagnosing delivery failures.\n",
        "tags": [
          "stream"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/streamId"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "dead_lettered"
              ]
            },
            "description": "Filter by delivery status."
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery history",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DeliveriesResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/stream/deliveries/{delivery_id}/replay": {
      "post": {
        "operationId": "replaySingleDelivery",
        "x-seo": {
          "title": "Replay a Delivery — kwery Docs",
          "description": "POST /stream/deliveries/{delivery_id}/replay — re-send one webhook delivery."
        },
        "summary": "Replay a single delivery",
        "description": "Re-enqueues a single `dead_lettered` delivery. Use when only\nspecific batches need to be retried.\n",
        "tags": [
          "stream"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          },
          {
            "BasicAuth": []
          }
        ],
        "parameters": [
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "MongoDB ObjectId of the delivery record."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "boolean",
                          "example": false
                        },
                        "message": {
                          "type": "string",
                          "example": "delivery re-enqueued"
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid credentials.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/HttpError"
            },
            "example": {
              "error": "unauthorized"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Authenticated but not subscribed to this source/country.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/HttpError"
            },
            "example": {
              "error": "forbidden"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT issued by your account. Valid for 24 hours."
      },
      "BasicAuth": {
        "type": "http",
        "scheme": "basic",
        "description": "HTTP Basic authentication with your account username and password."
      },
      "DashboardAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "kwery.co dashboard session token (Supabase). Used by the dashboard UI\nfor account/keys/billing endpoints.\n"
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Your data-API key, format `kwy_live_…`. May also be sent as\n`Authorization: Bearer kwy_live_…`.\n"
      }
    },
    "parameters": {
      "jobId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "MongoDB ObjectId of the job.",
        "example": "64f1c2d3e4b5a6c7d8e9f0a1"
      },
      "streamId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "MongoDB ObjectId of the stream job.",
        "example": "64f1c2d3e4b5a6c7d8e9f0a1"
      }
    },
    "schemas": {
      "JobSubmitRequest": {
        "description": "Discriminated by `source`. Each source has its own valid set of\n`key`, `topic`, and `country` values.\n",
        "oneOf": [
          {
            "$ref": "#/components/schemas/IdealoJobRequest"
          },
          {
            "$ref": "#/components/schemas/AmazonJobRequest"
          },
          {
            "$ref": "#/components/schemas/GoogleJobRequest"
          },
          {
            "$ref": "#/components/schemas/EbayJobRequest"
          }
        ],
        "discriminator": {
          "propertyName": "source",
          "mapping": {
            "idealo": "#/components/schemas/IdealoJobRequest",
            "amazon": "#/components/schemas/AmazonJobRequest",
            "google": "#/components/schemas/GoogleJobRequest",
            "ebay": "#/components/schemas/EbayJobRequest"
          }
        }
      },
      "JobRequestBase": {
        "type": "object",
        "required": [
          "source",
          "country",
          "values"
        ],
        "description": "Fields shared across all job submission requests.",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "idealo",
              "amazon",
              "google",
              "ebay",
              "kaufland",
              "otto",
              "billiger",
              "guenstiger",
              "walmart",
              "lidl",
              "aliexpress",
              "rakuten"
            ]
          },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code (lowercase).",
            "example": "de"
          },
          "key": {
            "type": "string",
            "default": "term",
            "description": "Type of values being submitted. Valid values depend on `source`."
          },
          "topic": {
            "type": "string",
            "default": "search",
            "description": "Processing mode. Valid values depend on `source`."
          },
          "values": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 1000,
            "description": "Values to query. Maximum **1 000** per request. Duplicates are removed.\n\nA comma-separated string is also accepted as a convenience form\n(`\"a,b,c\"` → `[\"a\",\"b\",\"c\"]`), but is **not** compatible with\n`key: product` — product values contain commas internally.\n",
            "example": [
              "4006381333962",
              "4719512101148"
            ]
          },
          "max_pages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 1,
            "description": "Number of result pages to fetch per value. Applicable to Idealo and Amazon.\nIgnored by Google and eBay.\n"
          },
          "max_age": {
            "type": "integer",
            "minimum": 0,
            "maximum": 259200,
            "default": 1200,
            "description": "Maximum acceptable age of a result, **in seconds**.\nDefault: `1200` (20 minutes). Maximum: `259200` (3 days) — the\nretention period for results; larger values are clamped.\n\nWhen a value was already crawled inside this window, the stored\nresult is returned without re-crawling it and the response is not\ncharged. Set to `0` to always force a fresh crawl.\n\nAvailable on eligible accounts; elsewhere every value is always\ncrawled fresh.\n"
          },
          "sort_by": {
            "type": "string",
            "default": "ranking_descending",
            "description": "Sort order for offers within each result."
          },
          "timeout": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440,
            "default": 1440,
            "description": "Job hard timeout in minutes. The job is forcibly finished with\nwhatever partial results exist after this time. Default: 1 440 (24 h).\n"
          },
          "callback_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Webhook URL to receive results when the job finishes.\nFor incremental push delivery, use the Stream endpoint instead.\n"
          },
          "not_found_max_age": {
            "type": "integer",
            "minimum": 1,
            "default": 10,
            "description": "How many days a not-found cache entry is honoured before the product\nis re-queried. Applies to GTIN and PZN lookups (Idealo `gtin`/`pzn`,\nAmazon `gtin`, Google `product`). Set to `1` to force a fresh lookup\non the next job after a single day. Ignored for `term` and `id` keys.\n"
          },
          "include_meta": {
            "type": "boolean",
            "default": false,
            "description": "When `true`, each result carries a `meta` provenance block — the\ncrawl trail (`meta.crawls[]`) with URL, HTTP status, timing and\nobservation timestamp per fetch. See\n[Audit & provenance](guides/audit-and-provenance.md).\n"
          },
          "wait": {
            "oneOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 120
              },
              {
                "type": "boolean"
              }
            ],
            "description": "Hold the request open for up to this many seconds (`true` = the\nmaximum, 120) and, if the job finishes in time, return the results\ninline — the response gains a `results` array identical to what\n`GET /job/{id}/download` serves. If the job is still running when\nthe wait elapses, the normal job object is returned with\n`wait_timed_out: true`; keep waiting with `GET /job/{id}?wait=N`\nor poll `GET /job/{id}` as usual. Accepts exactly one value\n(more returns `\"error\": true`); leave it off for batches.\n"
          }
        }
      },
      "IdealoJobRequest": {
        "description": "Idealo job submission.",
        "allOf": [
          {
            "$ref": "#/components/schemas/JobRequestBase"
          },
          {
            "type": "object",
            "required": [
              "source"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "idealo"
                ]
              },
              "country": {
                "type": "string",
                "description": "Supported Idealo countries.",
                "enum": [
                  "de",
                  "at",
                  "uk",
                  "gb",
                  "fr",
                  "it",
                  "es"
                ],
                "example": "de"
              },
              "key": {
                "type": "string",
                "enum": [
                  "term",
                  "id",
                  "gtin",
                  "pzn"
                ],
                "default": "term",
                "description": "| Value | Values format |\n|-------|---------------|\n| `term` | Free-text search query |\n| `id` | Idealo product ID (numeric string) |\n| `gtin` | EAN / GTIN-13 barcode |\n| `pzn` | Pharmacy product number (DE only) |\n"
              },
              "topic": {
                "type": "string",
                "enum": [
                  "search",
                  "convert",
                  "remove_conversions"
                ],
                "default": "search",
                "description": "| Value | Meaning |\n|-------|---------|\n| `search` | Standard price search — returns offers from all sellers (default) |\n| `convert` | Resolve GTIN to Idealo product ID only; no price data returned |\n| `remove_conversions` | Clear cached GTIN→ID mappings for the submitted GTINs |\n"
              },
              "fetch_seller_names": {
                "type": "boolean",
                "default": false,
                "description": "When `true`, seller detail pages are crawled for marketplace offer\nsellers whose names are not yet in the database. Seller names already\ncached in the database are always applied regardless of this flag.\n\nEnabling this adds one additional request per unresolved seller,\nbilled at the standard rate.\n"
              }
            }
          }
        ]
      },
      "AmazonJobRequest": {
        "description": "Amazon job submission.",
        "allOf": [
          {
            "$ref": "#/components/schemas/JobRequestBase"
          },
          {
            "type": "object",
            "required": [
              "source"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "amazon"
                ]
              },
              "country": {
                "type": "string",
                "description": "Amazon marketplace country code.",
                "enum": [
                  "us",
                  "ca",
                  "mx",
                  "br",
                  "uk",
                  "gb",
                  "de",
                  "at",
                  "ch",
                  "es",
                  "fr",
                  "it",
                  "jp",
                  "in",
                  "ae",
                  "au",
                  "nl",
                  "se",
                  "pl",
                  "be",
                  "sg",
                  "tr"
                ],
                "example": "de"
              },
              "key": {
                "type": "string",
                "enum": [
                  "term",
                  "asin",
                  "gtin"
                ],
                "default": "term",
                "description": "| Value | Values format |\n|-------|---------------|\n| `term` | Free-text search query |\n| `asin` | Amazon ASIN — 10-character alphanumeric identifier |\n| `gtin` | EAN / GTIN-13 — resolved to ASIN internally before fetching |\n"
              },
              "topic": {
                "type": "string",
                "enum": [
                  "search",
                  "search_and_offers",
                  "remove_conversions"
                ],
                "default": "search",
                "description": "| Value | Meaning |\n|-------|---------|\n| `search` | Standard product search (default) |\n| `search_and_offers` | Fetch all seller offers from the Amazon Offer Listing page (AOD) |\n| `remove_conversions` | Clear cached GTIN→ASIN mappings for the submitted GTINs |\n"
              }
            }
          }
        ]
      },
      "GoogleJobRequest": {
        "description": "Google Shopping job submission.\n\n**Key notes:**\n\n- `term` returns a list of matching product cards from a keyword search.\n- `id` fetches a specific product page using a Google Shopping product ID\n  (`catalogid:…` or `productid:…`).\n- `product` fetches a product page using a pipe-separated record\n  (see `GoogleProductValue`). This is the recommended key when you have a\n  product title, retailer deeplink, or size and want to anchor the Google\n  query to a specific listing.\n\n**Values for `key: product` must be an array** — the string shorthand is\nnot compatible because `||` separators may contain characters that conflict\nwith comma-splitting.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/JobRequestBase"
          },
          {
            "type": "object",
            "required": [
              "source"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "google"
                ]
              },
              "country": {
                "type": "string",
                "description": "Supported Google Shopping countries.",
                "enum": [
                  "de",
                  "at",
                  "ch",
                  "fr",
                  "it",
                  "es",
                  "uk",
                  "gb",
                  "us",
                  "au",
                  "ca",
                  "nl",
                  "be",
                  "pl",
                  "se",
                  "no",
                  "dk"
                ],
                "example": "de"
              },
              "key": {
                "type": "string",
                "enum": [
                  "term",
                  "id",
                  "product"
                ],
                "default": "term",
                "description": "| Value | Values format | Result shape |\n|-------|---------------|--------------|\n| `term` | Free-text search | List of product cards (`GoogleTermContent`) |\n| `id` | Google Shopping product ID | Full product page with seller offers (`GoogleProductContent`) |\n| `product` | `GoogleProductValue` — pipe-separated record | Full product page with seller offers (`GoogleProductContent`) |\n"
              },
              "topic": {
                "type": "string",
                "enum": [
                  "search"
                ],
                "default": "search",
                "description": "Only `search` is supported for Google Shopping."
              },
              "values": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/GoogleProductValue"
                },
                "maxItems": 1000,
                "description": "For `key: product`, each element must be a `GoogleProductValue` string.\nFor `key: term` or `key: id`, any plain string is valid — `GoogleProductValue`\nis a `string` type so the schema remains compatible.\n"
              }
            }
          }
        ]
      },
      "EbayJobRequest": {
        "description": "eBay job submission.",
        "allOf": [
          {
            "$ref": "#/components/schemas/JobRequestBase"
          },
          {
            "type": "object",
            "required": [
              "source"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "ebay"
                ]
              },
              "country": {
                "type": "string",
                "description": "Supported eBay countries.",
                "enum": [
                  "de",
                  "at",
                  "fr",
                  "it",
                  "es",
                  "uk",
                  "gb",
                  "us",
                  "au",
                  "ca"
                ],
                "example": "de"
              },
              "key": {
                "type": "string",
                "enum": [
                  "term",
                  "id",
                  "gtin"
                ],
                "default": "term",
                "description": "| Value | Values format |\n|-------|---------------|\n| `term` | Free-text search query |\n| `id` | eBay item ID (numeric string) |\n| `gtin` | EAN / GTIN-13 barcode |\n"
              },
              "topic": {
                "type": "string",
                "enum": [
                  "search",
                  "remove_conversions"
                ],
                "default": "search",
                "description": "| Value | Meaning |\n|-------|---------|\n| `search` | Standard listing search (default) |\n| `remove_conversions` | Clear cached GTIN mappings for the submitted GTINs |\n"
              }
            }
          }
        ]
      },
      "GoogleProductValue": {
        "type": "string",
        "description": "A `||`-separated product record used with `key: product` on Google Shopping.\n\n**Format:**\n\n```\ntitle||brand||gtin||price||deeplink||size\n```\n\n| Position | Field | Effect on Google query |\n|----------|-------|------------------------|\n| 0 | `title` | **Required.** Forms the base of the Google search query. |\n| 1 | `brand` | Informational only — not sent to Google. |\n| 2 | `gtin` | Informational only — not sent to Google. |\n| 3 | `price` | Informational only — not sent to Google. |\n| 4 | `deeplink` | Retailer product URL. The **hostname** is extracted and appended to the query, anchoring results to that seller. |\n| 5 | `size` | Size or variant string — appended to the query. |\n\n**Effective Google query:** `{title} [{retailer_hostname}] [{size}]`\n\nTrailing empty fields and their separators may be omitted.\n\n**Examples:**\n\nTitle only (minimum):\n```\nSony WH-1000XM5\n```\n\nTitle + deeplink to anchor to a specific retailer:\n```\nSony WH-1000XM5||||https://www.amazon.de/dp/B09XS7JWHH\n```\n\nFull record:\n```\nTissot T-Touch Expert Solar||Tissot||7611608277942||850.00||https://www.zeitlounge.de/tissot-t-touch-expert-solar||\n```\n",
        "example": "Tissot T-Touch Expert Solar||Tissot||7611608277942||850.00||https://www.zeitlounge.de/tissot-t-touch-expert-solar||"
      },
      "JobUpdateRequest": {
        "type": "object",
        "description": "Fields that can be updated on an interval job. Omitted fields retain current values.",
        "properties": {
          "values": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 1000
          },
          "max_pages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          },
          "max_age": {
            "type": "integer",
            "minimum": 0
          },
          "sort_by": {
            "type": "string"
          },
          "topic": {
            "type": "string"
          },
          "timeout": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440
          }
        }
      },
      "StreamSubmitRequest": {
        "description": "Stream job submission. Accepts the same source/key/country combinations\nas a batch job, plus stream-specific delivery parameters.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/JobRequestBase"
          },
          {
            "type": "object",
            "required": [
              "callback_url"
            ],
            "properties": {
              "callback_url": {
                "type": "string",
                "format": "uri",
                "description": "Endpoint to receive incremental result batches."
              },
              "client_ref": {
                "type": "string",
                "nullable": true,
                "description": "Opaque reference string echoed in every webhook payload and in\nthe status response. Use to correlate jobs with your own records.\n",
                "example": "batch-2026-04-03"
              },
              "delivery_batch_size": {
                "type": "integer",
                "minimum": 1,
                "maximum": 200,
                "default": 100,
                "description": "Number of results per webhook delivery."
              },
              "include_meta": {
                "type": "boolean",
                "default": false,
                "description": "When `true`, each result includes a `meta` provenance block\ndescribing how the data was gathered — the crawl chain with\nURL, HTTP status, timing, and observation timestamps.\n"
              },
              "fetch_seller_names": {
                "type": "boolean",
                "default": false,
                "description": "Idealo only. When `true`, seller detail pages are crawled for\nmarketplace offer sellers whose names are not yet in the database.\nSeller names already cached in the database are always applied\nregardless of this flag.\n\nEnabling this adds one additional request per unresolved seller,\nbilled at the standard rate.\n"
              },
              "values": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "maxItems": 100000,
                "description": "Up to 100 000 values."
              }
            }
          }
        ]
      },
      "JobSubmitResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean",
            "example": false
          },
          "job": {
            "$ref": "#/components/schemas/Job"
          },
          "results": {
            "type": "array",
            "description": "Present only when the request carried `wait` and the job settled in\ntime. Same items as `GET /job/{id}/download`.\n",
            "items": {
              "$ref": "#/components/schemas/JobResult"
            }
          },
          "wait_timed_out": {
            "type": "boolean",
            "description": "Present only when the request carried `wait` and the job was still\nrunning when the wait elapsed. Keep waiting with `GET /job/{id}?wait=N`\nor poll.\n"
          }
        }
      },
      "JobStatusResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean",
            "example": false
          },
          "job": {
            "type": "object",
            "properties": {
              "_id": {
                "type": "string"
              },
              "status": {
                "$ref": "#/components/schemas/JobStatus"
              },
              "done": {
                "type": "integer",
                "description": "Values with a result so far."
              },
              "all": {
                "type": "integer",
                "description": "Total values in this job."
              }
            }
          }
        }
      },
      "JobDownloadResponse": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JobResult"
            }
          }
        }
      },
      "StreamSubmitResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean",
            "example": false
          },
          "job_id": {
            "type": "string"
          },
          "webhook_secret": {
            "type": "string",
            "description": "32-byte hex secret for verifying webhook signatures.\nStore securely — not retrievable after submission.\n"
          },
          "client_ref": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "StreamStatusResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean",
            "example": false
          },
          "job_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "source": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "values_total": {
            "type": "integer",
            "description": "Total values submitted."
          },
          "values_done": {
            "type": "integer",
            "description": "Values with a result (success or error)."
          },
          "values_errors": {
            "type": "integer",
            "description": "Values that resulted in an error."
          },
          "is_final": {
            "type": "boolean",
            "description": "`true` when all values have been processed."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "client_ref": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "StreamResultsResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean",
            "example": false
          },
          "job_id": {
            "type": "string"
          },
          "values_total": {
            "type": "integer"
          },
          "values_done": {
            "type": "integer"
          },
          "values_errors": {
            "type": "integer"
          },
          "is_final": {
            "type": "boolean"
          },
          "offset": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "count": {
            "type": "integer",
            "description": "Number of results in this page."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StreamResult"
            }
          }
        }
      },
      "DeliveriesResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "boolean",
            "example": false
          },
          "deliveries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Delivery"
            }
          }
        }
      },
      "Job": {
        "type": "object",
        "properties": {
          "_id": {
            "type": "string",
            "description": "MongoDB ObjectId."
          },
          "source": {
            "type": "string",
            "enum": [
              "idealo",
              "amazon",
              "google",
              "ebay",
              "kaufland",
              "otto",
              "billiger",
              "guenstiger",
              "walmart",
              "lidl",
              "aliexpress",
              "rakuten"
            ]
          },
          "country": {
            "type": "string",
            "example": "de"
          },
          "key": {
            "type": "string",
            "example": "gtin"
          },
          "topic": {
            "type": "string",
            "example": "search"
          },
          "values": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "max_pages": {
            "type": "integer"
          },
          "max_age": {
            "type": "integer"
          },
          "timeout": {
            "type": "integer",
            "description": "Timeout in minutes."
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "JobStatus": {
        "type": "string",
        "enum": [
          "new",
          "working",
          "finished",
          "failed"
        ],
        "description": "| Value | Meaning |\n|-------|---------|\n| `new` | Created, queued for processing |\n| `working` | Crawls in progress |\n| `finished` | All results assembled |\n| `failed` | Timed out or unrecoverable error |\n"
      },
      "JobResult": {
        "type": "object",
        "description": "Result for a single input value.\n\n| `success` | `reason` | Meaning |\n|-----------|----------|---------|\n| `true` | `null` | At least one offer found |\n| `true` | `not found` | Product has no listings on this source/country (a completed lookup — billed when freshly crawled, free when re-served from the not-found cache) |\n| `false` | `source currently unavailable` | Transient crawl failure — may succeed on retry |\n| `false` | `timeout` | Crawl did not complete within the job timeout |\n| `false` | `parameter_invalid` | Input is malformed (invalid GTIN checksum, bad ASIN format) |\n",
        "properties": {
          "key": {
            "type": "string",
            "description": "The input value this result corresponds to.",
            "example": "4006381333962"
          },
          "success": {
            "type": "boolean"
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "not found",
              "source currently unavailable",
              "timeout",
              "parameter_invalid",
              null
            ]
          },
          "content": {
            "description": "Source-specific result payload. `null` when `success` is `false`.\n\nThe shape depends on `source` and `key`:\n- Idealo → `IdealoContent`\n- Amazon → `AmazonContent`\n- Google `term` → `GoogleTermContent`\n- Google `id` / `product` → `GoogleProductContent`\n- eBay → `EbayContent`\n",
            "oneOf": [
              {
                "$ref": "#/components/schemas/IdealoContent"
              },
              {
                "$ref": "#/components/schemas/AmazonContent"
              },
              {
                "$ref": "#/components/schemas/GoogleTermContent"
              },
              {
                "$ref": "#/components/schemas/GoogleProductContent"
              },
              {
                "$ref": "#/components/schemas/EbayContent"
              }
            ]
          },
          "served_from": {
            "type": "string",
            "enum": [
              "live",
              "cache"
            ],
            "description": "`live` — at least one fetch was made for this job. `cache` — the\nresult was re-served from a cached observation without a fetch.\n",
            "example": "live"
          },
          "observed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the data was observed (UTC): the last fetch for `live`, the\ncached observation's date for `cache`. `null` when nothing was\nobserved (failed lookup) or the cache date is unknown.\n",
            "example": "2026-09-08T10:00:00.000Z"
          },
          "trust": {
            "$ref": "#/components/schemas/Trust"
          },
          "meta": {
            "$ref": "#/components/schemas/ResultMeta"
          }
        }
      },
      "IdealoContent": {
        "type": "object",
        "description": "Idealo product result (`key: term`, `id`, `gtin`, or `pzn`). Product lookups (`id` / `gtin` / `pzn`) focus on offers; the page-only metadata fields (`rating`, `rating_count`, `available_since`) are populated on keyword `search` results only. `categories` is populated for product results in German markets (`de` / `at`).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Idealo product ID.",
            "example": "205062515"
          },
          "name": {
            "type": "string",
            "example": "Festool Bit PZ1 -25/10"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "category_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Primary category id(s) for the product.",
            "example": [
              "3308"
            ]
          },
          "rating": {
            "type": "number",
            "format": "float",
            "description": "Keyword `search` results only.",
            "example": 4.7
          },
          "rating_count": {
            "type": "integer",
            "description": "Keyword `search` results only.",
            "example": 150
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Category name(s). Product results: German markets (`de`/`at`) only.",
            "example": [
              "Tintenstrahldrucker"
            ]
          },
          "available_since": {
            "type": "string",
            "description": "Date the product appeared on Idealo. Keyword `search` results only.",
            "example": "2023-05-12"
          },
          "price_min": {
            "type": "number",
            "format": "float",
            "example": 4.9
          },
          "price_max": {
            "type": "number",
            "format": "float",
            "example": 19.85
          },
          "price_avg": {
            "type": "number",
            "format": "float",
            "example": 12.34
          },
          "offers_count": {
            "type": "integer",
            "example": 5
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IdealoOffer"
            }
          }
        }
      },
      "IdealoOffer": {
        "type": "object",
        "properties": {
          "position": {
            "type": "integer",
            "example": 1
          },
          "price": {
            "type": "number",
            "format": "float",
            "example": 4.9
          },
          "currency": {
            "type": "string",
            "example": "EUR"
          },
          "shipping": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 5.95
          },
          "total": {
            "type": "number",
            "format": "float",
            "description": "Price + shipping.",
            "example": 10.85
          },
          "seller_name": {
            "type": "string",
            "example": "mima.de"
          },
          "seller_url": {
            "type": "string",
            "format": "uri"
          },
          "seller_type": {
            "type": "string",
            "enum": [
              "standalone-shop",
              "marketplace-shop"
            ]
          },
          "marketplace_name": {
            "type": "string",
            "description": "Populated when `seller_type` is `marketplace-shop`.",
            "example": "Amazon"
          },
          "seller_rating": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "seller_rating_count": {
            "type": "integer",
            "nullable": true
          },
          "voucher": {
            "type": "boolean"
          },
          "free_return": {
            "type": "boolean",
            "nullable": true
          },
          "availability_code": {
            "type": "string",
            "enum": [
              "green",
              "orange",
              "red"
            ],
            "description": "`green` = in stock, `orange` = limited, `red` = out of stock."
          },
          "availability_text": {
            "type": "string",
            "example": "sofort lieferbar, 1 - 3 Werktage"
          }
        }
      },
      "AmazonContent": {
        "type": "object",
        "description": "Amazon product result (`key: term`, `asin`, or `gtin`).",
        "properties": {
          "product_id": {
            "type": "string",
            "description": "The ASIN (unified schema — `product_id` on every source).",
            "example": "B0847ZTV5Q"
          },
          "name": {
            "type": "string"
          },
          "brand_name": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "price_min": {
            "type": "number",
            "format": "float"
          },
          "price_max": {
            "type": "number",
            "format": "float"
          },
          "buybox": {
            "type": "object",
            "description": "Buy-box snapshot — the same object shape on Amazon, Walmart, and Kaufland (unified schema).",
            "properties": {
              "price": {
                "type": "number",
                "format": "float",
                "description": "Buy-box price. On a Prime-exclusive deal this is the regular (non-Prime) price; the Prime price is in `prime_price`.",
                "example": 27.99
              },
              "seller_name": {
                "type": "string",
                "nullable": true,
                "description": "Seller currently winning the buy box.",
                "example": "Amazon.de"
              },
              "seller_id": {
                "type": "string",
                "nullable": true,
                "example": "A3JWKAKR8XB7XF"
              }
            }
          },
          "seller_type": {
            "type": "string",
            "enum": [
              "amazon",
              "fba",
              "fbm"
            ],
            "description": "Fulfilment of the buy-box seller."
          },
          "is_prime": {
            "type": "boolean",
            "description": "True when the buy box carries a Prime-exclusive price."
          },
          "prime_price": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "description": "The Prime-exclusive price when `is_prime` is true, else null."
          },
          "offers_count": {
            "type": "integer"
          },
          "offers": {
            "type": "array",
            "description": "Populated when `topic` is `search_and_offers`.",
            "items": {
              "$ref": "#/components/schemas/AmazonOffer"
            }
          }
        }
      },
      "AmazonOffer": {
        "type": "object",
        "properties": {
          "price": {
            "type": "number",
            "format": "float"
          },
          "currency": {
            "type": "string",
            "example": "EUR"
          },
          "seller_name": {
            "type": "string"
          },
          "seller_id": {
            "type": "string"
          },
          "is_prime": {
            "type": "boolean"
          },
          "condition": {
            "type": "string",
            "example": "New"
          },
          "shipping": {
            "type": "number",
            "format": "float",
            "nullable": true
          }
        }
      },
      "GoogleTermContent": {
        "type": "object",
        "description": "Google Shopping result for `key: term`. Contains a list of product cards\nmatching the search query. Each card is a distinct product — not a single\nseller listing.\n",
        "properties": {
          "offers_count": {
            "type": "integer",
            "description": "Number of product cards returned."
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GoogleProductCard"
            }
          }
        }
      },
      "GoogleProductCard": {
        "type": "object",
        "description": "A product card from a `term` search. Represents a product, not a seller.\n`gid` can be used as a `key: id` value in a follow-up job to get full\nseller offers for that product.\n",
        "properties": {
          "name": {
            "type": "string",
            "description": "Product name."
          },
          "gid": {
            "type": "string",
            "description": "Google Shopping product ID in `catalogid:…` or `productid:…` format.\nUse as `values` with `key: id` to fetch the full product page.\n",
            "example": "catalogid:7294553093490218809"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL of the Google Shopping product page."
          },
          "price": {
            "type": "number",
            "format": "float",
            "description": "Lowest listed price for this product."
          },
          "currency": {
            "type": "string",
            "example": "EUR"
          },
          "shipping": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "condition": {
            "type": "string",
            "nullable": true
          },
          "seller": {
            "type": "string",
            "description": "Name of the seller shown on the card.",
            "nullable": true
          },
          "seller_url": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "rating": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "rating_count": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GoogleProductContent": {
        "type": "object",
        "description": "Google Shopping result for `key: id` or `key: product`. Contains\nfull product data with all seller offers from the product page.\n",
        "properties": {
          "id": {
            "type": "string",
            "description": "Google Shopping product ID.",
            "example": "7294553093490218809"
          },
          "name": {
            "type": "string",
            "example": "Tissot T-Touch Expert Solar"
          },
          "brand_name": {
            "type": "string",
            "nullable": true,
            "example": "Tissot"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical Google Shopping product URL."
          },
          "rating": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "rating_count": {
            "type": "integer",
            "nullable": true
          },
          "price_min": {
            "type": "number",
            "format": "float"
          },
          "price_max": {
            "type": "number",
            "format": "float"
          },
          "price_avg": {
            "type": "number",
            "format": "float"
          },
          "offers_count": {
            "type": "integer"
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GoogleSellerOffer"
            }
          }
        }
      },
      "GoogleSellerOffer": {
        "type": "object",
        "description": "A seller listing from a Google Shopping product page.",
        "properties": {
          "seller_name": {
            "type": "string"
          },
          "seller_url": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "price": {
            "type": "number",
            "format": "float"
          },
          "currency": {
            "type": "string",
            "example": "EUR"
          },
          "shipping": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "total": {
            "type": "number",
            "format": "float",
            "description": "Price + shipping.",
            "nullable": true
          },
          "condition": {
            "type": "string",
            "nullable": true
          },
          "position": {
            "type": "integer"
          },
          "seller_rating": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "seller_rating_count": {
            "type": "integer",
            "nullable": true
          }
        }
      },
      "EbayContent": {
        "type": "object",
        "description": "eBay search result (`key: term`, `id`, or `gtin`).",
        "properties": {
          "offers_count": {
            "type": "integer"
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EbayOffer"
            }
          }
        }
      },
      "EbayOffer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "eBay item ID."
          },
          "name": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "float"
          },
          "currency": {
            "type": "string",
            "example": "EUR"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "shipping": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "condition": {
            "type": "string",
            "example": "Neu | Gewerblich"
          },
          "position": {
            "type": "integer"
          },
          "seller_name": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "StreamResult": {
        "type": "object",
        "description": "A single result item from the stream results endpoint.",
        "properties": {
          "_id": {
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/JobResult"
          },
          "source": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "index": {
            "type": "integer",
            "description": "0-based position of this value in the original submission."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Delivery": {
        "type": "object",
        "description": "Webhook delivery record.",
        "properties": {
          "_id": {
            "type": "string"
          },
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "delivered",
              "dead_lettered"
            ]
          },
          "batch_sequence": {
            "type": "integer",
            "description": "1-based sequence number of this delivery batch."
          },
          "result_count": {
            "type": "integer",
            "description": "Number of results in this delivery."
          },
          "http_status": {
            "type": "integer",
            "nullable": true,
            "description": "HTTP status returned by the webhook endpoint."
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Error message if delivery failed."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "deliveredAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "AccountJob": {
        "type": "object",
        "description": "One row of the org's request history (`GET /v1/account/jobs`).",
        "properties": {
          "id": {
            "type": "string",
            "example": "68b9c2f1a4d3e5b6c7d8e9f0"
          },
          "source": {
            "type": "string",
            "example": "idealo"
          },
          "country": {
            "type": "string",
            "example": "de"
          },
          "key": {
            "type": "string",
            "example": "gtin"
          },
          "topic": {
            "type": "string",
            "example": "search"
          },
          "status": {
            "type": "string",
            "enum": [
              "new",
              "working",
              "finished",
              "failed"
            ]
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "description": "Failure / force-finish reason when set (e.g. `timeout_partial`)."
          },
          "values_count": {
            "type": "integer",
            "description": "Values submitted with the job.",
            "example": 250
          },
          "results_count": {
            "type": "integer",
            "nullable": true
          },
          "errors_count": {
            "type": "integer",
            "nullable": true,
            "description": "Failed lookups (timeout, blocked, parse error …) — never charged."
          },
          "resolved_count": {
            "type": "integer",
            "nullable": true,
            "description": "Lookups that returned a product (`results_count − errors_count − not_found_count`).",
            "example": 240
          },
          "not_found_count": {
            "type": "integer",
            "nullable": true,
            "description": "Lookups answered \"not found\"; free when served from cache, billed when freshly crawled.",
            "example": 8
          },
          "credits_charged": {
            "type": "integer",
            "nullable": true,
            "description": "Credits debited for this job — `0` for a failed job and for jobs whose\nlookups were all free (cache hits / errors); `null` while a job is\nstill running or once neither the debit nor the results are available.\n",
            "example": 250
          },
          "is_stream": {
            "type": "boolean"
          },
          "client_ref": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "duration_ms": {
            "type": "integer",
            "nullable": true,
            "description": "Submission → finished, in milliseconds."
          }
        }
      },
      "AccountDelivery": {
        "type": "object",
        "description": "One webhook delivery (batch) of a job (`GET /v1/account/jobs/{id}/deliveries`).",
        "properties": {
          "id": {
            "type": "string",
            "example": "68be1a0c9f2d4e7b8a1c2d3e"
          },
          "attempt": {
            "type": "integer",
            "description": "Attempts made so far on this batch (1 = first try; max 5).",
            "example": 3
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "delivered",
              "failed",
              "dead_lettered"
            ]
          },
          "http_status": {
            "type": "integer",
            "nullable": true,
            "description": "HTTP status the callback URL answered on the last attempt; `null` on a network error.",
            "example": 503
          },
          "error": {
            "type": "string",
            "nullable": true,
            "example": "non-2xx: 503"
          },
          "batch_sequence": {
            "type": "integer",
            "nullable": true,
            "description": "1-based batch number within the job — gaps mean a batch is missing on the receiver.",
            "example": 4
          },
          "result_count": {
            "type": "integer",
            "nullable": true,
            "description": "Results embedded in this batch.",
            "example": 100
          },
          "first_attempted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_attempted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "next_attempt_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Scheduled retry while `status` is `failed`; `null` otherwise."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Validation and business-logic errors return **HTTP 200** with `error: true`.\nCheck this field before consuming the response.\n",
        "properties": {
          "error": {
            "type": "boolean",
            "example": true
          },
          "message": {
            "type": "string",
            "example": "country not supported by source"
          }
        }
      },
      "HttpError": {
        "type": "object",
        "description": "Infrastructure-level error (4xx / 5xx).",
        "properties": {
          "error": {
            "type": "string",
            "example": "user not found"
          },
          "message": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Trust": {
        "type": "object",
        "description": "Confidence score attached to every result. `score` is a weighted average\n(0–1) of the five `components`. See the\n[Trust](guides/trust.md) guide for interpretation.\n",
        "properties": {
          "score": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1,
            "description": "Overall confidence, 0 (do not trust) to 1 (fully trusted).",
            "example": 0.81
          },
          "components": {
            "type": "object",
            "description": "The five sub-scores that make up `score`, each 0–1.",
            "properties": {
              "identity": {
                "type": "number",
                "format": "float",
                "description": "Is this the requested product? (weight 0.25)",
                "example": 1
              },
              "completeness": {
                "type": "number",
                "format": "float",
                "description": "Are the expected fields populated? (weight 0.20)",
                "example": 0.85
              },
              "price_integrity": {
                "type": "number",
                "format": "float",
                "description": "Pricing consistent and outlier-free? (weight 0.25)",
                "example": 0.7
              },
              "offer_contamination": {
                "type": "number",
                "format": "float",
                "description": "Fraction of offers that are clean. (weight 0.15)",
                "example": 0.9
              },
              "freshness": {
                "type": "number",
                "format": "float",
                "description": "Recency of the data; decays with age. (weight 0.15)",
                "example": 0.55
              }
            }
          },
          "flagged_offers": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Indices into `content.offers` of offers flagged as price outliers.",
            "example": [
              2,
              5
            ]
          }
        }
      },
      "ResultMeta": {
        "type": "object",
        "description": "Provenance metadata. Present only when the job was submitted with\n`include_meta: true`.\n",
        "properties": {
          "crawls": {
            "type": "array",
            "description": "One entry per fetch that contributed to this result.",
            "items": {
              "$ref": "#/components/schemas/CrawlProvenance"
            }
          },
          "partial": {
            "type": "boolean",
            "description": "Google only. `true` when the marketplace reports more sellers than\nwere gathered in this snapshot. Absent for other sources.\n"
          }
        }
      },
      "CrawlProvenance": {
        "type": "object",
        "description": "Provenance for a single fetch behind a result.",
        "properties": {
          "crawl_id": {
            "type": "string",
            "description": "Stable ID for this individual fetch — quote it to support.",
            "example": "9f1c2d3e4b5a6c7d8e9f0a1b"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The exact URL that was fetched."
          },
          "http_status": {
            "type": "integer",
            "example": 200
          },
          "duration_ms": {
            "type": "integer",
            "description": "Fetch round-trip time, in milliseconds.",
            "example": 2341
          },
          "observed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the data was observed (UTC)."
          },
          "geo": {
            "type": "string",
            "description": "Country the request was made from.",
            "example": "de"
          },
          "job_type": {
            "type": "string",
            "description": "Internal crawl step that produced this fetch.",
            "example": "idealo.search"
          }
        }
      },
      "ChangeEventType": {
        "type": "string",
        "description": "Type of a change-event webhook. See the\n[Change events](guides/change-events.md) guide.\n",
        "enum": [
          "product.changed",
          "price.delta",
          "buybox.change",
          "stock.update",
          "product.resolved",
          "product.unavailable"
        ]
      },
      "FieldChange": {
        "type": "object",
        "description": "A single changed field, as an old → new pair.",
        "properties": {
          "old": {
            "description": "Previous value."
          },
          "new": {
            "description": "Current value."
          }
        }
      },
      "ChangeEventPayload": {
        "type": "object",
        "description": "Body of a change-event webhook `POST`. Delivered to your `callback_url`\nwith the same HMAC signing and retry behaviour as stream deliveries (see\n[Webhooks](guides/webhooks.md)). With `delta_only: true` on the\nsubscription, only `product` and `changes` are sent.\n",
        "properties": {
          "event": {
            "$ref": "#/components/schemas/ChangeEventType"
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time"
          },
          "product": {
            "type": "object",
            "description": "Identity of the product that changed.",
            "properties": {
              "source": {
                "type": "string",
                "example": "idealo"
              },
              "country": {
                "type": "string",
                "example": "de"
              },
              "key": {
                "type": "string",
                "example": "gtin"
              },
              "value": {
                "type": "string",
                "example": "4006381333962"
              },
              "name": {
                "type": "string",
                "example": "Fissler Original-Profi Collection"
              }
            }
          },
          "changes": {
            "type": "object",
            "description": "The fields that changed, each an old → new pair. Keys depend on the\nevent (e.g. `price`, `offer_count`, `buybox_seller`, `buybox_price`).\nAbsent for `product.resolved` and `product.unavailable`, which report a\ntransition rather than a field moving.\n",
            "additionalProperties": {
              "$ref": "#/components/schemas/FieldChange"
            }
          }
        }
      }
    }
  }
}