openapi: 3.1.0
info:
  title: TempoLife Food Nutrition API
  version: 1.0.0
  description: Read-only food lookup and grounded answers. Values are per 100 g reference figures, not measurements of individual meals. Inspect row-level provenance and licensing.
  contact:
    name: TempoLife
    url: https://tempolife.app/
    email: info@tempolife.app
  license:
    name: Mixed — inspect each row
    url: https://tempolife.app/food-api.php#licensing
servers:
  - url: https://tempolife.app
paths:
  /food-api.php:
    get:
      operationId: lookupOrSearchFood
      summary: Look up one food or search canonical foods
      parameters:
        - {name: food, in: query, schema: {type: string}, description: Canonical food slug}
        - {name: search, in: query, schema: {type: string}, description: Name or slug search; returns at most 20 matches}
        - {name: lang, in: query, schema: {type: string, enum: [et, fi, ru]}, description: Optional localized name}
      responses:
        '200':
          description: Food row or search results with row-level provenance
          content:
            application/json:
              schema: {type: object, additionalProperties: true}
        '404': {description: Food not found}
        '503': {description: Dataset unavailable}
  /api/answer:
    get:
      operationId: answerFoodQuestion
      summary: Answer a food nutrition question from TempoLife data
      description: Supports calorie and macro questions plus two-food comparisons. Limited to 60 requests per IP per hour.
      parameters:
        - name: q
          in: query
          required: true
          schema: {type: string, minLength: 1, maxLength: 160}
          examples:
            calories: {value: calories in banana}
            compare: {value: apple vs banana protein}
      responses:
        '200':
          description: Grounded answer with canonical source URL
          headers:
            X-RateLimit-Limit: {schema: {type: integer}}
            X-RateLimit-Remaining: {schema: {type: integer}}
          content:
            application/json:
              schema:
                type: object
                required: [query, answer, source_url, basis, license]
                properties:
                  query: {type: string}
                  answer: {type: string}
                  value: {type: number}
                  unit: {type: string}
                  source_url: {type: string, format: uri}
                  source_urls: {type: array, items: {type: string, format: uri}}
                  basis: {type: string}
                  license: {type: object}
        '400': {description: Missing or invalid query}
        '404': {description: No grounded answer found}
        '429': {description: Rate limit reached}
