{"openapi":"3.1.0","info":{"title":"GET /api/v1/public/dashboards/{token}","version":"1.0.0","description":"Public dashboard viewer (unauthenticated)"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/public/dashboards/{token}":{"get":{"tags":["dashboards-public"],"summary":"Public dashboard viewer (unauthenticated)","description":"Resolve a share token to a read-only, redacted dashboard. Returns 404 for unknown, expired, revoked, or deleted targets — the four are indistinguishable on purpose. Rate-limited per IP and cached for 60 seconds; the payload reflects each widget's stored snapshot, so it is exactly as fresh as the dashboard itself.","operationId":"fetch_public_dashboard_api_v1_public_dashboards__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_PublicDashboardResponse_"}}}},"404":{"description":"Not Found - Resource does not exist","content":{"application/json":{"example":{"detail":"Resource not found"}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","content":{"application/json":{"example":{"detail":"Rate limit exceeded"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ChartWidget":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","maxLength":200,"title":"Title"},"layout":{"$ref":"#/components/schemas/WidgetLayout"},"source":{"anyOf":[{"$ref":"#/components/schemas/WidgetSource"},{"type":"null"}]},"snapshot":{"$ref":"#/components/schemas/WidgetSnapshot"},"last_refresh_error":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Last Refresh Error"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"},"widget_type":{"type":"string","const":"chart","title":"Widget Type","default":"chart"}},"additionalProperties":false,"type":"object","required":["id","title","snapshot"],"title":"ChartWidget"},"GaugeWidget":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","maxLength":200,"title":"Title"},"layout":{"$ref":"#/components/schemas/WidgetLayout"},"source":{"anyOf":[{"$ref":"#/components/schemas/WidgetSource"},{"type":"null"}]},"snapshot":{"$ref":"#/components/schemas/WidgetSnapshot"},"last_refresh_error":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Last Refresh Error"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"},"widget_type":{"type":"string","const":"gauge","title":"Widget Type","default":"gauge"}},"additionalProperties":false,"type":"object","required":["id","title","snapshot"],"title":"GaugeWidget","description":"A linear meter showing a single value against a min/max range."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MetricWidget":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","maxLength":200,"title":"Title"},"layout":{"$ref":"#/components/schemas/WidgetLayout"},"source":{"anyOf":[{"$ref":"#/components/schemas/WidgetSource"},{"type":"null"}]},"snapshot":{"$ref":"#/components/schemas/WidgetSnapshot"},"last_refresh_error":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Last Refresh Error"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"},"widget_type":{"type":"string","const":"metric","title":"Widget Type","default":"metric"}},"additionalProperties":false,"type":"object","required":["id","title","snapshot"],"title":"MetricWidget","description":"A single headline number (e.g. cash on hand, total AR)."},"PublicDashboardResponse":{"properties":{"dashboard":{"$ref":"#/components/schemas/PublicDashboardSpec"},"cached":{"type":"boolean","title":"Cached","default":false}},"additionalProperties":false,"type":"object","required":["dashboard"],"title":"PublicDashboardResponse","description":"Public, redacted DashboardSpec served via the unauth share route."},"PublicDashboardSpec":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"widgets":{"items":{"oneOf":[{"$ref":"#/components/schemas/ChartWidget"},{"$ref":"#/components/schemas/TableWidget"},{"$ref":"#/components/schemas/MetricWidget"},{"$ref":"#/components/schemas/GaugeWidget"},{"$ref":"#/components/schemas/TimelineWidget"},{"$ref":"#/components/schemas/TextWidget"}],"discriminator":{"propertyName":"widget_type","mapping":{"chart":"#/components/schemas/ChartWidget","gauge":"#/components/schemas/GaugeWidget","metric":"#/components/schemas/MetricWidget","table":"#/components/schemas/TableWidget","text":"#/components/schemas/TextWidget","timeline":"#/components/schemas/TimelineWidget"}}},"type":"array","maxItems":24,"title":"Widgets"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"}},"type":"object","required":["id","title","created_at"],"title":"PublicDashboardSpec","description":"Redacted dashboard payload for unauthenticated share viewers.\n\nOmits assignment/creator identifiers and widget sources so tenant data\nand internal tool parameters never leak to the public route.\n``extra=\"ignore\"`` tolerates stale Redis cache entries."},"SuccessEnvelope_PublicDashboardResponse_":{"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/PublicDashboardResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[PublicDashboardResponse]"},"TableWidget":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","maxLength":200,"title":"Title"},"layout":{"$ref":"#/components/schemas/WidgetLayout"},"source":{"anyOf":[{"$ref":"#/components/schemas/WidgetSource"},{"type":"null"}]},"snapshot":{"$ref":"#/components/schemas/WidgetSnapshot"},"last_refresh_error":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Last Refresh Error"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"},"widget_type":{"type":"string","const":"table","title":"Widget Type","default":"table"}},"additionalProperties":false,"type":"object","required":["id","title","snapshot"],"title":"TableWidget"},"TextWidget":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","maxLength":200,"title":"Title"},"layout":{"$ref":"#/components/schemas/WidgetLayout"},"source":{"anyOf":[{"$ref":"#/components/schemas/WidgetSource"},{"type":"null"}]},"snapshot":{"anyOf":[{"$ref":"#/components/schemas/WidgetSnapshot"},{"type":"null"}]},"last_refresh_error":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Last Refresh Error"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"},"widget_type":{"type":"string","const":"text","title":"Widget Type","default":"text"},"body":{"type":"string","maxLength":8000,"title":"Body","default":""}},"additionalProperties":false,"type":"object","required":["id","title"],"title":"TextWidget","description":"Free-form markdown note; has no data snapshot requirement."},"TimelineWidget":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","maxLength":200,"title":"Title"},"layout":{"$ref":"#/components/schemas/WidgetLayout"},"source":{"anyOf":[{"$ref":"#/components/schemas/WidgetSource"},{"type":"null"}]},"snapshot":{"$ref":"#/components/schemas/WidgetSnapshot"},"last_refresh_error":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Last Refresh Error"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"},"widget_type":{"type":"string","const":"timeline","title":"Widget Type","default":"timeline"}},"additionalProperties":false,"type":"object","required":["id","title","snapshot"],"title":"TimelineWidget","description":"Chronological event list with status indicators."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WidgetLayout":{"properties":{"x":{"type":"integer","maximum":11.0,"minimum":0.0,"title":"X","default":0},"y":{"type":"integer","maximum":999.0,"minimum":0.0,"title":"Y","default":0},"w":{"type":"integer","maximum":12.0,"minimum":1.0,"title":"W","default":6},"h":{"type":"integer","maximum":12.0,"minimum":1.0,"title":"H","default":4}},"additionalProperties":false,"type":"object","title":"WidgetLayout","description":"Position on a 12-column grid."},"WidgetSnapshot":{"properties":{"data":{"additionalProperties":true,"type":"object","title":"Data"},"ui_hint":{"type":"string","maxLength":60,"minLength":1,"title":"Ui Hint"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"}},"type":"object","required":["data","ui_hint","captured_at"],"title":"WidgetSnapshot","description":"The captured chat payload the widget renders from.\n\n``data`` is intentionally open-shaped (chat payloads vary per tool), so no\n``extra=\"forbid\"`` here — only the size guard applies."},"WidgetSource":{"properties":{"tool_name":{"type":"string","maxLength":120,"minLength":1,"title":"Tool Name"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"refreshable":{"type":"boolean","title":"Refreshable","default":true},"scope":{"type":"string","enum":["business","firm"],"title":"Scope","default":"business"},"firm_business_ids":{"items":{"type":"string"},"type":"array","maxItems":500,"title":"Firm Business Ids"}},"additionalProperties":false,"type":"object","required":["tool_name"],"title":"WidgetSource","description":"The READ tool invocation that can re-produce this widget's data.\n\n``scope`` records the breadth the widget was *created* at. A\n``\"business\"`` widget resolves against the dashboard's own business; a\n``\"firm\"`` widget aggregates across ``firm_business_ids`` — the client\nbusinesses the creator could reach at capture time.\n\n``firm_business_ids`` is a security input, not a display field: at\nview/refresh time it is intersected against the *current* viewer's firm\naccess so a widget can never keep surfacing a client the viewer has since\nlost access to. It is deliberately stored on the widget (rather than\nre-derived) so a shrinking firm roster narrows the widget instead of\nsilently re-broadening it."}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}