{
  "openapi": "3.1.1",
  "info": {
    "title": "Succession Sowing Planner API",
    "version": "1.0.0",
    "summary": "Space repeat sowings of lettuce, radish, beans and more so you harvest all season.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://greenplotsuccessionplanner.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Space repeat sowings of lettuce, radish, beans and more so you harvest all season.",
        "description": "Plans repeat sowings of one vegetable, herb or flower from your frost dates: a sowing every few weeks, each with its harvest window and number of plants, until the last sowing that still ripens before the autumn frost — with gaps in the harvest pointed out and a timeline chart.\n\nMethodology:\n- The first sowing is the start of the plant’s outdoor sowing (or planting-out) window, counted in weeks from your last spring frost — the same window as the garden calendar — or the date you give.\n- Sowings repeat every n weeks (the plant’s usual interval when you leave 0, or three weeks). The last sowing is the last one that still ripens before the end of the season: the first autumn frost minus 14 days for tender plants, the frost itself for half-hardy ones and two weeks after it for hardy ones, minus the days to harvest.\n- Each sowing is picked for the interval (at least two weeks), so harvests follow on; a gap is reported where one harvest ends before the next begins. Plants per sowing = squares × plants per 30 cm square (square-foot spacing from the plant table).\n- Sowings after the end of the usual sowing window are marked: many crops still ripen then, but bolting (lettuce, spinach, coriander in hot weather) and slow autumn growth are more likely.\n\nDays to harvest vary with variety and weather; in midsummer choose bolt-resistant varieties and shade young sowings.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "greenplot_succession_planner",
        "x-owner-app": "greenplot",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GreenplotSuccessionPlannerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Lettuce every three weeks, two squares each",
                  "value": {
                    "plant": "lettuce",
                    "lastFrost": "04-08",
                    "firstFrost": "11-02",
                    "year": 2027,
                    "intervalWeeks": 0,
                    "squares": 2
                  }
                },
                "example2": {
                  "summary": "Radishes every two weeks",
                  "value": {
                    "plant": "radish",
                    "lastFrost": "04-20",
                    "firstFrost": "10-20",
                    "year": 2027,
                    "intervalWeeks": 2,
                    "squares": 1
                  }
                },
                "example3": {
                  "summary": "Bush beans from mid-May, every four weeks",
                  "value": {
                    "plant": "bush-bean",
                    "lastFrost": "05-06",
                    "firstFrost": "10-06",
                    "year": 2027,
                    "intervalWeeks": 4,
                    "squares": 4,
                    "start": "2027-05-15"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GreenplotSuccessionPlannerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "GreenplotSuccessionPlannerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "plant": {
            "title": "Plant",
            "type": "string",
            "enum": [
              "tomato",
              "pepper",
              "eggplant",
              "potato",
              "cucumber",
              "zucchini",
              "squash",
              "melon",
              "sweetcorn",
              "bush-bean",
              "pole-bean",
              "pea",
              "broad-bean",
              "lettuce",
              "spinach",
              "chard",
              "beet",
              "carrot",
              "parsnip",
              "radish",
              "turnip",
              "onion",
              "spring-onion",
              "garlic",
              "leek",
              "cabbage",
              "broccoli",
              "cauliflower",
              "kale",
              "brussels-sprouts",
              "kohlrabi",
              "pak-choi",
              "rocket",
              "celery",
              "fennel",
              "parsley",
              "basil",
              "dill",
              "coriander",
              "chives",
              "jerusalem-artichoke",
              "sweet-potato",
              "okra",
              "celeriac",
              "swede",
              "endive",
              "chicory",
              "mizuna",
              "corn-salad",
              "shallot",
              "chilli",
              "mangetout",
              "chinese-cabbage",
              "cress",
              "mustard-greens",
              "soybean",
              "tomatillo",
              "watermelon",
              "marjoram",
              "chamomile",
              "borage",
              "chervil",
              "summer-savory",
              "physalis",
              "sunflower",
              "french-marigold",
              "calendula",
              "nasturtium",
              "sweet-pea",
              "cosmos",
              "zinnia",
              "cornflower",
              "poppy",
              "nigella",
              "phacelia",
              "crimson-clover",
              "dahlia",
              "tulip",
              "daffodil",
              "snapdragon",
              "alyssum",
              "larkspur",
              "gladiolus"
            ],
            "default": "lettuce"
          },
          "lastFrost": {
            "title": "Last spring frost (MM-DD)",
            "description": "Month and day, for example 04-20. Hearth’s Frost Dates Finder gives it for Germany and the United States.",
            "type": "string",
            "maxLength": 5,
            "default": "04-20"
          },
          "firstFrost": {
            "title": "First autumn frost (MM-DD)",
            "type": "string",
            "maxLength": 5,
            "default": "10-20"
          },
          "year": {
            "title": "Season (year of the spring frost)",
            "type": "integer",
            "minimum": 2000,
            "maximum": 2100,
            "default": 2027
          },
          "intervalWeeks": {
            "title": "Weeks between sowings (0 = the plant’s usual interval)",
            "type": "integer",
            "minimum": 0,
            "maximum": 12,
            "default": 0
          },
          "squares": {
            "title": "30 cm squares per sowing",
            "type": "integer",
            "minimum": 1,
            "maximum": 64,
            "default": 2
          },
          "start": {
            "title": "First sowing (optional)",
            "description": "Empty = start of the sowing window.",
            "type": "string",
            "format": "date"
          }
        },
        "required": [
          "lastFrost",
          "firstFrost"
        ]
      },
      "GreenplotSuccessionPlannerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "year",
              "lastFrost",
              "firstFrost",
              "name",
              "plant",
              "intervalWeeks",
              "squares",
              "plantsPerSowing",
              "daysToHarvest",
              "windowFrom",
              "windowTo",
              "lastSowing",
              "seasonEnd",
              "sowings",
              "totalPlants",
              "gaps",
              "harvestFrom",
              "harvestTo",
              "outsideWindow"
            ],
            "properties": {
              "year": {
                "type": "integer"
              },
              "lastFrost": {
                "type": "string"
              },
              "firstFrost": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "plant": {
                "type": "string"
              },
              "intervalWeeks": {
                "type": "integer"
              },
              "squares": {
                "type": "integer"
              },
              "plantsPerSowing": {
                "type": "integer"
              },
              "daysToHarvest": {
                "type": "integer"
              },
              "windowFrom": {
                "type": "string"
              },
              "windowTo": {
                "type": "string"
              },
              "lastSowing": {
                "type": "string"
              },
              "seasonEnd": {
                "type": "string"
              },
              "sowings": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "n",
                    "sow",
                    "indoor",
                    "harvestFrom",
                    "harvestTo",
                    "plants",
                    "inWindow"
                  ],
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "sow": {
                      "type": "string"
                    },
                    "indoor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "harvestFrom": {
                      "type": "string"
                    },
                    "harvestTo": {
                      "type": "string"
                    },
                    "plants": {
                      "type": "integer"
                    },
                    "inWindow": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "totalPlants": {
                "type": "integer"
              },
              "gaps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "after",
                    "days"
                  ],
                  "properties": {
                    "after": {
                      "type": "integer"
                    },
                    "days": {
                      "type": "integer"
                    }
                  }
                }
              },
              "harvestFrom": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "harvestTo": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "outsideWindow": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}