{
  "openapi": "3.1.0",
  "info": {
    "title": "2aFinder Public API",
    "version": "1.0.0",
    "description": "REST público do catálogo 2aFinder. Mesma fonte do MCP server e da UI. Filtros são contratos invioláveis (rule #2). Cupom só aparece quando validado nas últimas 6h (rule #3).",
    "contact": {
      "name": "2aFinder",
      "url": "https://2afinder.com"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://2afinder.com"
    }
  ],
  "security": [],
  "paths": {
    "/api/v1/search": {
      "get": {
        "operationId": "searchProducts",
        "summary": "Busca textual + filtros estruturados",
        "description": "Busca canônicos por texto + filtros estruturados (category, brand, model_family, ram_gb, storage_gb, release_year). Quando q é um GTIN/EAN/UPC completo de 8, 12, 13 ou 14 dígitos, o match é literal em variantes e nunca cai em candidatos semânticos. Resposta paginada (limit/offset).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 2
            },
            "description": "Texto livre (>= 2 chars) ou GTIN/EAN/UPC exato de 8, 12, 13 ou 14 dígitos."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model_family",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ram_gb",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Inteiro ou lista CSV (ex.: \"16\" ou \"8,16,32\")"
          },
          {
            "name": "storage_gb",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Inteiro ou lista CSV"
          },
          {
            "name": "release_year",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Inteiro ou lista CSV"
          },
          {
            "name": "ranking",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "bm25",
                "vec",
                "hybrid"
              ],
              "default": "hybrid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "ld+json"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              },
              "application/ld+json": {
                "schema": {
                  "type": "object",
                  "description": "schema.org/ItemList"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (100 req/min/IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{slug}": {
      "get": {
        "operationId": "getProduct",
        "summary": "Detalhe canônico por slug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "ld+json"
              ],
              "default": "json"
            }
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "full",
                "compact"
              ],
              "default": "full"
            },
            "description": "compact reduz tokens e mantém identidade, specs, evidência e top-5 ofertas."
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "price-history"
              ]
            },
            "description": "CSV de extras a incluir."
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 90,
              "default": 30
            },
            "description": "Janela do price-history quando include=price-history."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDetail"
                }
              },
              "application/ld+json": {
                "schema": {
                  "type": "object",
                  "description": "schema.org/Product denso"
                }
              }
            }
          },
          "308": {
            "description": "Slug substituído; Location aponta diretamente ao canônico final",
            "headers": {
              "Location": {
                "description": "URL canônica final, preservando parâmetros de consulta",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/changes": {
      "get": {
        "operationId": "listProductChanges",
        "summary": "Delta de produtos canônicos atualizados",
        "description": "Lista compacta de produtos alterados desde um timestamp ISO 8601. Use apiUrl para buscar a ficha compacta com proveniência auditada.",
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Janela de mudanças",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductChanges"
                }
              }
            }
          },
          "400": {
            "description": "Timestamp inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/compare": {
      "get": {
        "operationId": "compareProducts",
        "summary": "Compara de 2 a 4 produtos canônicos",
        "description": "Ficha lado a lado com cobertura de evidência. Só publica vencedor geral ou custo-benefício quando os gates compartilhados com HTML, Markdown e MCP são satisfeitos.",
        "parameters": [
          {
            "name": "slugs",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "De 2 a 4 slugs distintos separados por vírgula."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Comparison"
                }
              }
            }
          },
          "400": {
            "description": "Lista de slugs inválida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Um ou mais produtos não encontrados",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "code"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        }
      },
      "ProductSummary": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "brand",
          "category"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "brandSlug": {
            "type": "string"
          },
          "line": {
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "type": "string"
          },
          "releaseYear": {
            "type": "integer"
          },
          "mpn": {
            "type": [
              "string",
              "null"
            ]
          },
          "gtin": {
            "type": [
              "string",
              "null"
            ]
          },
          "specs": {
            "type": "object",
            "additionalProperties": true
          },
          "variantCount": {
            "type": "integer"
          },
          "variantSummaries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "imageUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "fromPriceCents": {
            "type": [
              "integer",
              "null"
            ]
          },
          "totalOfferCount": {
            "type": "integer"
          },
          "apiUrl": {
            "type": "string"
          },
          "mdUrl": {
            "type": "string"
          },
          "webUrl": {
            "type": "string"
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "apiVersion",
          "items",
          "total",
          "page",
          "limit",
          "offset"
        ],
        "properties": {
          "apiVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "query": {
            "type": "object",
            "additionalProperties": true
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        }
      },
      "Offer": {
        "type": "object",
        "properties": {
          "offerId": {
            "type": "string"
          },
          "variantSlug": {
            "type": "string"
          },
          "sellerName": {
            "type": "string"
          },
          "platformSlug": {
            "type": "string"
          },
          "platformName": {
            "type": "string"
          },
          "priceCents": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "enum": [
              "BRL"
            ]
          },
          "shippingCents": {
            "type": [
              "integer",
              "null"
            ]
          },
          "freeShipping": {
            "type": "boolean"
          },
          "lastCheckedAt": {
            "type": "string",
            "format": "date-time"
          },
          "condition": {
            "type": "string",
            "enum": [
              "new",
              "refurbished",
              "used",
              "unknown"
            ]
          },
          "installments": {
            "type": [
              "object",
              "null"
            ]
          },
          "trust": {
            "type": "object",
            "properties": {
              "platform": {
                "type": "number"
              },
              "seller": {
                "type": "number"
              },
              "product": {
                "type": "number"
              }
            }
          }
        }
      },
      "ProductDetail": {
        "type": "object",
        "required": [
          "apiVersion",
          "slug",
          "name",
          "brand",
          "category"
        ],
        "properties": {
          "apiVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "view": {
            "type": "string",
            "enum": [
              "full",
              "compact"
            ]
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "brandSlug": {
            "type": "string"
          },
          "line": {
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "type": "string"
          },
          "generation": {
            "type": [
              "string",
              "null"
            ]
          },
          "releaseYear": {
            "type": "integer"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "imageUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "mpn": {
            "type": [
              "string",
              "null"
            ]
          },
          "gtin": {
            "type": [
              "string",
              "null"
            ]
          },
          "specs": {
            "type": "object",
            "additionalProperties": true
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldEvidence"
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Offer"
            }
          },
          "fromPriceCents": {
            "type": [
              "integer",
              "null"
            ]
          },
          "totalOfferCount": {
            "type": "integer"
          },
          "manufacturerProductUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "apiUrl": {
            "type": "string"
          },
          "mdUrl": {
            "type": "string"
          },
          "webUrl": {
            "type": "string"
          },
          "priceHistory": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "offerId": {
                  "type": "string"
                },
                "priceCents": {
                  "type": "integer"
                },
                "takenAt": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "FieldEvidence": {
        "type": "object",
        "required": [
          "fieldPath",
          "value",
          "sourceUrl",
          "authority",
          "confidence",
          "observedAt",
          "auditedAt"
        ],
        "properties": {
          "fieldPath": {
            "type": "string"
          },
          "value": {},
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri"
          },
          "sourceType": {
            "type": "string"
          },
          "authority": {
            "type": "string"
          },
          "sourceLocator": {
            "type": "object",
            "additionalProperties": true
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "auditedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProductChanges": {
        "type": "object",
        "required": [
          "apiVersion",
          "since",
          "generatedAt",
          "count",
          "truncated",
          "changes"
        ],
        "properties": {
          "apiVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "since": {
            "type": "string",
            "format": "date-time"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "count": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean"
          },
          "changes": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "Comparison": {
        "type": "object",
        "required": [
          "apiVersion",
          "generatedAt",
          "products",
          "rows",
          "score",
          "value",
          "links"
        ],
        "properties": {
          "apiVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "products": {
            "type": "array",
            "minItems": 2,
            "maxItems": 4,
            "items": {
              "type": "object"
            }
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "score": {
            "type": "object",
            "description": "Elegibilidade, vencedor e motivo explícito de bloqueio."
          },
          "value": {
            "type": "object",
            "description": "Elegibilidade do custo-benefício e motivo de bloqueio."
          },
          "links": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      }
    }
  }
}