openapi: 3.0.3

info:
  title: Meal Planning API
  description: |-
    The *Meal Planning API* provides dietary planning based on a user-supplied daily meal structure and nutritional
    constraints.

    A meal plan is the assignment of a number of dishes, according to a fixed daily pattern, over a given period of
    time.  The daily pattern structures one or more *slots* (dishes) into a hierarchy of *sections*.  An example meal
    plan daily pattern might be:

    1. Breakfast *(1 dish)*
    2. Lunch *(section)*
       1. Starter *(1 dish)*
       2. Main course *(1 dish)*
       3. Dessert *(1 dish)*
    3. Dinner *(section)*
       1. Main course *(1 dish)*
       2. Dessert *(1 dish)*

    The daily pattern is defined by the caller and is supplied to the meal planner with each `select` call.

    Any section within the pattern may include acceptance criteria and nutritional constraints; a section's selection
    criteria apply *separately* to each slot in that section's sub-tree; a section's nutritional constraints apply to
    the *total* combined nutritional value of assigned slots in the section's sub-tree.

    **Selection**

    A `select` call will attempt to generate a meal plan for a specified period from a given specification (daily
    pattern plus criteria and constraints.)  Upon successful generation, the meal plan will contain unique assignments
    of recipes for each slot in the requested period.

    Selection usually generates the same results from the same inputs (though this is not guaranteed.)  To force
    varying the output, include all recipes assigned so far as exclusions at the top-level section of the plan.

    **Recipe details**

    The details of the assigned recipes can be retrieved through the *Recipe Search API* in one or more
    [search-by-URI](https://developer.edamam.com/edamam-docs-recipe-api#operations-tag-Lookup_recipes_by_URI) calls
    (search-by-URI access is always provided by meal planner subscriptions.)  See the *Recipe Search API*
    documentation for further details.

    **Shopping list**

    A `shopping-list` call may be issued on assigned recipes to obtain total shopping quantities for the products
    involved.  Each recipe may be scaled individually for the shopping list by indicating the planned consumption as a
    number of servings; in the absence of such indication, consumption (and therefore preparation) of the complete
    output of the recipe will be assumed.

  version: 1.0 beta

servers:
  - url: https://api.edamam.com

tags:
  - name: planner
    description: Meal planning
  - name: shopping list
    description: Shopping list

paths:
  /api/meal-planner/v1/{app_id}/select:
    post:
      tags:
        - planner
      summary: Create dietary plan according to supplied specification
      parameters:
        - name: app_id
          in: path
          required: true
          schema:
            type: string
        - name: Edamam-Account-User
          in: header
          schema:
            type: string
          description: ID of the account user. Should be used *only* if the account is configured for active user tracking.
        - name: beta
          in: query
          schema:
            type: boolean
          description: Turn on support for beta features
        - name: type
          in: query
          required: true
          explode: true
          schema:
            type: array
            uniqueItems: true
            items:
              type: string
              enum:
                - public
                - edamam-generic
          description: Types of recipes to choose from.
      requestBody:
        description: Meal plan descriptor
        content:
          application/json:
            schema:
              properties:
                size:
                  description: Plan length (days)
                  type: integer
                  default: 1
                plan:
                  $ref: '#/components/schemas/Section'
            examples:
              7 Days Plan with Allergens:
                $ref: '#/components/examples/7 Day Plan with Allergens'
              Vegan plan:
                $ref: '#/components/examples/Vegan plan'
      responses:
        200:
          description: Plan generated completely or partially
          content:
            application/json:
              schema:
                properties:
                  status:
                    description: >
                      Plan generation status:
                        * `OK` - Plan generated completely
                        * `INCOMPLETE` - Plan generated partially.  Unique assignments for one or more days of the
                          requested period could not be completed from available recipe data
                        * `TIME_OUT` - Plan generated partially.  Unique assignments for one or more days of the
                          requested period could not be completed within the allowed execution time
                    type: string
                    enum:
                      - OK
                      - INCOMPLETE
                      - TIME_OUT
                  _links:
                    description: Links to resources related to the generated meal plan
                    type: object
                    properties:
                      next:
                        allOf:
                          - description: >
                              (BETA only) Link for extending the current meal plan with one more complete period, with new
                              recipe entries.  The link is only provided for convenience; it will *not* be available for
                              incomplete assignments (i.e. where `status` = `"INCOMPLETE"`,) or if the included extension
                              token has grown too large.  It is highly recommended that the caller maintain their own chain
                              of extension requests, by keeping track of recipe entries assigned so far in the chain, and
                              adding them for exclusion on subsequent calls (see `exclude` in
                              [`Section`](#/components/schemas/Section).)
                          - $ref: '#/components/schemas/LinkEntry'
                  selection:
                    description: >
                      Daily assignments according to the specified plan.  Each element of the array represents
                      complete assignments for a single day, each daily assignment corresponding with the structure of
                      the meals specified in the plan descriptor.
                    type: array
                    items:
                      $ref: '#/components/schemas/Selection'
              examples:
                Vegan plan assignment:
                  $ref: '#/components/examples/Vegan plan assignment'
        400:
          description: Malformed or invalid plan specification
      security:
        - basic:
            - app_id

  /api/recipes/v2/by-uri:
    get:
      tags:
        - planner
      summary: Lookup recipes by URI
      description: The meal planner returns recipe URIs as part of its response. Use this endpoint to retrieve the
        recipes. For more information see the relevant documentation in the
        [Recipe Search API](https://developer.edamam.com/edamam-docs-recipe-api#operations-tag-Lookup_recipes_by_URI).
      responses:
        XXX:
          description: See the relevant documentation in the
            [Recipe Search API](https://developer.edamam.com/edamam-docs-recipe-api#operations-tag-Lookup_recipes_by_URI).

  /api/meal-planner/v1/{app_id}/shopping-list:
    post:
      tags:
        - shopping list
      summary: Create shopping list from total meal quantities
      parameters:
        - name: app_id
          in: path
          required: true
          schema:
            type: string
        - name: Edamam-Account-User
          in: header
          schema:
            type: string
          description: ID of the account user. Should be used *only* if the account is configured for active user tracking.
        - name: beta
          in: query
          schema:
            type: boolean
          description: Turn on support for beta features
        - name: type
          in: query
          required: true
          explode: true
          schema:
            type: array
            uniqueItems: true
            items:
              type: string
              enum:
                - public
                - edamam-generic
          description: Types of recipes to choose from.
        - name: shopping-cart
          in: query
          required: false
          schema:
            type: boolean
          description: (BETA only) Generate a shopping cart page for the the foods aggregated in the shopping list
      requestBody:
        description: Meal quantities
        content:
          application/json:
            schema:
              properties:
                entries:
                  description: Recipe execution plan, as product quantity required for each given recipe
                  type: array
                  items:
                    $ref: '#/components/schemas/RecipeEntry'
            examples:
              Recipe execution plan, by servings:
                $ref: '#/components/examples/Recipe execution plan, by servings'
              Recipe execution plan, by total quantity:
                $ref: '#/components/examples/Recipe execution plan, by total quantity'
      responses:
        200:
          description: Shopping list generated successfully
          content:
            application/json:
              schema:
                properties:
                  entries:
                    description: Aggregated ingredient quantities.
                    type: array
                    items:
                      $ref: '#/components/schemas/ShoppingEntry'
                  _links:
                    description: Links to resources related to the generated shopping list
                    type: object
                    properties:
                      shopping-cart:
                        allOf:
                          - description: (BETA only) Shopping cart link
                          - $ref: '#/components/schemas/LinkEntry'
              examples:
                Shopping list:
                  $ref: '#/components/examples/Shopping list'
        400:
          description: Malformed or invalid request

      security:
        - basic:
            - app_id

components:

  schemas:

    Section:
      description: |-
        Plan section; may contain sub-sections.

        Leaf sections (i.e. those that do not contain sub-sections) represent individual dishes in the daily plan.
        Upon generation of the plan, complete or partial, each leaf section will be assigned a single recipe that will
        be unique throughout the complete period of the generated plan.
      type: object
      properties:
        accept:
          allOf:
            - description: Acceptance criteria for all entries in the sub-tree
            - $ref: '#/components/schemas/Predicate'
        fit:
          description: >
            Nutritional budget (constraints for total nutrient content values in the sub-tree.)
            Keys must be valid **NutrientTag**-s
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Range'
        exclude:
          description: Recipes to exclude from this section's sub-tree, listed by URI
          type: array
          items:
            type: string
        sections:
          description: |-
            Sub-sections.

            This section's acceptance criteria and nutritional budget will apply to its complete sub-tree of
            sub-sections, potentially in conjunction will any other criteria that may apply, specifically from
            containing parent sections.
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Section'

    Selection:
      type: object
      properties:
        assigned:
          description: URI of the recipe assigned for this section (leaf sections only.)
          type: string
        _links:
          description: Links to resources related to the assigned recipe
          type: object
          properties:
            self:
              allOf:
                - description: Link to the assigned recipe's details in the Recipe Search API
                - $ref: '#/components/schemas/LinkEntry'
        sections:
          description: Selection tree for sub-sections, according to the structure specified by the plan descriptor.
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Selection'

    LinkEntry:
      type: object
      required: [href]
      properties:
        title:
          description: Human-readable link title
          type: string
        href:
          description: Target URL
          type: string

    Range:
      type: object
      properties:
        min:
          type: number
        max:
          type: number

    Predicate:
      oneOf:
        - description: Select entries matching all of a given list of predicates
          type: object
          required: [all]
          properties:
            all:
              type: array
              items:
                $ref: '#/components/schemas/Predicate'
        - description: Select entries matching at least one out of a given list of predicates
          type: object
          required: [any]
          properties:
            any:
              type: array
              items:
                $ref: '#/components/schemas/Predicate'
        - description: Select entries that do *not* match a given predicate
          type: object
          required: [not]
          properties:
            not:
              $ref: '#/components/schemas/Predicate'
        - description: >
            Select entries that satisfy a given target requirement, subject to a pre-condition.  Entries that do *not*
            satisfy the precondition will match this rule vacuously.
          type: object
          required: [when]
          properties:
            when:
              type: object
              required: [condition, require]
              properties:
                condition:
                  allOf:
                    - description: Pre-condition for checking the target requirement
                    - $ref: '#/components/schemas/Predicate'
                require:
                  allOf:
                    - description: Target requirement to check if the pre-condition is satisfied
                    - $ref: '#/components/schemas/Predicate'
        - description: Select entries falling under one or more of the supplied health labels
          type: object
          required: [health]
          properties:
            health:
              type: array
              items:
                $ref: '#/components/schemas/HealthLabel'
        - description: Select entries falling under one or more of the supplied diet labels
          type: object
          required: [diet]
          properties:
            diet:
              type: array
              items:
                $ref: '#/components/schemas/DietLabel'
        - description: Select entries falling under one or more of the supplied caution labels
          type: object
          required: [caution]
          properties:
            caution:
              type: array
              items:
                $ref: '#/components/schemas/CautionLabel'
        - description: Select entries falling under one or more of the supplied cuisine types
          type: object
          required: [cuisine]
          properties:
            cuisine:
              type: array
              items:
                type: string
        - description: Select entries falling under one or more of the supplied neal types
          type: object
          required: [meal]
          properties:
            meal:
              type: array
              items:
                type: string
        - description: Select entries falling under one or more of the supplied dish types
          type: object
          required: [dish]
          properties:
            dish:
              type: array
              items:
                type: string
        - description: Select entries falling under one or more of the supplied dish types *only* (exclude entries under any other dish types)
          type: object
          required: [only-dish]
          properties:
            only-dish:
              type: array
              items:
                type: string
        - description: Select entries from one of the listed sources
          type: object
          required: [source]
          properties:
            source:
              type: array
              items:
                type: string
        - description: Select entries from one of the listed sources (by site name)
          type: object
          required: [source-name]
          properties:
            source-name:
              type: array
              items:
                type: string

    HealthLabel:
      type: string
      enum: [ "fat-free", "low-fat-abs", "sugar-conscious", "low-sugar", "low-potassium", "kidney-friendly",
        "keto-friendly", "plant-based", "vegan", "vegetarian", "pescatarian", "paleo", "specific-carbs",
        "Mediterranean", "DASH", "dairy-free", "gluten-free", "wheat-free", "egg-free", "milk-free", "peanut-free",
        "tree-nut-free", "soy-free", "fish-free", "shellfish-free", "pork-free", "red-meat-free", "crustacean-free",
        "celery-free", "mustard-free", "sesame-free", "lupine-free", "mollusk-free", "alcohol-free", "no-oil-added",
        "no-sugar-added", "sulfite-free", "fodmap-free", "kosher", "alcohol-cocktail", "immuno-supportive" ]

    DietLabel:
      type: string
      enum: [ "balanced", "high-protein", "high-fiber", "low-fat", "low-carb", "low-sodium" ]

    CautionLabel:
      type: string
      enum: [ "gluten", "wheat", "eggs", "milk", "peanuts", "tree-nuts", "soy", "fish", "shellfish", "sulfites", "fodmap" ]

    NutrientTag:
      description: See *Nutrient Guide*
      type: string

    RecipeEntry:
      type: object
      required: [quantity, recipe]
      properties:
        quantity:
          description: >
            Total quantity of the specified recipe's product that will be prepared, in given units of measure (see
            `measure`)
          type: number
        measure:
          description: >
            Unit of measure (URI) for the total quantity; if omitted, the unit is the total quantity of a single
            execution of the given recipe
          type: string
          enum:
            - "http://www.edamam.com/ontologies/edamam.owl#Measure_serving"
        recipe:
          description: Recipe URI
          type: string

    ShoppingEntry:
      type: object
      properties:
        foodItem:
          description: (DEPRECATED; use Food ID) Food URI
          type: string
        foodId:
          description: Food ID
          type: string
        food:
          description: Food label
          type: string
        quantities:
          description: >
            Total quantity required of the specified food item for fulfillment of the requested quantities for the
            complete recipe execution plan.  One sub-total is given per each specific shopping measure type.
          type: array
          items:
            type: object
            required: [quantity, measure]
            properties:
              quantity:
                description: Required quantity of the specified units of measure
                type: number
              measure:
                description: Unit of measure (URI)
                type: string
              qualifiers:
                description: Qualifiers applicable to the shopping item, e.g. "large", "small", etc.
                type: array
                items:
                  type: string

  examples:

    7 Day Plan with Allergens:
      description: 7 Day Allergens descriptor
      value:
        size: 7
        plan:
          accept:
            all:
              - health:
                  - SOY_FREE
                  - FISH_FREE
                  - MEDITERRANEAN
          fit:
            ENERC_KCAL:
              min: 1000
              max: 2000
            SUGAR.added:
              max: 20
          exclude:
            - http://www.edamam.com/ontologies/edamam.owl#recipe_x
            - http://www.edamam.com/ontologies/edamam.owl#recipe_y
            - http://www.edamam.com/ontologies/edamam.owl#recipe_z
          sections:
            Breakfast:
              accept:
                all:
                  - dish:
                      - drinks
                      - egg
                      - biscuits and cookies
                      - bread
                      - pancake
                      - cereals
                  - meal:
                      - breakfast
              fit:
                ENERC_KCAL:
                  min: 100
                  max: 600
            Lunch:
              accept:
                all:
                  - dish:
                    - main course
                    - pasta
                    - egg
                    - salad
                    - soup
                    - sandwiches
                    - pizza
                    - seafood
                  - meal:
                    - lunch/dinner
              fit:
                ENERC_KCAL:
                  min: 300
                  max: 900
            Dinner:
              accept:
                all:
                  - dish:
                    - seafood
                    - egg
                    - salad
                    - pizza
                    - pasta
                    - main course
                  - meal:
                    - lunch/dinner
              fit:
                ENERC_KCAL:
                  min: 200
                  max: 900

    Vegan plan:
      description: Vegan meal plan descriptor
      value:
        size: 2
        plan:
          accept:
            all:
              - health:
                  - VEGAN
              - cuisine:
                  - Mediterranean
          fit:
            ENERC_KCAL:
              min: 1800
              max: 2200
            PROCNT:
              min: 50
              max: 300
          sections:
            Breakfast: {}
            Lunch:
              exclude:
                - http://www.edamam.com/ontologies/edamam.owl#recipe_x
                - http://www.edamam.com/ontologies/edamam.owl#recipe_y
                - http://www.edamam.com/ontologies/edamam.owl#recipe_z
              sections:
                Starter: {}
                Main: {}
                Dessert: {}
            Dinner:
              exclude:
                - http://www.edamam.com/ontologies/edamam.owl#recipe_a
                - http://www.edamam.com/ontologies/edamam.owl#recipe_b
                - http://www.edamam.com/ontologies/edamam.owl#recipe_c
              sections:
                Main: {}
                Dessert: {}

    Vegan plan assignment:
      description: Vegan meal plan, 2-day selection
      value:
        status: OK
        selection:
          - sections:
              Breakfast:
                assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_1
                _links:
                  self:
                    title: Recipe №1
                    href: https://test-cluster.edamam.com/api/recipes/v2/1?type=public
              Lunch:
                sections:
                    Starter:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_2
                      _links:
                        self:
                          title: Recipe №2
                          href: https://test-cluster.edamam.com/api/recipes/v2/2?type=public
                    Main:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_3
                      _links:
                        self:
                          title: Recipe №3
                          href: https://test-cluster.edamam.com/api/recipes/v2/3?type=public
                    Dessert:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_4
                      _links:
                        self:
                          title: Recipe №4
                          href: https://test-cluster.edamam.com/api/recipes/v2/4?type=public
              Dinner:
                sections:
                    Main:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_5
                      _links:
                        self:
                          title: Recipe №5
                          href: https://test-cluster.edamam.com/api/recipes/v2/5?type=public
                    Dessert:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_6
                      _links:
                        self:
                          title: Recipe №6
                          href: https://test-cluster.edamam.com/api/recipes/v2/6?type=public
          - sections:
              Breakfast:
                assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_7
                _links:
                  self:
                    title: Recipe №7
                    href: https://test-cluster.edamam.com/api/recipes/v2/7?type=public
              Lunch:
                sections:
                    Starter:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_8
                      _links:
                        self:
                          title: Recipe №8
                          href: https://test-cluster.edamam.com/api/recipes/v2/8?type=public
                    Main:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_9
                      _links:
                        self:
                          title: Recipe №9
                          href: https://test-cluster.edamam.com/api/recipes/v2/9?type=public
                    Dessert:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_10
                      _links:
                        self:
                          title: Recipe №10
                          href: https://test-cluster.edamam.com/api/recipes/v2/10?type=public
              Dinner:
                sections:
                    Main:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_11
                      _links:
                        self:
                          title: Recipe №11
                          href: https://test-cluster.edamam.com/api/recipes/v2/11?type=public
                    Dessert:
                      assigned: http://www.edamam.com/ontologies/edamam.owl#recipe_12
                      _links:
                        self:
                          title: Recipe №12
                          href: https://test-cluster.edamam.com/api/recipes/v2/12?type=public

    Recipe execution plan, by servings:
      value:
        entries:
          - quantity: 1
            measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_serving"
            recipe: http://www.edamam.com/ontologies/edamam.owl#recipe_1
          - quantity: 3
            measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_serving"
            recipe: http://www.edamam.com/ontologies/edamam.owl#recipe_2
          - quantity: 2
            measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_serving"
            recipe: http://www.edamam.com/ontologies/edamam.owl#recipe_3

    Recipe execution plan, by total quantity:
      value:
        entries:
          - quantity: 1
            recipe: http://www.edamam.com/ontologies/edamam.owl#recipe_1
          - quantity: 1
            recipe: http://www.edamam.com/ontologies/edamam.owl#recipe_2
          - quantity: 2
            recipe: http://www.edamam.com/ontologies/edamam.owl#recipe_3

    Shopping list:
      value:
        entries:
          - foodId: food_abcdefghijklmnoprqstuvwxyzab
            food: ABC
            quantities:
              - quantity: 2
                measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_unit"
                qualifiers: [ large ]
              - quantity: 5
                measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_unit"
          - foodId: food_defghijklmnoprqstuvwxyzabcde
            food: DEF
            quantities:
              - quantity: 1500
                measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_milliliter"
          - foodId: food_ghijklmnoprqstuvwxyzabcdefgh
            food: GHI
            quantities:
              - quantity: 120
                measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_milliliter"
          - foodId: food_jklmnoprqstuvwxyzabcdefghijk
            food: JKL
            quantities:
              - quantity: 230
                measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_gram"
          - foodId: food_xyzabcdefghijklmnoprqstuvwxy
            food: XYZ
            quantities:
              - quantity: 300
                measure: "http://www.edamam.com/ontologies/edamam.owl#Measure_gram"

  securitySchemes:
    basic:
      type: http
      scheme: basic
