{
  "openapi": "3.1.0",
  "info": {
    "title": "We Love SaaS Benchmarks — public API",
    "version": "1.0.0",
    "summary": "Read-only access to published benchmark results for European SaaS and AI companies.",
    "description": "Published results only, as fixed releases. No figure is ever returned for a group of fewer than eight companies. One filter at a time; combinations of filters are available to contributors after signing in. No authentication. Limit: 60 requests a minute. Every response carries a citation string.",
    "contact": {
      "name": "We Love SaaS",
      "url": "https://welovesaas.io",
      "email": "info@welovesaas.io"
    },
    "license": {
      "name": "Creative Commons Attribution 4.0 International (CC BY 4.0)",
      "url": "https://creativecommons.org/licenses/by/4.0/"
    }
  },
  "servers": [
    {
      "url": "https://benchmarks.welovesaas.io/api/v1"
    }
  ],
  "paths": {
    "/surveys": {
      "get": {
        "operationId": "listSurveys",
        "summary": "List surveys and their rounds",
        "responses": {
          "200": {
            "description": "Every survey with an open or published round.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SurveyList"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (60 a minute per caller).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/surveys/{slug}": {
      "get": {
        "operationId": "getSurvey",
        "summary": "Survey metadata: rounds, questions and definitions",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The survey, its rounds, and what each round asks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Survey"
                }
              }
            }
          },
          "404": {
            "description": "No such survey.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (60 a minute per caller).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/results/{waveSlug}": {
      "get": {
        "operationId": "queryBenchmark",
        "summary": "Published results for one round",
        "description": "Returns `status: \"published\"` with the figures, or `status: \"not_published\"` with an empty list while the round has no public results.",
        "parameters": [
          {
            "name": "waveSlug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Show one HQ country group only. One filter at a time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "arr_band",
            "in": "query",
            "required": false,
            "description": "Show one ARR band group only. One filter at a time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "headcount",
            "in": "query",
            "required": false,
            "description": "Show one Headcount group only. One filter at a time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "engineering_fte",
            "in": "query",
            "required": false,
            "description": "Show one Engineering FTE group only. One filter at a time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "funding_type",
            "in": "query",
            "required": false,
            "description": "Show one Funding group only. One filter at a time.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Published results, or a not-yet-published notice.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Results"
                }
              }
            }
          },
          "400": {
            "description": "More than one filter, or an invalid filter value.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such round.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (60 a minute per caller).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SurveyList": {
        "type": "object",
        "required": [
          "citation",
          "surveys"
        ],
        "properties": {
          "citation": {
            "type": "string",
            "description": "How to cite this response, e.g. \"We Love SaaS Benchmarks, <survey name> <year>, n=<companies>.\""
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "licence": {
            "type": "string"
          },
          "surveys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SurveySummary"
            }
          }
        }
      },
      "SurveySummary": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "rounds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Round"
            }
          }
        }
      },
      "Round": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "collecting_answers",
              "closed"
            ]
          },
          "collected_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "collected_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "results_published": {
            "type": "boolean"
          },
          "results_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Survey": {
        "type": "object",
        "required": [
          "citation",
          "slug",
          "title"
        ],
        "properties": {
          "citation": {
            "type": "string",
            "description": "How to cite this response, e.g. \"We Love SaaS Benchmarks, <survey name> <year>, n=<companies>.\""
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "region": {
            "type": "string"
          },
          "rounds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Round"
            }
          }
        }
      },
      "Results": {
        "type": "object",
        "required": [
          "status",
          "citation",
          "results"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "published",
              "not_published"
            ]
          },
          "citation": {
            "type": "string",
            "description": "How to cite this response, e.g. \"We Love SaaS Benchmarks, <survey name> <year>, n=<companies>.\""
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "survey": {
            "type": "string"
          },
          "round": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "companies": {
            "type": "integer",
            "description": "Companies in the round (n)."
          },
          "minimum_group_size": {
            "type": "integer"
          },
          "published_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_updated": {
            "type": "string",
            "format": "date-time"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultRow"
            }
          }
        }
      },
      "ResultRow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable id; also the anchor on the results page."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "question_key": {
            "type": "string"
          },
          "question": {
            "type": "string"
          },
          "metric": {
            "type": [
              "string",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "group_by": {
            "type": "string"
          },
          "group": {
            "type": "string"
          },
          "group_label": {
            "type": "string"
          },
          "option": {
            "type": [
              "string",
              "null"
            ]
          },
          "companies": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lower_quartile": {
            "type": [
              "number",
              "null"
            ]
          },
          "median": {
            "type": [
              "number",
              "null"
            ]
          },
          "upper_quartile": {
            "type": [
              "number",
              "null"
            ]
          },
          "share_percent": {
            "type": [
              "number",
              "null"
            ]
          },
          "withheld": {
            "type": "boolean",
            "description": "True when the group has fewer than eight companies: no figure is given."
          }
        }
      }
    }
  }
}