{
  "openapi": "3.1.0",
  "info": {
    "title": "GAMEPRICEAPI",
    "version": "1.0.0",
    "description": "Commercial, authenticated access to a synchronized physical-product catalog, available metadata, cached images and processed reference prices delivered by GAMEPRICEAPI through a licensed partner integration. EBAY identifies the upstream marketplace reported by the partner, not a direct eBay API connection, official affiliation, raw completed-sale records or individual verification of every price against eBay. Prices use USD integer cents. All /v1/ routes require a valid customer Bearer key and an active entitlement. Internal-only use and display to users of apps/sites, even free apps, require different contracted scopes. Raw-data redistribution, third-party bulk exports and API resale require a separate written agreement. Pricing is by consultation; onboarding, activation and changes are manual, with no automatic overage billing. Published base quotas do not change existing customer agreements. Keep keys on the backend and cache only as agreed, preserving required credits. Coverage and metadata completeness depend on configured catalogs and synchronization. Reads never query upstream sources. No SLA, real-time, full worldwide-coverage, unlimited-use, CSV-export, historical-price or raw-sale endpoint is promised.",
    "contact": {
      "name": "GAMEPRICEAPI — solicitar acesso",
      "url": "https://meuretro.com.br/?support=1"
    }
  },
  "x-commercial-access": {
    "onboarding": "manual_after_written_agreement",
    "pricing": "contact_sales",
    "automatic_overage_billing": false,
    "existing_customers": "Existing contracted limits and permissions are unchanged by this documentation.",
    "base_modalities": [
      {
        "id": "internal",
        "name": "Uso interno",
        "scope": "Private analysis, inventory and dashboards restricted to the customer's own organization; not display to customers or other third parties.",
        "requests_per_utc_calendar_month": 10000,
        "requests_per_utc_minute": 60
      },
      {
        "id": "app",
        "name": "Apps e sites",
        "scope": "Display to users through the contracted app/site backend, including free apps and storefront reference valuations. Projects, caching and media permissions require agreement; raw-data redistribution and API resale are not automatically included.",
        "requests_per_utc_calendar_month": 100000,
        "requests_per_utc_minute": 60
      },
      {
        "id": "partnership",
        "name": "Parcerias de dados",
        "scope": "Custom data distribution or resale only after technical review and separate written authorization; no default unlimited access or elevated rate guarantee.",
        "limits": "custom_after_review"
      }
    ],
    "contract_specifics": [
      "approved projects and use scope",
      "catalog coverage",
      "media permissions and attribution",
      "cache retention and post-termination data handling",
      "account quotas and access expiry"
    ]
  },
  "x-usage-accounting": {
    "quota_unit": "One authenticated and entitled /v1/ request admitted by the account limiter, including later parameter errors, not-found responses and server errors.",
    "shared_scope": "Customer account across all of its keys, not per user or page view.",
    "windows": "Fixed UTC minute and UTC calendar month; not a rolling 30-day billing period.",
    "batch": "One admitted batch request costs one request unit for 1 to 100 distinct IDs; each list page and image download is separate.",
    "usage_endpoint": "Counts itself and is unavailable after quota exhaustion; returned_items is a separate counter, not the quota unit.",
    "not_counted": "Requests rejected before quota admission, including failed authentication, inactive entitlement and exhausted account limits.",
    "ingress_protection": "Additional public-entry protection averages 120 requests/minute per IP with a limited burst allowance. Shared-IP callers and bursts may be rejected before account quotas. Keep calls paced and respect 429; higher account quotas do not bypass ingress protection.",
    "retry": "Honor Retry-After when present; edge 429 may be non-JSON and omit this header. Use bounded exponential backoff with jitter when absent."
  },
  "servers": [
    {
      "url": "https://api.meuretro.com.br",
      "description": "Public API origin"
    }
  ],
  "externalDocs": {
    "description": "Documentação em português",
    "url": "https://api.meuretro.com.br/docs"
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Products",
      "description": "Authenticated catalog and prices."
    },
    {
      "name": "Images",
      "description": "Authenticated cached binary assets."
    },
    {
      "name": "Coverage",
      "description": "Authenticated synchronized coverage."
    },
    {
      "name": "Account",
      "description": "Own-account usage and limits."
    },
    {
      "name": "Health",
      "description": "Public process availability only."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "operationId": "getHealth",
        "summary": "Basic process availability",
        "description": "Public; does not expose customer data or catalog metrics and does not guarantee price freshness or provider health.",
        "security": [],
        "responses": {
          "200": {
            "description": "Service process is available.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "version"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "ok"
                    },
                    "version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "listProducts",
        "summary": "Search and page through products",
        "description": "Optional filters combine. Unknown or repeated query parameters are rejected. external_source and external_id must be sent together. All admitted requests consume one quota unit, including invalid parameters. updated_after filters fetched_at or metadata_observed_at, not a transactional change feed; paginate with stable filters, overlap sync windows and reconcile periodically.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Title search.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "platform_id",
            "in": "query",
            "required": false,
            "description": "Provider platform ID.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000
            }
          },
          {
            "name": "country_id",
            "in": "query",
            "required": false,
            "description": "Provider country/region ID, not an ISO code.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000
            }
          },
          {
            "name": "category_id",
            "in": "query",
            "required": false,
            "description": "Provider category ID.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "barcode",
            "in": "query",
            "required": false,
            "description": "Checksum-valid GTIN/ISBN barcode. Leading zeros are significant. Invalid barcodes return 400.",
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "external_source",
            "in": "query",
            "required": false,
            "description": "Identifier namespace, e.g. gamepriceapi, metacritic or howlongtobeat. Requires external_id. Identifiers are not marketplace listing or transaction IDs unless explicitly identified as such.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{0,39}$"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Provider-specific ID. Requires external_source.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "The next_after returned by the preceding page. Preserve other filters.",
            "schema": {
              "$ref": "#/components/schemas/ProductIdInput"
            }
          },
          {
            "name": "updated_after",
            "in": "query",
            "required": false,
            "description": "UTC ISO timestamp with milliseconds. Includes records where fetched_at or metadata_observed_at is later than this value; not a transactional cursor.",
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum products returned.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Products matching the search, plus next-page cursor.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/products/{id}": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "getProduct",
        "summary": "Get one product",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ProductIdInput"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product metadata and per-condition reference prices.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/products/{id}/image": {
      "get": {
        "tags": [
          "Images"
        ],
        "operationId": "getProductImage",
        "summary": "Download a cached image",
        "description": "Requires the same Bearer key and active entitlement as JSON routes. Follow metadata.images[].url. No upstream request is made when an image is absent. One admitted image request consumes one quota unit; a successful download records one returned item.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ProductIdInput"
            }
          },
          {
            "name": "variant",
            "in": "query",
            "required": false,
            "description": "Only variants present in metadata.images are available.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{0,39}$",
              "default": "cover"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cached image bytes. Content-Type identifies the file format.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/catalogs": {
      "get": {
        "tags": [
          "Coverage"
        ],
        "operationId": "listCatalogs",
        "summary": "Inspect configured catalog coverage",
        "description": "Authenticated coverage, not a public directory. next_run_at is scheduling metadata, not an SLA. No query parameters.",
        "responses": {
          "200": {
            "description": "Configured catalogs and current synchronized counts.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Catalog"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/platforms": {
      "get": {
        "tags": [
          "Coverage"
        ],
        "operationId": "listPlatforms",
        "summary": "List platforms in the synchronized catalog",
        "description": "Authenticated platform metadata. No query parameters. Names may be null.",
        "responses": {
          "200": {
            "description": "Available platform IDs, names and product counts.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Platform"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getUsage",
        "summary": "Inspect own-account usage",
        "description": "Current UTC calendar-month counters shared by all keys for the customer account, including this admitted request. Subject to the same access and quota checks as other /v1/ routes and unavailable when quota is exhausted. Read remaining-quota response headers before reaching the limit. Counters are not invoices or user/view counts.",
        "responses": {
          "200": {
            "description": "Authenticated client usage, commercial-access metadata and limits.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/prices/batch": {
      "post": {
        "tags": [
          "Products"
        ],
        "operationId": "batchPrices",
        "summary": "Get product records by IDs",
        "description": "Returns complete product records, including metadata and prices. 1–100 distinct IDs; no query parameters. Both batch routes have identical behavior. One admitted request consumes one quota unit. Returned items are counted separately. JSON body must be at most 32 KiB and uncompressed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matched records and requested IDs not found.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    },
    "/v1/products/batch": {
      "post": {
        "tags": [
          "Products"
        ],
        "operationId": "batchProducts",
        "summary": "Get product records by IDs (alias)",
        "description": "Returns complete product records, including metadata and prices. 1–100 distinct IDs; no query parameters. Both batch routes have identical behavior. One admitted request consumes one quota unit. Returned items are counted separately. JSON body must be at most 32 KiB and uncompressed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matched records and requested IDs not found.",
            "headers": {
              "X-Request-Id": {
                "description": "Request trace identifier.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Client requests per minute.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining in the minute after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-RateLimit-Reset": {
                "description": "End of minute window; Unix timestamp in seconds.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "X-MonthlyQuota-Remaining": {
                "description": "Requests remaining in the UTC calendar month after admission.",
                "schema": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Customer secret sent only in Authorization: Bearer. Use server-to-server. Never place in query strings, public JavaScript, browser storage, repositories or logs. Valid authentication also requires an active commercial entitlement."
      }
    },
    "responses": {
      "Error400": {
        "description": "Invalid parameters, JSON, product IDs, or credentials placed in URL. Correct the request before retrying.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error401": {
        "description": "Missing, invalid or revoked API key; invalid_api_key.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "const": "Bearer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error403": {
        "description": "Commercial entitlement inactive or expired; subscription_inactive or subscription_expired.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error404": {
        "description": "Product, image or route unavailable; product_not_found, image_not_available or not_found.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error405": {
        "description": "HTTP method is not allowed; method_not_allowed.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error413": {
        "description": "JSON body exceeds 32 KiB; body_too_large.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error414": {
        "description": "URL exceeds the accepted length; url_too_long.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error415": {
        "description": "application/json required or body encoding unsupported; json_required or encoding_not_supported.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error429": {
        "description": "Rate or monthly quota exceeded, or ingress protection triggered. Application JSON codes: rate_limit_exceeded, monthly_quota_exceeded, ingress_rate_limit. Account-quota rejections provide Retry-After; honor it when present. The public ingress layer may instead return non-JSON HTML and omit Retry-After and X-Request-Id. Check Content-Type; if no retry delay is supplied, use bounded exponential backoff with jitter. Rejected requests are not admitted account-quota units.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          "Retry-After": {
            "description": "Seconds until retry may be attempted when supplied; monthly quota exhaustion can require a long wait. May be absent on ingress-layer rejection.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          },
          "text/html": {
            "schema": {
              "type": "string",
              "description": "Possible public-ingress rejection; not the application JSON error envelope."
            }
          }
        }
      },
      "Error503": {
        "description": "Temporary service_unavailable. Retry with bounded exponential backoff and jitter.",
        "headers": {
          "X-Request-Id": {
            "description": "Request trace identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "ProductId": {
        "type": "string",
        "pattern": "^gameprice:[1-9][0-9]{0,14}$",
        "description": "Canonical public product ID. Treat the complete value as opaque; do not calculate IDs or infer equivalence with source IDs. Source identifiers are returned separately in metadata.identifiers.",
        "examples": ["gameprice:12345"]
      },
      "ProductIdInput": {
        "type": "string",
        "pattern": "^gameprice:[1-9][0-9]{0,14}$",
        "description": "Use the complete canonical gameprice: ID returned by the API in product/image requests, batches and pagination inputs. Responses use gameprice:, including not_found entries and image URLs.",
        "examples": ["gameprice:12345"]
      },
      "Price": {
        "type": "object",
        "required": [
          "amount_cents",
          "observed_at",
          "stale"
        ],
        "properties": {
          "amount_cents": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "USD integer cents; 12345 means USD 123.45. Missing prices are null, never a fabricated zero."
          },
          "observed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "stale": {
            "type": "boolean",
            "description": "True when no observation exists or the configured freshness window is exceeded."
          }
        }
      },
      "NamedReference": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ProviderReference": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Identifiers": {
        "type": "object",
        "description": "Public identifiers as strings. Keys can include gamepriceapi, parent_gamepriceapi, metacritic and howlongtobeat. Treat the GAMEPRICEAPI identifier as opaque; no equivalence across catalogs or with eBay listing/transaction IDs is implied.",
        "properties": {
          "gamepriceapi": {
            "type": "string"
          },
          "metacritic": {
            "type": "string"
          },
          "howlongtobeat": {
            "type": "string"
          },
          "parent_gamepriceapi": {
            "type": "string"
          }
        },
        "additionalProperties": {
          "type": "string"
        }
      },
      "Barcode": {
        "type": "object",
        "required": [
          "value",
          "format",
          "normalized",
          "checksum_valid"
        ],
        "properties": {
          "value": {
            "type": "string",
            "description": "Original barcode string. Preserve leading zeros."
          },
          "format": {
            "type": "string",
            "description": "Source-normalized format, such as UPC-A, EAN-13, GTIN-8, GTIN-14, ISBN-10, ISBN-13, or unknown."
          },
          "normalized": {
            "type": [
              "string",
              "null"
            ],
            "description": "Validated, normalized 14-digit GTIN; null when unavailable or invalid."
          },
          "checksum_valid": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "Image": {
        "type": "object",
        "required": [
          "type",
          "url",
          "mime_type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{0,39}$",
            "description": "Cached variant, such as cover. Only request variants actually returned for this product."
          },
          "url": {
            "type": "string",
            "format": "uri-reference",
            "pattern": "^/v1/products/gameprice:[1-9][0-9]{0,14}/image\\?variant=[a-z][a-z0-9_]{0,39}$",
            "description": "Protected relative API URL. Resolve against the API origin and send Authorization: Bearer; not an upstream image URL."
          },
          "attribution": {
            "type": ["string", "null"],
            "description": "Source attribution when supplied. Preserve attribution when displaying the asset."
          },
          "mime_type": {
            "type": "string",
            "enum": [
              "image/jpeg",
              "image/png",
              "image/webp"
            ]
          },
          "width": {
            "type": "integer",
            "minimum": 1
          },
          "height": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "Metadata": {
        "type": "object",
        "required": [
          "images"
        ],
        "properties": {
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "release_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "developers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NamedReference"
            }
          },
          "publishers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NamedReference"
            }
          },
          "genres": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NamedReference"
            }
          },
          "players": {
            "type": [
              "number",
              "string",
              "null"
            ]
          },
          "platform": {
            "$ref": "#/components/schemas/ProviderReference"
          },
          "country": {
            "$ref": "#/components/schemas/ProviderReference"
          },
          "edition": {
            "type": [
              "string",
              "null"
            ]
          },
          "identifiers": {
            "$ref": "#/components/schemas/Identifiers"
          },
          "barcodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Barcode"
            }
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Image"
            }
          },
          "links": {
            "type": "array",
            "description": "Available product or search links. These links do not establish completed sales or evidence for an individual price reference.",
            "items": {
              "type": "object",
              "required": [
                "source",
                "url"
              ],
              "properties": {
                "source": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "attributes": {
            "type": "object",
            "description": "Allowlisted public product fields from the source. May include co_op, rating_id, item_state, metascore, provider_updated_at, titles and alternative_titles. No private collection or contributor data.",
            "additionalProperties": true
          }
        }
      },
      "Provenance": {
        "type": "object",
        "description": "Distinguishes the partner-reported upstream marketplace from the service delivering processed references. No direct marketplace API access, official affiliation, raw sold transactions or independent per-price marketplace verification is implied.",
        "required": [
          "source",
          "delivered_by",
          "source_role",
          "acquisition_method",
          "source_basis",
          "source_url",
          "provider_as_of",
          "fetched_at",
          "match_type"
        ],
        "properties": {
          "source": {
            "const": "EBAY",
            "type": "string",
            "description": "Upstream marketplace reported by the licensed partner for this integration, not a verified source transaction for each reference."
          },
          "delivered_by": {
            "const": "GAMEPRICEAPI",
            "type": "string"
          },
          "source_role": {
            "const": "upstream_marketplace",
            "type": "string",
            "description": "The source label describes the upstream marketplace, not the direct API supplier."
          },
          "acquisition_method": {
            "const": "licensed_partner_reference",
            "type": "string",
            "description": "Processed reference received through a licensed partner integration, not a direct eBay API request."
          },
          "source_basis": {
            "const": "partner_reported",
            "type": "string",
            "description": "The upstream-marketplace attribution is reported by the partner; it is not independently verified for each product or price."
          },
          "source_url": {
            "type": "null",
            "description": "No individual marketplace listing or completed-sale evidence URL is supplied. Product/search links are separate from price evidence."
          },
          "provider_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "fetched_at": {
            "type": "string",
            "format": "date-time"
          },
          "match_type": {
            "const": "exact_provider_identity",
            "type": "string",
            "description": "Exact product identity within the licensed integration, not a verified match to a marketplace transaction."
          }
        }
      },
      "Product": {
        "type": "object",
        "required": [
          "id",
          "title",
          "identifiers",
          "platform_id",
          "country_id",
          "release_type",
          "category_id",
          "product_type",
          "currency",
          "metadata",
          "metadata_observed_at",
          "prices",
          "provenance"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/ProductId"
          },
          "title": {
            "type": "string"
          },
          "identifiers": {
            "$ref": "#/components/schemas/Identifiers"
          },
          "platform_id": {
            "type": "integer",
            "minimum": 1
          },
          "country_id": {
            "type": "integer",
            "minimum": 1
          },
          "release_type": {
            "type": "integer",
            "minimum": 0
          },
          "category_id": {
            "type": "integer",
            "minimum": 0
          },
          "product_type": {
            "type": "string",
            "enum": [
              "game",
              "console",
              "controller",
              "guide",
              "accessory",
              "product"
            ],
            "description": "Mapping: category 0=game, 1=console, 2=controller, 4=guide, 5=accessory; otherwise product. Availability depends on configured catalogs."
          },
          "currency": {
            "type": "string",
            "const": "USD"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "metadata_observed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "prices": {
            "type": "object",
            "required": [
              "loose",
              "cib",
              "new"
            ],
            "properties": {
              "loose": {
                "$ref": "#/components/schemas/Price"
              },
              "cib": {
                "$ref": "#/components/schemas/Price"
              },
              "new": {
                "$ref": "#/components/schemas/Price"
              }
            }
          },
          "provenance": {
            "$ref": "#/components/schemas/Provenance"
          }
        }
      },
      "ProductList": {
        "type": "object",
        "required": [
          "data",
          "next_after"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          },
          "next_after": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^gameprice:[1-9][0-9]{0,14}$",
            "description": "Canonical gameprice: cursor. Pass unchanged to after with the same search filters. Null means no further page at the time of this response."
          }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/ProductIdInput"
            }
          }
        },
        "additionalProperties": false
      },
      "BatchResponse": {
        "type": "object",
        "required": [
          "data",
          "not_found"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          },
          "not_found": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductId"
            }
          }
        }
      },
      "Catalog": {
        "type": "object",
        "required": [
          "id",
          "platform_id",
          "country_id",
          "release_type",
          "products",
          "priced_products",
          "with_barcodes",
          "with_images",
          "last_success_at",
          "next_run_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "platform_id": {
            "type": "integer"
          },
          "country_id": {
            "type": "integer"
          },
          "release_type": {
            "type": "integer"
          },
          "products": {
            "type": "integer",
            "minimum": 0
          },
          "priced_products": {
            "type": "integer",
            "minimum": 0
          },
          "with_barcodes": {
            "type": "integer",
            "minimum": 0
          },
          "with_images": {
            "type": "integer",
            "minimum": 0
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "next_run_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Platform": {
        "type": "object",
        "required": [
          "id",
          "name",
          "products"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "products": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "Usage": {
        "type": "object",
        "description": "Own-account counters shared across keys. Request units, not returned-item totals or app users, determine quota consumption.",
        "required": [
          "client_id",
          "month",
          "requests",
          "returned_items",
          "access",
          "limits"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "format": "uuid"
          },
          "month": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}$"
          },
          "requests": {
            "type": "integer",
            "minimum": 0
          },
          "returned_items": {
            "type": "integer",
            "minimum": 0
          },
          "access": {
            "type": "object",
            "required": [
              "status",
              "plan",
              "expires_at"
            ],
            "properties": {
              "status": {
                "type": "string"
              },
              "plan": {
                "type": ["string", "null"]
              },
              "expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "limits": {
            "type": "object",
            "required": [
              "per_minute",
              "per_month"
            ],
            "properties": {
              "per_minute": {
                "type": "integer",
                "minimum": 1
              },
              "per_month": {
                "type": "integer",
                "minimum": 1
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "request_id"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable error code."
              },
              "request_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        }
      }
    }
  }
}
