{
  "openapi": "3.0.3",
  "info": {
    "title": "Nutritionist Pro customer API",
    "version": "3.0.0",
    "description": "Read-only access to the recipes, recipe books, ingredients and labels on a Nutritionist Pro online account. Every endpoint is a GET request. The API returns what the key owner can see in Nutritionist Pro.",
    "contact": {
      "name": "Nutritionist Pro support",
      "email": "support@axxya.com"
    }
  },
  "servers": [
    {
      "url": "https://dev.nutritionistpro.com/v3/customer"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Recipes"
    },
    {
      "name": "Recipe books"
    },
    {
      "name": "Ingredients"
    },
    {
      "name": "Labels"
    }
  ],
  "paths": {
    "/recipes": {
      "get": {
        "operationId": "listRecipes",
        "summary": "List recipes",
        "description": "The recipes the key owner can see, newest ID first. Recipes in Draft status are left out.",
        "tags": [
          "Recipes"
        ],
        "responses": {
          "200": {
            "description": "A page of recipes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "$ref": "#/components/schemas/RecipeSummary"
                          },
                          {
                            "$ref": "#/components/schemas/Recipe"
                          }
                        ]
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/offset"
          },
          {
            "$ref": "#/components/parameters/view"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "$ref": "#/components/parameters/updated_until"
          }
        ]
      }
    },
    "/recipes/{id}": {
      "get": {
        "operationId": "getRecipe",
        "summary": "Get one recipe",
        "description": "One recipe with its serving, instructions, allergens, nutrients and ingredient lines.",
        "tags": [
          "Recipes"
        ],
        "responses": {
          "200": {
            "description": "The recipe.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Recipe"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The recipe ID."
          }
        ]
      }
    },
    "/recipe-books": {
      "get": {
        "operationId": "listRecipeBooks",
        "summary": "List recipe books",
        "description": "The recipe books the key owner can see, newest ID first.",
        "tags": [
          "Recipe books"
        ],
        "responses": {
          "200": {
            "description": "A page of recipe books.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RecipeBook"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/offset"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "$ref": "#/components/parameters/updated_until"
          }
        ]
      }
    },
    "/recipe-books/{id}": {
      "get": {
        "operationId": "getRecipeBook",
        "summary": "Get one recipe book",
        "description": "One recipe book.",
        "tags": [
          "Recipe books"
        ],
        "responses": {
          "200": {
            "description": "The recipe book.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/RecipeBook"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The recipe book ID."
          }
        ]
      }
    },
    "/recipe-books/{id}/recipes": {
      "get": {
        "operationId": "listRecipeBookRecipes",
        "summary": "List the recipes in a book",
        "description": "The book, a page of its recipes, and the IDs of recipes that were deleted. deleted_recipe_ids is returned in full on every page.",
        "tags": [
          "Recipe books"
        ],
        "responses": {
          "200": {
            "description": "The book and a page of its recipes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/RecipeBookRecipes"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The recipe book ID."
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/offset"
          },
          {
            "$ref": "#/components/parameters/view"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "$ref": "#/components/parameters/updated_until"
          }
        ]
      }
    },
    "/ingredients/{id}": {
      "get": {
        "operationId": "getIngredient",
        "summary": "Get one ingredient",
        "description": "One ingredient. There is no ingredient list or search. An Axxya database ingredient can be read only when it is used in a recipe the key owner can see.",
        "tags": [
          "Ingredients"
        ],
        "responses": {
          "200": {
            "description": "The ingredient.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Ingredient"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ingredient ID, from the ingredient_id of a recipe's ingredient line."
          }
        ]
      }
    },
    "/labels": {
      "get": {
        "operationId": "listLabels",
        "summary": "List labels",
        "description": "The labels the key owner can see, newest ID first. Labels in Draft status are left out.",
        "tags": [
          "Labels"
        ],
        "responses": {
          "200": {
            "description": "A page of labels.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LabelSummary"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/offset"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "$ref": "#/components/parameters/updated_until"
          }
        ]
      }
    },
    "/labels/{id}": {
      "get": {
        "operationId": "getLabel",
        "summary": "Get one label",
        "description": "One label with its footnote and the foods on it. Nutrient values are returned as saved on the label.",
        "tags": [
          "Labels"
        ],
        "responses": {
          "200": {
            "description": "The label.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "code": {
                      "type": "integer",
                      "enum": [
                        200
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  },
                  "required": [
                    "status",
                    "code",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The label ID."
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key from the Settings page of Nutritionist Pro online. It begins with npcust_."
      }
    },
    "parameters": {
      "limit": {
        "name": "limit",
        "in": "query",
        "description": "Records to return. A value outside the range is refused with 400.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "offset": {
        "name": "offset",
        "in": "query",
        "description": "Records to skip.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      },
      "view": {
        "name": "view",
        "in": "query",
        "description": "summary returns RecipeSummary items. full returns Recipe items.",
        "schema": {
          "type": "string",
          "enum": [
            "summary",
            "full"
          ],
          "default": "summary"
        }
      },
      "updated_since": {
        "name": "updated_since",
        "in": "query",
        "description": "Return records changed at or after this moment. A date (YYYY-MM-DD) or an ISO 8601 date and time. A date and time with no offset is read as UTC.",
        "schema": {
          "type": "string"
        },
        "example": "2026-05-01"
      },
      "updated_until": {
        "name": "updated_until",
        "in": "query",
        "description": "Return records changed before this moment. A date covers that whole day. A date (YYYY-MM-DD) or an ISO 8601 date and time. A date and time with no offset is read as UTC.",
        "schema": {
          "type": "string"
        },
        "example": "2026-05-31"
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "The daily request limit for the key owner.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left today. The count resets at midnight UTC.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "When the daily count resets, as Unix time in seconds (the next midnight UTC).",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Seconds until the daily count resets at midnight UTC.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A query parameter has a value the API cannot use.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "status": false,
              "code": 400,
              "message": "'limit' must be between 1 and 200"
            }
          }
        },
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        }
      },
      "Unauthorized": {
        "description": "The API key is missing or is not accepted.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "status": false,
              "code": 401,
              "message": "Invalid API key"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key is valid and the account has no active subscription.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "status": false,
              "code": 403,
              "message": "This account has no active subscription."
            }
          }
        }
      },
      "NotFound": {
        "description": "The record does not exist, is in Draft status, or belongs to another account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "status": false,
              "code": 404,
              "message": "Recipe not found"
            }
          }
        },
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        }
      },
      "TooManyRequests": {
        "description": "The daily request limit was reached. The body says when the count resets.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RateLimitError"
            },
            "example": {
              "status": false,
              "code": 429,
              "message": "Daily request limit reached. This API key's user has made all 500 customer API requests allowed per day. The limit resets at midnight UTC (2026-10-26T00:00:00Z), in 3 hours 12 minutes.",
              "limit": 500,
              "reset_at": "2026-10-26T00:00:00Z",
              "retry_after_seconds": 11520
            }
          }
        },
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "status": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "code": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "message": {
            "type": "string",
            "description": "A short description for people. The wording can change."
          }
        },
        "required": [
          "status",
          "code",
          "message"
        ]
      },
      "RateLimitError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Error"
          },
          {
            "type": "object",
            "properties": {
              "limit": {
                "type": "integer",
                "description": "The daily request limit for the key owner."
              },
              "reset_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the daily count resets: the next midnight UTC, in ISO 8601."
              },
              "retry_after_seconds": {
                "type": "integer",
                "description": "Seconds until the count resets. The same value as the Retry-After header."
              }
            },
            "required": [
              "limit",
              "reset_at",
              "retry_after_seconds"
            ]
          }
        ]
      },
      "Meta": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "Records that match the request, across all pages."
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        },
        "required": [
          "total",
          "limit",
          "offset"
        ]
      },
      "NamedRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "Creator": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name"
        ],
        "nullable": true,
        "description": "The user who created the record."
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name"
        ],
        "nullable": true,
        "description": "The account the creator belongs to."
      },
      "Serving": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          },
          "gram_weight": {
            "type": "number",
            "nullable": true
          },
          "note": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "amount",
          "unit",
          "gram_weight",
          "note"
        ],
        "nullable": true,
        "description": "The typical serving."
      },
      "Nutrient": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The nutrient ID. Stable, so match nutrients by it."
          },
          "name": {
            "type": "string"
          },
          "abbreviation": {
            "type": "string",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          },
          "value": {
            "type": "number",
            "description": "The amount for one serving, rounded to three decimal places."
          }
        },
        "required": [
          "id",
          "name",
          "abbreviation",
          "unit",
          "value"
        ]
      },
      "IngredientLine": {
        "type": "object",
        "properties": {
          "line": {
            "type": "integer",
            "description": "The position of the line in the recipe."
          },
          "ingredient_id": {
            "type": "integer",
            "nullable": true,
            "description": "Use with GET /ingredients/{id}."
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "amount": {
            "type": "number",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          },
          "text": {
            "type": "string",
            "nullable": true,
            "description": "The line as it reads in the recipe."
          }
        },
        "required": [
          "line",
          "ingredient_id",
          "name",
          "amount",
          "unit",
          "text"
        ]
      },
      "RecipeSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The recipe ID."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "The recipe name."
          },
          "code": {
            "type": "string",
            "nullable": true,
            "description": "The recipe's unique code."
          },
          "number_of_servings": {
            "type": "number",
            "nullable": true,
            "description": "How many servings the recipe makes."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "The time of the recipe's most recent save."
          }
        },
        "required": [
          "id",
          "name",
          "code",
          "number_of_servings",
          "created_at",
          "updated_at"
        ]
      },
      "Recipe": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The recipe ID."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "The recipe name."
          },
          "code": {
            "type": "string",
            "nullable": true,
            "description": "The recipe's unique code."
          },
          "number_of_servings": {
            "type": "number",
            "nullable": true,
            "description": "How many servings the recipe makes."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "The time of the recipe's most recent save."
          },
          "region": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NamedRef"
              }
            ],
            "nullable": true
          },
          "preparation_method": {
            "type": "string",
            "nullable": true
          },
          "meal_component": {
            "type": "string",
            "nullable": true
          },
          "preparation_time": {
            "type": "string",
            "nullable": true
          },
          "cooking_time_minutes": {
            "type": "integer",
            "nullable": true
          },
          "cooking_temperature": {
            "type": "string",
            "nullable": true
          },
          "instructions": {
            "type": "string",
            "nullable": true,
            "description": "The steps in order, separated by line breaks."
          },
          "serving": {
            "$ref": "#/components/schemas/Serving"
          },
          "allergens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NamedRef"
            }
          },
          "nutrient_basis": {
            "type": "string",
            "enum": [
              "per_serving"
            ]
          },
          "nutrients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Nutrient"
            }
          },
          "ingredients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IngredientLine"
            }
          },
          "creator": {
            "$ref": "#/components/schemas/Creator"
          },
          "account": {
            "$ref": "#/components/schemas/Account"
          }
        },
        "required": [
          "id",
          "name",
          "code",
          "number_of_servings",
          "created_at",
          "updated_at",
          "region",
          "preparation_method",
          "meal_component",
          "preparation_time",
          "cooking_time_minutes",
          "cooking_temperature",
          "instructions",
          "serving",
          "allergens",
          "nutrient_basis",
          "nutrients",
          "ingredients",
          "creator",
          "account"
        ]
      },
      "RecipeBook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "recipe_count": {
            "type": "integer",
            "description": "Recipes listed in the book. A recipe listed twice is counted once."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "creator": {
            "$ref": "#/components/schemas/Creator"
          },
          "account": {
            "$ref": "#/components/schemas/Account"
          }
        },
        "required": [
          "id",
          "name",
          "recipe_count",
          "created_at",
          "updated_at",
          "creator",
          "account"
        ]
      },
      "RecipeBookRecipes": {
        "type": "object",
        "properties": {
          "book": {
            "$ref": "#/components/schemas/RecipeBook"
          },
          "recipes": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/RecipeSummary"
                },
                {
                  "$ref": "#/components/schemas/Recipe"
                }
              ]
            }
          },
          "deleted_recipe_ids": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "IDs the book still lists for recipes that no longer exist."
          }
        },
        "required": [
          "book",
          "recipes",
          "deleted_recipe_ids"
        ]
      },
      "Ingredient": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "code": {
            "type": "string",
            "nullable": true
          },
          "source_code": {
            "type": "string",
            "nullable": true,
            "description": "The code the food carries from the database it came from: the 8-digit USDA FNDDS food code, the USDA Standard Reference NDB number or the Canadian Nutrient File code. Null for a food without one."
          },
          "source_code_type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "fndds",
              "usda_ndb",
              "cnf",
              "other"
            ],
            "description": "Which database source_code belongs to. Null when source_code is null."
          },
          "source": {
            "type": "string",
            "enum": [
              "own",
              "axxya"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "ingredient",
              "recipe"
            ]
          },
          "serving": {
            "$ref": "#/components/schemas/Serving"
          },
          "allergens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NamedRef"
            }
          },
          "nutrient_basis": {
            "type": "string",
            "enum": [
              "per_serving"
            ]
          },
          "nutrients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Nutrient"
            }
          },
          "creator": {
            "$ref": "#/components/schemas/Creator"
          },
          "account": {
            "$ref": "#/components/schemas/Account"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name",
          "code",
          "source_code",
          "source_code_type",
          "source",
          "type",
          "serving",
          "allergens",
          "nutrient_basis",
          "nutrients"
        ],
        "description": "creator, account, created_at and updated_at are returned for your own ingredients only."
      },
      "LabelSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "short_name": {
            "type": "string",
            "nullable": true
          },
          "region": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NamedRef"
              }
            ],
            "nullable": true
          },
          "label_type_id": {
            "type": "integer",
            "nullable": true
          },
          "language_id": {
            "type": "integer",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "creator": {
            "$ref": "#/components/schemas/Creator"
          },
          "account": {
            "$ref": "#/components/schemas/Account"
          }
        },
        "required": [
          "id",
          "name",
          "short_name",
          "region",
          "label_type_id",
          "language_id",
          "created_at",
          "updated_at",
          "creator",
          "account"
        ]
      },
      "LabelNutrient": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          },
          "value": {
            "type": "number",
            "nullable": true,
            "description": "The value before rounding."
          },
          "rounded_value": {
            "type": "number",
            "nullable": true,
            "description": "The rounded value saved on the label."
          }
        },
        "required": [
          "id",
          "name",
          "unit",
          "value",
          "rounded_value"
        ]
      },
      "LabelServing": {
        "type": "object",
        "properties": {
          "household_measure": {
            "type": "string",
            "nullable": true
          },
          "metric_value": {
            "type": "number",
            "nullable": true
          },
          "metric_unit": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "household_measure",
          "metric_value",
          "metric_unit"
        ]
      },
      "LabelFood": {
        "type": "object",
        "properties": {
          "food_id": {
            "type": "integer",
            "nullable": true,
            "description": "The recipe or ingredient the label was made from."
          },
          "serving": {
            "$ref": "#/components/schemas/LabelServing"
          },
          "ingredient_statement": {
            "type": "string",
            "nullable": true
          },
          "allergen_statement": {
            "type": "string",
            "nullable": true
          },
          "nutrients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LabelNutrient"
            }
          }
        },
        "required": [
          "food_id",
          "serving",
          "ingredient_statement",
          "allergen_statement",
          "nutrients"
        ]
      },
      "Label": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "short_name": {
            "type": "string",
            "nullable": true
          },
          "region": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NamedRef"
              }
            ],
            "nullable": true
          },
          "label_type_id": {
            "type": "integer",
            "nullable": true
          },
          "language_id": {
            "type": "integer",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "creator": {
            "$ref": "#/components/schemas/Creator"
          },
          "account": {
            "$ref": "#/components/schemas/Account"
          },
          "foot_note": {
            "type": "string",
            "nullable": true
          },
          "foods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LabelFood"
            }
          }
        },
        "required": [
          "id",
          "name",
          "short_name",
          "region",
          "label_type_id",
          "language_id",
          "created_at",
          "updated_at",
          "creator",
          "account",
          "foot_note",
          "foods"
        ]
      }
    }
  }
}
