openapi: 3.1.0 info: title: RecallMatch Product Check API version: 1.0.0 description: Checks supplied product identity against monitored official recall sources. A no-match result does not certify safety. servers: - url: https://api.example.com security: - bearerAuth: [] paths: /healthz: get: security: [] responses: '200': {description: Process is healthy} /readyz: get: security: [] responses: '200': {description: Database is reachable} '503': {$ref: '#/components/responses/ServiceUnavailable'} /v1/products/check: post: operationId: checkProduct requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/Product'} responses: '200': description: Match result content: {application/json: {schema: {$ref: '#/components/schemas/MatchResponse'}}} '400': {$ref: '#/components/responses/BadRequest'} '401': {$ref: '#/components/responses/Unauthorized'} '403': {$ref: '#/components/responses/Forbidden'} '422': {$ref: '#/components/responses/ValidationFailed'} '429': {$ref: '#/components/responses/RateLimited'} '503': {$ref: '#/components/responses/ServiceUnavailable'} /v1/products/check-batch: post: operationId: checkProductsBatch requestBody: required: true content: application/json: schema: type: object required: [products] properties: products: {type: array, minItems: 1, maxItems: 100, items: {$ref: '#/components/schemas/Product'}} responses: '200': description: Ordered match results content: application/json: schema: type: object required: [results] properties: results: type: array items: type: object required: [result] properties: sku: {type: string} result: {$ref: '#/components/schemas/MatchResponse'} '400': {$ref: '#/components/responses/BadRequest'} '401': {$ref: '#/components/responses/Unauthorized'} '403': {$ref: '#/components/responses/Forbidden'} '422': {$ref: '#/components/responses/ValidationFailed'} '429': {$ref: '#/components/responses/RateLimited'} '503': {$ref: '#/components/responses/ServiceUnavailable'} components: securitySchemes: bearerAuth: {type: http, scheme: bearer, bearerFormat: API key} schemas: Product: type: object required: [title] additionalProperties: false properties: title: {type: string, minLength: 1} brand: {type: string} model: {type: string} gtin: {type: string} mpn: {type: string} category: {type: string} sku: {type: string} manufacturer: {type: string} description: {type: string} country: {type: string} MatchResponse: type: object required: [schema_version, product, status, highest_confidence, matches, sources_checked, checked_at, disclaimer] properties: schema_version: {type: integer, const: 1} product: {$ref: '#/components/schemas/Product'} status: {type: string} highest_confidence: {type: number, minimum: 0, maximum: 1} matches: {type: array, items: {type: object}} sources_checked: {type: array, items: {type: string}} checked_at: {type: string, format: date-time} disclaimer: {type: string} Error: type: object required: [error] properties: error: type: object required: [code, message, request_id] properties: code: {type: string} message: {type: string} request_id: {type: string} details: {} responses: BadRequest: {description: Malformed JSON, content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}} Unauthorized: {description: Missing or invalid API key, content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}} Forbidden: {description: Disabled tenant or unsupported plan, content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}} ValidationFailed: {description: Invalid product input, content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}} RateLimited: {description: Usage limit exceeded, headers: {Retry-After: {schema: {type: integer}}}, content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}} ServiceUnavailable: {description: Dependency unavailable, content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}}