{"openapi":"3.1.0","info":{"title":"GET /api/v1/firm/benchmarks","version":"1.0.0","description":"Every client's peer percentiles (firm table)"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/firm/benchmarks":{"get":{"tags":["benchmarks"],"summary":"Every client's peer percentiles (firm table)","description":"One row per business the caller can see with its percentile per metric in the first cohort that has 20 or more contributors. Members of an advisory firm (and DayZero staff) only.","operationId":"get_firm_benchmarks","parameters":[{"name":"month","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"YYYY-MM; default the last complete month","title":"Month"},"description":"YYYY-MM; default the last complete month"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_FirmBenchmarksResponse_"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: due_date: Input should be a valid date","errors":{"due_date":"Input should be a valid date"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"}}}}},"x-fastapi-operation-id":"get_firm_benchmarks_api_v1_firm_benchmarks_get"}}},"components":{"schemas":{"CohortRef":{"properties":{"key":{"type":"string","title":"Key","description":"industry, revenue_band or channel_mix"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value","description":"The business's value for the key; null when unknown"},"description":{"type":"string","title":"Description","description":"Plain-language label for the cell"},"n":{"type":"integer","title":"N","description":"Contributors in the cell this month (0 when unknown)"},"qualifies":{"type":"boolean","title":"Qualifies","description":"n meets the minimum cohort size"}},"additionalProperties":false,"type":"object","required":["key","value","description","n","qualifies"],"title":"CohortRef","description":"One cohort cell the business belongs to and whether it can be shown."},"FirmBenchmarkCell":{"properties":{"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display"},"percentile":{"$ref":"#/components/schemas/PercentileValue"}},"additionalProperties":false,"type":"object","required":["key","percentile"],"title":"FirmBenchmarkCell","description":"One client's percentile for one metric."},"FirmBenchmarkRow":{"properties":{"business_id":{"type":"string","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"enabled":{"type":"boolean","title":"Enabled"},"contributing":{"type":"boolean","title":"Contributing"},"cohort":{"anyOf":[{"$ref":"#/components/schemas/CohortRef"},{"type":"null"}]},"metrics":{"items":{"$ref":"#/components/schemas/FirmBenchmarkCell"},"type":"array","title":"Metrics"}},"additionalProperties":false,"type":"object","required":["business_id","business_name","enabled","contributing"],"title":"FirmBenchmarkRow","description":"One client in the firm table."},"FirmBenchmarksResponse":{"properties":{"month":{"type":"string","title":"Month"},"metric_keys":{"items":{"type":"string"},"type":"array","title":"Metric Keys"},"metric_labels":{"additionalProperties":{"type":"string"},"type":"object","title":"Metric Labels"},"items":{"items":{"$ref":"#/components/schemas/FirmBenchmarkRow"},"type":"array","title":"Items"}},"additionalProperties":false,"type":"object","required":["month"],"title":"FirmBenchmarksResponse","description":"``GET /firm/benchmarks``: every client's percentiles in one table."},"PercentileValue":{"properties":{"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"cohort_too_small, no_cohort, no_value or opted_out when null"}},"additionalProperties":false,"type":"object","title":"PercentileValue","description":"Where the business sits in its cohort for one metric, 0-100."},"SuccessEnvelope_FirmBenchmarksResponse_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/FirmBenchmarksResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[FirmBenchmarksResponse]"},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}