{
  "openapi": "3.1.1",
  "info": {
    "title": "Rapport Pipeline Forecast API",
    "version": "1.0.0",
    "summary": "Weighted sales forecast, pipeline per stage, win rate and sales cycle from a deals CSV.",
    "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://rapportpipelineforecast.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Weighted sales forecast, pipeline per stage, win rate and sales cycle from a deals CSV.",
        "description": "Reads a deals export (Rapport, HubSpot or Pipedrive CSV, or a Rapport CRM file) and computes the open pipeline per stage, the weighted forecast per month by expected close date, overdue deals, win rate by count and value, the average and median sales cycle and the numbers per owner. Same calculation as the Rapport dashboard.\n\nMethodology:\n- Weighted value of an open deal = value × probability. The probability is the deal’s own value when the file has one, otherwise the stage’s; won stages count 100 %, lost 0 %.\n- Forecast per month: open deals grouped by the month of their expected close date, starting with the month of “Today is”. Open deals whose expected close lies before “Today is” are listed as overdue instead; deals without a date are only in the stage totals.\n- Win rate = won ÷ (won + lost) among deals closed inside the window, by count and by value. Sales cycle = days from creation to the won date of the deals won in the window (average and median).\n- CSV files: stages are taken in the order they first appear among open deals. Without a probability column, stage probabilities are spread evenly (the tool says so), so add one for real numbers.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "rapport_pipeline_forecast",
        "x-owner-app": "rapport",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RapportPipelineForecastInput"
              },
              "examples": {
                "example1": {
                  "summary": "Pipedrive deals export, six months",
                  "value": {
                    "deals": "Deal - Title,Deal - Value,Deal - Currency,Deal - Pipeline,Deal - Stage,Deal - Status,Deal - Probability,Deal - Expected close date,Deal - Owner,Deal - Organization,Deal - Contact person,Deal - Deal created,Deal - Won time,Deal - Lost time,Deal - Lost reason\r\nBooking site relaunch,84000,EUR,Sales,Negotiation,open,75,2026-12-12,Mara Lindqvist,Fjordline Ferries AS,Ingrid Halvorsen,2026-09-15,,,\r\nOnline shop for beans,18500,EUR,Sales,Proposal made,open,50,2026-12-19,Jonas Becker,Kaffeerösterei Hansen,Paul Hansen,2026-10-15,,,\r\nPatient portal UX audit,12000,EUR,Sales,Qualified,open,25,2027-01-08,Ada Okafor,Mediq Health GmbH,Lena Vogt,2026-11-04,,,\r\nBrand refresh,9500,EUR,Sales,Lead in,open,10,2027-01-23,Jonas Becker,Atelier Rousseau SARL,Camille Rousseau,2026-11-09,,,\r\nDriver app design system,56000,EUR,Sales,Proposal made,open,60,2026-12-26,Mara Lindqvist,Greenway Logistics B.V.,Daan de Vries,2026-10-20,,,\r\nIntranet news hub,22000,EUR,Sales,Lead in,open,10,2027-02-07,Ada Okafor,Mediq Pharma Services,Tobias Krüger,2026-11-14,,,\r\nShop maintenance 2026,7200,EUR,Sales,Proposal made,won,,2026-08-21,Jonas Becker,Kaffeerösterei Hansen,Paul Hansen,2026-07-27,2026-08-21,,\r\nSpring campaign landing pages,14800,EUR,Sales,Negotiation,won,,2026-04-18,Mara Lindqvist,Solberg Outdoor,Elin Solberg,2026-03-09,2026-04-18,,\r\nAccessibility retrofit,31000,EUR,Sales,Negotiation,won,,2026-09-25,Ada Okafor,Mediq Health GmbH,Lena Vogt,2026-06-27,2026-09-25,,\r\nFleet tracking dashboard,42000,EUR,Sales,Proposal made,lost,,2026-07-17,Mara Lindqvist,Greenway Logistics B.V.,Daan de Vries,2026-05-08,,2026-07-17,Chose an in-house team\r\nOutdoor catalogue print,6000,EUR,Sales,Qualified,lost,,2026-03-09,Jonas Becker,Solberg Outdoor,Elin Solberg,2026-01-28,,2026-03-09,Budget cut\r\nFerry app onboarding,26000,EUR,Sales,Negotiation,won,,2026-11-04,Mara Lindqvist,Fjordline Ferries AS,Henrik Aas,2026-08-21,2026-11-04,,\r\n",
                    "asOf": "2026-11-24"
                  }
                },
                "example2": {
                  "summary": "Rapport agency template, twelve months",
                  "value": {
                    "deals": "{\"format\":\"rapport\",\"version\":1,\"name\":\"Northlight Studio — new business\",\"currency\":\"EUR\",\"country\":\"DE\",\"settings\":{\"privateDeals\":false,\"retentionMonths\":24,\"quotePrefix\":\"Q-\",\"nextQuote\":3,\"ossB2C\":true,\"quoteDays\":30,\"seller\":{\"name\":\"Northlight Studio GmbH\",\"address\":\"Kastanienallee 12, 10435 Berlin, Germany\",\"vatId\":\"DE123456789\",\"email\":\"hello@northlight.example\",\"phone\":\"\",\"iban\":\"DE02 1001 0010 0006 8201 01\"}},\"people\":[{\"id\":\"me\",\"name\":\"Mara Lindqvist\"},{\"id\":\"jon\",\"name\":\"Jonas Becker\"},{\"id\":\"ada\",\"name\":\"Ada Okafor\"}],\"pipelines\":[{\"id\":\"sales\",\"name\":\"Sales\",\"stages\":[{\"id\":\"lead\",\"name\":\"Lead\",\"probability\":10,\"kind\":\"open\"},{\"id\":\"qualified\",\"name\":\"Qualified\",\"probability\":25,\"kind\":\"open\"},{\"id\":\"proposal\",\"name\":\"Proposal\",\"probability\":50,\"kind\":\"open\"},{\"id\":\"negotiation\",\"name\":\"Negotiation\",\"probability\":75,\"kind\":\"open\"},{\"id\":\"won\",\"name\":\"Won\",\"probability\":100,\"kind\":\"won\"},{\"id\":\"lost\",\"name\":\"Lost\",\"probability\":0,\"kind\":\"lost\"}]}],\"companies\":[{\"id\":\"o1\",\"name\":\"Fjordline Ferries AS\",\"domain\":\"fjordline.example\",\"industry\":\"Travel\",\"size\":\"500–1000\",\"phone\":\"\",\"address\":\"Bergen, Norway\",\"country\":\"NO\",\"vatId\":\"\",\"owner\":\"me\",\"tags\":[\"enterprise\"],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-08T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o2\",\"name\":\"Kaffeerösterei Hansen\",\"domain\":\"hansen-kaffee.example\",\"industry\":\"Food \u0026 drink\",\"size\":\"10–50\",\"phone\":\"\",\"address\":\"Hamburg\",\"country\":\"DE\",\"vatId\":\"\",\"owner\":\"me\",\"tags\":[\"retail\"],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-09T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o3\",\"name\":\"Mediq Health GmbH\",\"domain\":\"mediq.example\",\"industry\":\"Healthcare\",\"size\":\"200–500\",\"phone\":\"\",\"address\":\"Munich\",\"country\":\"DE\",\"vatId\":\"DE811223344\",\"owner\":\"me\",\"tags\":[\"enterprise\",\"regulated\"],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-10T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o4\",\"name\":\"Atelier Rousseau SARL\",\"domain\":\"rousseau.example\",\"industry\":\"Fashion\",\"size\":\"10–50\",\"phone\":\"\",\"address\":\"Lyon, France\",\"country\":\"FR\",\"vatId\":\"FR40303265045\",\"owner\":\"me\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-11T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o5\",\"name\":\"Greenway Logistics B.V.\",\"domain\":\"greenway.example\",\"industry\":\"Logistics\",\"size\":\"1000+\",\"phone\":\"\",\"address\":\"Rotterdam, Netherlands\",\"country\":\"NL\",\"vatId\":\"NL859052841B01\",\"owner\":\"me\",\"tags\":[\"enterprise\"],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-12T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o6\",\"name\":\"Mediq Pharma Services\",\"domain\":\"mediq-pharma.example\",\"industry\":\"Healthcare\",\"size\":\"50–200\",\"phone\":\"\",\"address\":\"Munich\",\"country\":\"DE\",\"vatId\":\"\",\"owner\":\"me\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-13T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o7\",\"name\":\"Solberg Outdoor\",\"domain\":\"solberg.example\",\"industry\":\"Retail\",\"size\":\"50–200\",\"phone\":\"\",\"address\":\"Gothenburg, Sweden\",\"country\":\"SE\",\"vatId\":\"\",\"owner\":\"me\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-14T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"},{\"id\":\"o8\",\"name\":\"Pixelwerk Freelancers\",\"domain\":\"pixelwerk.example\",\"industry\":\"Design\",\"size\":\"1–10\",\"phone\":\"\",\"address\":\"Leipzig\",\"country\":\"DE\",\"vatId\":\"\",\"owner\":\"me\",\"tags\":[\"partner\"],\"custom\":{},\"notes\":\"\",\"created\":\"2025-12-15T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\"}],\"contacts\":[{\"id\":\"c1\",\"firstName\":\"Ingrid\",\"lastName\":\"Halvorsen\",\"email\":\"ingrid.halvorsen@fjordline.example\",\"phone\":\"+47 55 12 34 56\",\"title\":\"Head of Digital\",\"companyId\":\"o1\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"decision-maker\"],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"legitimate-interest\",\"marketing\":false,\"date\":\"2026-04-28\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2026-04-28T10:00:00.000Z\",\"updated\":\"2026-11-21T10:00:00.000Z\",\"lastContact\":\"2026-11-21\"},{\"id\":\"c2\",\"firstName\":\"Paul\",\"lastName\":\"Hansen\",\"email\":\"paul.hansen@hansen-kaffee.example\",\"phone\":\"+49 40 2345678\",\"title\":\"Owner\",\"companyId\":\"o2\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"customer\",\"decision-maker\"],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"contract\",\"marketing\":false,\"date\":\"2025-12-29\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2025-12-29T10:00:00.000Z\",\"updated\":\"2026-11-12T10:00:00.000Z\",\"lastContact\":\"2026-11-12\"},{\"id\":\"c3\",\"firstName\":\"Lena\",\"lastName\":\"Vogt\",\"email\":\"lena.vogt@mediq.example\",\"phone\":\"+49 89 7654321\",\"title\":\"Marketing Director\",\"companyId\":\"o3\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"decision-maker\"],\"custom\":{\"cf2\":true},\"notes\":\"\",\"consent\":{\"basis\":\"consent\",\"marketing\":true,\"date\":\"2026-08-26\",\"source\":\"Web form\",\"note\":\"\"},\"created\":\"2026-08-26T10:00:00.000Z\",\"updated\":\"2026-11-23T10:00:00.000Z\",\"lastContact\":\"2026-11-23\"},{\"id\":\"c4\",\"firstName\":\"Camille\",\"lastName\":\"Rousseau\",\"email\":\"camille.rousseau@rousseau.example\",\"phone\":\"\",\"title\":\"Creative Director\",\"companyId\":\"o4\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"legitimate-interest\",\"marketing\":false,\"date\":\"2026-06-27\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2026-06-27T10:00:00.000Z\",\"updated\":\"2026-10-15T10:00:00.000Z\",\"lastContact\":\"2026-10-15\"},{\"id\":\"c5\",\"firstName\":\"Daan\",\"lastName\":\"de Vries\",\"email\":\"daan.devries@greenway.example\",\"phone\":\"\",\"title\":\"CIO\",\"companyId\":\"o5\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"decision-maker\"],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"legitimate-interest\",\"marketing\":false,\"date\":\"2026-09-25\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2026-09-25T10:00:00.000Z\",\"updated\":\"2026-11-18T10:00:00.000Z\",\"lastContact\":\"2026-11-18\"},{\"id\":\"c6\",\"firstName\":\"Sanne\",\"lastName\":\"Bakker\",\"email\":\"sanne.bakker@greenway.example\",\"phone\":\"\",\"title\":\"E-commerce Manager\",\"companyId\":\"o5\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[],\"custom\":{\"cf2\":true},\"notes\":\"\",\"consent\":{\"basis\":\"consent\",\"marketing\":true,\"date\":\"2026-09-30\",\"source\":\"Web form\",\"note\":\"\"},\"created\":\"2026-09-30T10:00:00.000Z\",\"updated\":\"2026-11-18T10:00:00.000Z\",\"lastContact\":\"2026-11-18\"},{\"id\":\"c7\",\"firstName\":\"Tobias\",\"lastName\":\"Krüger\",\"email\":\"tobias.kruger@mediq-pharma.example\",\"phone\":\"\",\"title\":\"Communications Lead\",\"companyId\":\"o6\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"legitimate-interest\",\"marketing\":false,\"date\":\"2026-10-25\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2026-10-25T10:00:00.000Z\",\"updated\":\"2026-11-09T10:00:00.000Z\",\"lastContact\":\"2026-11-09\"},{\"id\":\"c8\",\"firstName\":\"Elin\",\"lastName\":\"Solberg\",\"email\":\"elin.solberg@solberg.example\",\"phone\":\"\",\"title\":\"CEO\",\"companyId\":\"o7\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"customer\"],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"contract\",\"marketing\":false,\"date\":\"2025-09-30\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2025-09-30T10:00:00.000Z\",\"updated\":\"2025-11-09T10:00:00.000Z\",\"lastContact\":\"2025-11-09\"},{\"id\":\"c9\",\"firstName\":\"Max\",\"lastName\":\"Pfeiffer\",\"email\":\"max.pfeiffer@pixelwerk.example\",\"phone\":\"\",\"title\":\"Freelance developer\",\"companyId\":\"o8\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"partner\"],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"contract\",\"marketing\":false,\"date\":\"2025-07-12\",\"source\":\"First meeting\",\"note\":\"\"},\"created\":\"2025-07-12T10:00:00.000Z\",\"updated\":\"2026-10-30T10:00:00.000Z\",\"lastContact\":\"2026-10-30\"},{\"id\":\"c10\",\"firstName\":\"Lena\",\"lastName\":\"Vogt\",\"email\":\"lena.vogt@mediq.example\",\"phone\":\"\",\"title\":\"Marketing\",\"companyId\":\"o3\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"\",\"marketing\":false,\"date\":\"\",\"source\":\"\",\"note\":\"\"},\"created\":\"2026-11-12T10:00:00.000Z\",\"updated\":\"2026-11-14T10:00:00.000Z\",\"lastContact\":\"\"},{\"id\":\"c11\",\"firstName\":\"Henrik\",\"lastName\":\"Aas\",\"email\":\"henrik.aas@fjordline.example\",\"phone\":\"\",\"title\":\"Product Owner\",\"companyId\":\"o1\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"consent\",\"marketing\":false,\"date\":\"2026-10-10\",\"source\":\"Web form\",\"note\":\"\"},\"created\":\"2026-10-10T10:00:00.000Z\",\"updated\":\"2026-11-15T10:00:00.000Z\",\"lastContact\":\"2026-11-15\"},{\"id\":\"c12\",\"firstName\":\"Yusuf\",\"lastName\":\"Demir\",\"email\":\"yusuf.demir@example.org\",\"phone\":\"\",\"title\":\"Founder\",\"companyId\":\"\",\"owner\":\"me\",\"address\":\"\",\"country\":\"\",\"birthday\":\"\",\"website\":\"\",\"tags\":[\"lead\"],\"custom\":{},\"notes\":\"\",\"consent\":{\"basis\":\"consent\",\"marketing\":true,\"date\":\"2026-11-16\",\"source\":\"Web form\",\"note\":\"\"},\"created\":\"2026-11-16T10:00:00.000Z\",\"updated\":\"2026-11-14T10:00:00.000Z\",\"lastContact\":\"\"}],\"relationships\":[{\"id\":\"r1\",\"from\":\"o:o3\",\"to\":\"o:o6\",\"type\":\"parent-of\",\"note\":\"\"},{\"id\":\"r2\",\"from\":\"o:o8\",\"to\":\"o:o2\",\"type\":\"partner\",\"note\":\"\"},{\"id\":\"r3\",\"from\":\"c:c6\",\"to\":\"c:c5\",\"type\":\"reports-to\",\"note\":\"\"},{\"id\":\"r4\",\"from\":\"c:c11\",\"to\":\"c:c1\",\"type\":\"referred-by\",\"note\":\"\"}],\"deals\":[{\"id\":\"d1\",\"title\":\"Booking site relaunch\",\"pipelineId\":\"sales\",\"stageId\":\"negotiation\",\"value\":84000,\"probability\":null,\"expectedClose\":\"2026-12-12\",\"owner\":\"me\",\"companyId\":\"o1\",\"contactIds\":[\"c1\",\"c11\"],\"tags\":[\"web\"],\"custom\":{\"cf1\":\"Referral\"},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-09-15T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-09-15T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-10-08T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-11-01T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-11-24T10:00:00.000Z\",\"stageId\":\"negotiation\"}]},{\"id\":\"d2\",\"title\":\"Online shop for beans and subscriptions\",\"pipelineId\":\"sales\",\"stageId\":\"proposal\",\"value\":18500,\"probability\":null,\"expectedClose\":\"2026-12-19\",\"owner\":\"jon\",\"companyId\":\"o2\",\"contactIds\":[\"c2\"],\"tags\":[\"shop\"],\"custom\":{\"cf1\":\"Website\"},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-10-15T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-10-15T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-11-04T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-11-24T10:00:00.000Z\",\"stageId\":\"proposal\"}]},{\"id\":\"d3\",\"title\":\"Patient portal UX audit\",\"pipelineId\":\"sales\",\"stageId\":\"qualified\",\"value\":12000,\"probability\":null,\"expectedClose\":\"2027-01-08\",\"owner\":\"ada\",\"companyId\":\"o3\",\"contactIds\":[\"c3\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-11-04T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-11-04T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-11-24T10:00:00.000Z\",\"stageId\":\"qualified\"}]},{\"id\":\"d4\",\"title\":\"Brand refresh and lookbook\",\"pipelineId\":\"sales\",\"stageId\":\"lead\",\"value\":9500,\"probability\":null,\"expectedClose\":\"2027-01-23\",\"owner\":\"jon\",\"companyId\":\"o4\",\"contactIds\":[\"c4\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-11-09T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-11-09T10:00:00.000Z\",\"stageId\":\"lead\"}]},{\"id\":\"d5\",\"title\":\"Driver app design system\",\"pipelineId\":\"sales\",\"stageId\":\"proposal\",\"value\":56000,\"probability\":60,\"expectedClose\":\"2026-12-26\",\"owner\":\"me\",\"companyId\":\"o5\",\"contactIds\":[\"c5\",\"c6\"],\"tags\":[],\"custom\":{\"cf1\":\"Event\"},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-10-20T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-10-20T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-11-07T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-11-24T10:00:00.000Z\",\"stageId\":\"proposal\"}]},{\"id\":\"d6\",\"title\":\"Intranet news hub\",\"pipelineId\":\"sales\",\"stageId\":\"lead\",\"value\":22000,\"probability\":null,\"expectedClose\":\"2027-02-07\",\"owner\":\"ada\",\"companyId\":\"o6\",\"contactIds\":[\"c7\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-11-14T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-11-14T10:00:00.000Z\",\"stageId\":\"lead\"}]},{\"id\":\"d7\",\"title\":\"Shop maintenance 2026\",\"pipelineId\":\"sales\",\"stageId\":\"won\",\"value\":7200,\"probability\":null,\"expectedClose\":\"2026-08-21\",\"owner\":\"jon\",\"companyId\":\"o2\",\"contactIds\":[\"c2\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-07-27T10:00:00.000Z\",\"updated\":\"2026-08-21T10:00:00.000Z\",\"closedAt\":\"2026-08-21T16:00:00.000Z\",\"history\":[{\"at\":\"2026-07-27T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-08-04T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-08-13T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-08-21T10:00:00.000Z\",\"stageId\":\"won\"}]},{\"id\":\"d8\",\"title\":\"Spring campaign landing pages\",\"pipelineId\":\"sales\",\"stageId\":\"won\",\"value\":14800,\"probability\":null,\"expectedClose\":\"2026-04-18\",\"owner\":\"me\",\"companyId\":\"o7\",\"contactIds\":[\"c8\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-03-09T10:00:00.000Z\",\"updated\":\"2026-04-18T10:00:00.000Z\",\"closedAt\":\"2026-04-18T16:00:00.000Z\",\"history\":[{\"at\":\"2026-03-09T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-03-22T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-04-05T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-04-18T10:00:00.000Z\",\"stageId\":\"won\"}]},{\"id\":\"d9\",\"title\":\"Accessibility retrofit\",\"pipelineId\":\"sales\",\"stageId\":\"won\",\"value\":31000,\"probability\":null,\"expectedClose\":\"2026-09-25\",\"owner\":\"ada\",\"companyId\":\"o3\",\"contactIds\":[\"c3\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-06-27T10:00:00.000Z\",\"updated\":\"2026-09-25T10:00:00.000Z\",\"closedAt\":\"2026-09-25T16:00:00.000Z\",\"history\":[{\"at\":\"2026-06-27T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-07-27T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-08-26T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-09-25T10:00:00.000Z\",\"stageId\":\"won\"}]},{\"id\":\"d10\",\"title\":\"Fleet tracking dashboard\",\"pipelineId\":\"sales\",\"stageId\":\"lost\",\"value\":42000,\"probability\":null,\"expectedClose\":\"2026-07-17\",\"owner\":\"me\",\"companyId\":\"o5\",\"contactIds\":[\"c5\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"Chose an in-house team\",\"created\":\"2026-05-08T10:00:00.000Z\",\"updated\":\"2026-07-17T10:00:00.000Z\",\"closedAt\":\"2026-07-17T16:00:00.000Z\",\"history\":[{\"at\":\"2026-05-08T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-05-31T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-06-24T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-07-17T10:00:00.000Z\",\"stageId\":\"lost\"}]},{\"id\":\"d11\",\"title\":\"Outdoor catalogue print\",\"pipelineId\":\"sales\",\"stageId\":\"lost\",\"value\":6000,\"probability\":null,\"expectedClose\":\"2026-03-19\",\"owner\":\"jon\",\"companyId\":\"o7\",\"contactIds\":[\"c8\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"Budget cut\",\"created\":\"2026-01-28T10:00:00.000Z\",\"updated\":\"2026-03-19T10:00:00.000Z\",\"closedAt\":\"2026-03-19T16:00:00.000Z\",\"history\":[{\"at\":\"2026-01-28T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-02-14T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-03-02T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-03-19T10:00:00.000Z\",\"stageId\":\"lost\"}]},{\"id\":\"d12\",\"title\":\"Concept workshop\",\"pipelineId\":\"sales\",\"stageId\":\"qualified\",\"value\":3500,\"probability\":null,\"expectedClose\":\"2026-12-06\",\"owner\":\"ada\",\"companyId\":\"\",\"contactIds\":[\"c12\"],\"tags\":[],\"custom\":{\"cf1\":\"Website\"},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-11-18T10:00:00.000Z\",\"updated\":\"2026-11-24T10:00:00.000Z\",\"closedAt\":\"\",\"history\":[{\"at\":\"2026-11-18T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-11-24T10:00:00.000Z\",\"stageId\":\"qualified\"}]},{\"id\":\"d13\",\"title\":\"Ferry app onboarding\",\"pipelineId\":\"sales\",\"stageId\":\"won\",\"value\":26000,\"probability\":null,\"expectedClose\":\"2026-11-04\",\"owner\":\"me\",\"companyId\":\"o1\",\"contactIds\":[\"c11\"],\"tags\":[],\"custom\":{},\"notes\":\"\",\"lostReason\":\"\",\"created\":\"2026-08-21T10:00:00.000Z\",\"updated\":\"2026-11-04T10:00:00.000Z\",\"closedAt\":\"2026-11-04T16:00:00.000Z\",\"history\":[{\"at\":\"2026-08-21T10:00:00.000Z\",\"stageId\":\"lead\"},{\"at\":\"2026-09-15T10:00:00.000Z\",\"stageId\":\"qualified\"},{\"at\":\"2026-10-10T10:00:00.000Z\",\"stageId\":\"proposal\"},{\"at\":\"2026-11-04T10:00:00.000Z\",\"stageId\":\"won\"}]}],\"activities\":[{\"id\":\"a1\",\"type\":\"call\",\"subject\":\"Discuss scope options with Ingrid\",\"body\":\"\",\"due\":\"2026-11-23T14:00\",\"done\":false,\"doneAt\":\"\",\"owner\":\"me\",\"contactId\":\"c1\",\"companyId\":\"\",\"dealId\":\"d1\",\"remindMinutes\":30,\"created\":\"2026-11-21T10:00:00.000Z\"},{\"id\":\"a2\",\"type\":\"meeting\",\"subject\":\"Negotiation meeting in Bergen (video)\",\"body\":\"\",\"due\":\"2026-11-27T10:30\",\"done\":false,\"doneAt\":\"\",\"owner\":\"me\",\"contactId\":\"c1\",\"companyId\":\"\",\"dealId\":\"d1\",\"remindMinutes\":30,\"created\":\"2026-11-22T10:00:00.000Z\"},{\"id\":\"a3\",\"type\":\"task\",\"subject\":\"Send revised proposal to Paul\",\"body\":\"\",\"due\":\"2026-11-24\",\"done\":false,\"doneAt\":\"\",\"owner\":\"jon\",\"contactId\":\"c2\",\"companyId\":\"\",\"dealId\":\"d2\",\"remindMinutes\":-1,\"created\":\"2026-11-22T10:00:00.000Z\"},{\"id\":\"a4\",\"type\":\"email\",\"subject\":\"Proposal sent\",\"body\":\"\",\"due\":\"2026-11-12\",\"done\":true,\"doneAt\":\"2026-11-12T11:00:00.000Z\",\"owner\":\"jon\",\"contactId\":\"c2\",\"companyId\":\"\",\"dealId\":\"d2\",\"remindMinutes\":-1,\"created\":\"2026-11-10T10:00:00.000Z\"},{\"id\":\"a5\",\"type\":\"meeting\",\"subject\":\"Discovery workshop with the marketing team\",\"body\":\"\",\"due\":\"2026-11-16T09:00\",\"done\":true,\"doneAt\":\"2026-11-16T09:00:00.000Z\",\"owner\":\"ada\",\"contactId\":\"c3\",\"companyId\":\"\",\"dealId\":\"d3\",\"remindMinutes\":30,\"created\":\"2026-11-14T10:00:00.000Z\"},{\"id\":\"a6\",\"type\":\"task\",\"subject\":\"Prepare audit plan\",\"body\":\"\",\"due\":\"2026-11-29\",\"done\":false,\"doneAt\":\"\",\"owner\":\"ada\",\"contactId\":\"c3\",\"companyId\":\"\",\"dealId\":\"d3\",\"remindMinutes\":-1,\"created\":\"2026-11-22T10:00:00.000Z\"},{\"id\":\"a7\",\"type\":\"call\",\"subject\":\"Intro call\",\"body\":\"\",\"due\":\"2026-11-20\",\"done\":true,\"doneAt\":\"2026-11-20T11:00:00.000Z\",\"owner\":\"jon\",\"contactId\":\"c4\",\"companyId\":\"\",\"dealId\":\"d4\",\"remindMinutes\":-1,\"created\":\"2026-11-18T10:00:00.000Z\"},{\"id\":\"a8\",\"type\":\"call\",\"subject\":\"Follow up on the design system proposal\",\"body\":\"\",\"due\":\"2026-11-21\",\"done\":false,\"doneAt\":\"\",\"owner\":\"me\",\"contactId\":\"c5\",\"companyId\":\"\",\"dealId\":\"d5\",\"remindMinutes\":-1,\"created\":\"2026-11-19T10:00:00.000Z\"},{\"id\":\"a9\",\"type\":\"note\",\"subject\":\"Budget approved for Q1\",\"body\":\"Sanne confirmed that the budget is approved; the board wants a pilot with one driver team first.\",\"due\":\"\",\"done\":true,\"doneAt\":\"2026-11-18T11:00:00.000Z\",\"owner\":\"me\",\"contactId\":\"c6\",\"companyId\":\"\",\"dealId\":\"d5\",\"remindMinutes\":-1,\"created\":\"2026-11-16T10:00:00.000Z\"},{\"id\":\"a10\",\"type\":\"task\",\"subject\":\"Check references for the intranet project\",\"body\":\"\",\"due\":\"2026-12-03\",\"done\":false,\"doneAt\":\"\",\"owner\":\"ada\",\"contactId\":\"c7\",\"companyId\":\"\",\"dealId\":\"d6\",\"remindMinutes\":-1,\"created\":\"2026-11-22T10:00:00.000Z\"},{\"id\":\"a11\",\"type\":\"call\",\"subject\":\"Yearly check-in with Elin\",\"body\":\"\",\"due\":\"2025-11-19\",\"done\":true,\"doneAt\":\"2025-11-19T11:00:00.000Z\",\"owner\":\"me\",\"contactId\":\"c8\",\"companyId\":\"\",\"dealId\":\"\",\"remindMinutes\":-1,\"created\":\"2025-11-17T10:00:00.000Z\"},{\"id\":\"a12\",\"type\":\"meeting\",\"subject\":\"Partner lunch\",\"body\":\"\",\"due\":\"2026-10-30\",\"done\":true,\"doneAt\":\"2026-10-30T11:00:00.000Z\",\"owner\":\"jon\",\"contactId\":\"c9\",\"companyId\":\"o8\",\"dealId\":\"\",\"remindMinutes\":-1,\"created\":\"2026-10-28T10:00:00.000Z\"},{\"id\":\"a13\",\"type\":\"task\",\"subject\":\"Book the concept workshop room\",\"body\":\"\",\"due\":\"2026-11-26\",\"done\":false,\"doneAt\":\"\",\"owner\":\"ada\",\"contactId\":\"c12\",\"companyId\":\"\",\"dealId\":\"d12\",\"remindMinutes\":-1,\"created\":\"2026-11-22T10:00:00.000Z\"},{\"id\":\"a14\",\"type\":\"call\",\"subject\":\"Kick-off call onboarding project\",\"body\":\"\",\"due\":\"2026-08-26\",\"done\":true,\"doneAt\":\"2026-08-26T11:00:00.000Z\",\"owner\":\"me\",\"contactId\":\"c11\",\"companyId\":\"\",\"dealId\":\"d13\",\"remindMinutes\":-1,\"created\":\"2026-08-24T10:00:00.000Z\"},{\"id\":\"a15\",\"type\":\"email\",\"subject\":\"Newsletter invitation\",\"body\":\"\",\"due\":\"2026-10-25\",\"done\":true,\"doneAt\":\"2026-10-25T11:00:00.000Z\",\"owner\":\"ada\",\"contactId\":\"c6\",\"companyId\":\"\",\"dealId\":\"\",\"remindMinutes\":-1,\"created\":\"2026-10-23T10:00:00.000Z\"}],\"products\":[{\"id\":\"p1\",\"name\":\"UX workshop (day)\",\"sku\":\"WS-DAY\",\"price\":1600,\"unit\":\"day\",\"vatRate\":null,\"description\":\"Facilitated workshop with preparation and summary\"},{\"id\":\"p2\",\"name\":\"Design sprint (week)\",\"sku\":\"DS-WEEK\",\"price\":7200,\"unit\":\"week\",\"vatRate\":null,\"description\":\"\"},{\"id\":\"p3\",\"name\":\"Front-end development\",\"sku\":\"DEV-H\",\"price\":105,\"unit\":\"hour\",\"vatRate\":null,\"description\":\"\"},{\"id\":\"p4\",\"name\":\"Hosting \u0026 maintenance\",\"sku\":\"OPS-M\",\"price\":600,\"unit\":\"month\",\"vatRate\":null,\"description\":\"\"},{\"id\":\"p5\",\"name\":\"Accessibility audit (WCAG 2.2)\",\"sku\":\"A11Y\",\"price\":4800,\"unit\":\"audit\",\"vatRate\":null,\"description\":\"\"}],\"quotes\":[{\"id\":\"q1\",\"number\":\"Q-2026-0001\",\"dealId\":\"d2\",\"contactId\":\"c2\",\"companyId\":\"o2\",\"date\":\"2026-11-24\",\"validUntil\":\"2026-12-24\",\"buyerCountry\":\"DE\",\"buyerVatId\":\"\",\"lines\":[{\"productId\":\"p1\",\"description\":\"UX workshop (day)\",\"qty\":2,\"unitPrice\":1600,\"discountPct\":0,\"vatRate\":null},{\"productId\":\"p3\",\"description\":\"Front-end development\",\"qty\":120,\"unitPrice\":105,\"discountPct\":5,\"vatRate\":null},{\"productId\":\"p4\",\"description\":\"Hosting \u0026 maintenance\",\"qty\":12,\"unitPrice\":600,\"discountPct\":10,\"vatRate\":null}],\"discountPct\":0,\"notes\":\"Payment 50 % on order, 50 % on launch.\",\"status\":\"sent\"},{\"id\":\"q2\",\"number\":\"Q-2026-0002\",\"dealId\":\"d5\",\"contactId\":\"c5\",\"companyId\":\"o5\",\"date\":\"2026-11-24\",\"validUntil\":\"2026-12-24\",\"buyerCountry\":\"NL\",\"buyerVatId\":\"NL859052841B01\",\"lines\":[{\"productId\":\"p2\",\"description\":\"Design sprint (week)\",\"qty\":4,\"unitPrice\":7200,\"discountPct\":0,\"vatRate\":null},{\"productId\":\"p3\",\"description\":\"Front-end development\",\"qty\":240,\"unitPrice\":105,\"discountPct\":0,\"vatRate\":null}],\"discountPct\":3,\"notes\":\"\",\"status\":\"draft\"}],\"emailTemplates\":[{\"id\":\"intro\",\"name\":\"First contact\",\"subject\":\"Nice to meet you, {{contact.firstName}}\",\"body\":\"Hi {{contact.firstName}},\\n\\nthanks for your time today. As promised, here is a short summary of what we talked about for {{company.name}}.\\n\\nBest regards,\\n{{me.name}}\"},{\"id\":\"follow-up\",\"name\":\"Follow-up on a proposal\",\"subject\":\"Your proposal for {{deal.title}}\",\"body\":\"Hi {{contact.firstName}},\\n\\nI wanted to check whether you had a chance to look at our proposal for {{deal.title}} ({{deal.value}}). Happy to answer any questions.\\n\\nBest regards,\\n{{me.name}}\"}],\"segments\":[{\"id\":\"sg1\",\"name\":\"Decision makers with marketing consent\",\"entity\":\"contacts\",\"match\":\"all\",\"rules\":[{\"field\":\"tags\",\"op\":\"has-tag\",\"value\":\"decision-maker\"},{\"field\":\"marketing\",\"op\":\"is\",\"value\":\"yes\"}]},{\"id\":\"sg2\",\"name\":\"Closing in the next 30 days\",\"entity\":\"deals\",\"match\":\"all\",\"rules\":[{\"field\":\"status\",\"op\":\"is\",\"value\":\"open\"},{\"field\":\"expectedClose\",\"op\":\"within-days\",\"value\":\"-30\"}]},{\"id\":\"sg3\",\"name\":\"Enterprise accounts\",\"entity\":\"companies\",\"match\":\"all\",\"rules\":[{\"field\":\"tags\",\"op\":\"has-tag\",\"value\":\"enterprise\"}]}],\"customFields\":[{\"id\":\"cf1\",\"name\":\"Lead source\",\"entity\":\"deals\",\"type\":\"select\",\"options\":[\"Referral\",\"Website\",\"Event\",\"Outbound\"]},{\"id\":\"cf2\",\"name\":\"Newsletter\",\"entity\":\"contacts\",\"type\":\"checkbox\",\"options\":[]}]}",
                    "asOf": "2026-11-24",
                    "months": 12
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RapportPipelineForecastResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "RapportPipelineForecastInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "deals": {
            "title": "Deals (CSV or Rapport file)",
            "description": "Needs a title and a value column; stage, status (open/won/lost), probability, expected close, created, closed and owner columns are used when present.",
            "type": "string",
            "maxLength": 5000000,
            "default": ""
          },
          "dealsFile": {
            "title": "File (optional)",
            "description": "Used instead of the pasted text when given. Upload as {filename, contentType?, contentBase64}. Max 9766 KiB. Accepts .csv,.json,text/csv,application/json.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "asOf": {
            "title": "Today is",
            "description": "Deals expected before this day count as overdue; the months start here. Empty = today.",
            "type": "string",
            "format": "date"
          },
          "months": {
            "title": "Months to forecast",
            "type": "number",
            "minimum": 1,
            "maximum": 24,
            "default": 6
          },
          "from": {
            "title": "Closed from (optional)",
            "description": "Win rate and sales cycle count deals closed in this window. Empty = 12 months up to “Today is”.",
            "type": "string",
            "format": "date"
          },
          "to": {
            "title": "Closed until (optional)",
            "type": "string",
            "format": "date"
          },
          "pipeline": {
            "title": "Pipeline (optional)",
            "description": "Name of one pipeline; empty = all.",
            "type": "string",
            "maxLength": 60,
            "default": ""
          }
        },
        "required": []
      },
      "RapportPipelineForecastResult": {
        "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",
            "required": [
              "open",
              "stages",
              "months",
              "winRate",
              "cycle"
            ],
            "properties": {
              "asOf": {
                "type": "string"
              },
              "from": {
                "type": "string"
              },
              "to": {
                "type": "string"
              },
              "currency": {
                "type": "string"
              },
              "pipelineId": {
                "type": "string"
              },
              "pipelineName": {
                "type": "string"
              },
              "source": {
                "type": "string"
              },
              "deals": {
                "type": "integer"
              },
              "open": {
                "type": "object"
              },
              "stages": {
                "type": "array"
              },
              "months": {
                "type": "array"
              },
              "overdue": {
                "type": "object"
              },
              "won": {
                "type": "object"
              },
              "lost": {
                "type": "object"
              },
              "winRate": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "winRateByValue": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "cycle": {
                "type": "object"
              },
              "owners": {
                "type": "array"
              },
              "activities": {
                "type": "array"
              },
              "warnings": {
                "type": "array"
              },
              "svgArtifact": {
                "type": "string"
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}