openapi: 3.0.3
info:
  title: ScaleRecipe API
  description: |
    Free public API for scaling recipe ingredient quantities with smart
    culinary fractions and unit promotion. Same engine that powers the
    on-site scaler at https://www.scale-recipe.com/scaler.

    No authentication. Open CORS. Up to 200 ingredient lines per request.
  version: "1.0.0"
  contact:
    name: ScaleRecipe Support
    email: support@scale-recipe.com
    url: https://www.scale-recipe.com/contact
  license:
    name: Free for any use (commercial or non-commercial)
    url: https://www.scale-recipe.com/terms
  termsOfService: https://www.scale-recipe.com/terms
  x-logo:
    url: https://www.scale-recipe.com/icon.png
    altText: ScaleRecipe logo
servers:
  - url: https://www.scale-recipe.com
    description: Production
externalDocs:
  description: Full developer documentation with examples
  url: https://www.scale-recipe.com/developers
tags:
  - name: Scaling
    description: Recipe ingredient scaling endpoints
paths:
  /api/scale:
    post:
      summary: Scale recipe ingredient quantities
      description: |
        Takes a list of recipe ingredient lines and a from/to ratio (or an
        explicit ratio), returns the same lines with quantities scaled and
        units smart-promoted (3 tsp → 1 tbsp, 16 tbsp → 1 cup, 1000 g → 1 kg).

        Lines without a parseable quantity (e.g. `to taste`) pass through
        unchanged.

        Provide either `ratio`, or both `from` and `to`. If you provide both
        forms, `ratio` takes precedence.
      operationId: scaleRecipe
      tags: [Scaling]
      requestBody:
        required: true
        description: Ingredient lines plus the scaling factor.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ScaleRequest"
            examples:
              fromTo:
                summary: Scale from 4 to 6 servings
                value:
                  ingredients:
                    - "1 1/2 cups all-purpose flour"
                    - "2 tsp salt"
                    - "3 large eggs"
                  from: 4
                  to: 6
              ratio:
                summary: Halve a recipe explicitly
                value:
                  ingredients:
                    - "1 cup butter"
                    - "2 cups sugar"
                  ratio: 0.5
              localizedUnits:
                summary: Scale 1.5× and translate units to Spanish
                value:
                  ingredients:
                    - "2 tablespoons olive oil"
                    - "1 cup white rice"
                  ratio: 1.5
                  lang: "es"
      responses:
        "200":
          description: Successful scaling
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScaleSuccess"
              example:
                ok: true
                ratio: 1.5
                scaled:
                  - "2 1/4 cups all-purpose flour"
                  - "1 tbsp salt"
                  - "4 1/2 large eggs"
        "400":
          description: |
            Invalid request: malformed JSON, missing required fields,
            type mismatch, ratio out of range, too many ingredients, etc.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScaleError"
              examples:
                badArray:
                  summary: ingredients isn't an array
                  value:
                    ok: false
                    error: "`ingredients` must be an array of strings."
                badRatio:
                  summary: ratio out of range
                  value:
                    ok: false
                    error: "Ratio must be between 0.01 and 100."
        "500":
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScaleError"
components:
  schemas:
    ScaleRequest:
      type: object
      required: [ingredients]
      properties:
        ingredients:
          type: array
          minItems: 1
          maxItems: 200
          items:
            type: string
            maxLength: 500
          description: |
            Recipe ingredient lines (one per array entry). Quantities can be
            integers (`2`), decimals (`1.5`), slashed fractions (`1/2`),
            mixed numbers (`1 1/2`), Unicode fractions (`½`, `1½`), or
            absent (lines pass through unchanged).
          example:
            - "1 1/2 cups all-purpose flour"
            - "2 tsp salt"
            - "3 large eggs"
        from:
          type: number
          exclusiveMinimum: 0
          description: Original recipe servings. Provide with `to` to compute the ratio automatically.
          example: 4
        to:
          type: number
          exclusiveMinimum: 0
          description: Target recipe servings.
          example: 6
        ratio:
          type: number
          minimum: 0.01
          maximum: 100
          description: Explicit scaling factor (alternative to `from` + `to`). Takes precedence if both are provided.
          example: 1.5
        lang:
          type: string
          maxLength: 16
          description: |
            ISO language code for unit-name translation (e.g. `es`, `fr`,
            `de`). Defaults to English. Invalid codes silently fall back
            to English.
          example: "es"
    ScaleSuccess:
      type: object
      required: [ok, ratio, scaled]
      properties:
        ok:
          type: boolean
          enum: [true]
          description: Always `true` on success.
        ratio:
          type: number
          description: The scaling factor that was applied.
          example: 1.5
        scaled:
          type: array
          items:
            type: string
          description: Scaled ingredient lines, in the same order as the request.
          example:
            - "2 1/4 cups all-purpose flour"
            - "1 tbsp salt"
            - "4 1/2 large eggs"
    ScaleError:
      type: object
      required: [ok, error]
      properties:
        ok:
          type: boolean
          enum: [false]
          description: Always `false` on error.
        error:
          type: string
          description: Human-readable error message.
          example: "`ingredients` must be an array of strings."
