{"openapi":"3.1.0","info":{"title":"status.available.dk API","version":"1.0.0","description":"Status and SLA API for Available ApS. Uptime is measured for the service window only (weekdays 08:00-19:00 Europe/Copenhagen, excluding Danish public holidays). Two figures are always provided: raw uptime and SLA-adjusted uptime (after documented, manually attributed exclusions). Periods without measurement data are `unknown` and never count as uptime. Public endpoints are rate-limited to 60 requests/minute per IP and have open CORS for GET.","contact":{"name":"Available ApS","url":"https://available.dk"}},"servers":[{"url":"https://status.available.dk/api/v1"}],"security":[],"paths":{"/status":{"get":{"summary":"Current status for all services","responses":{"200":{"description":"Current status","headers":{"Cache-Control":{"schema":{"type":"string"},"description":"public, max-age=30"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusOverview"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/status/{service_key}":{"get":{"summary":"Current status for a single service","parameters":[{"name":"service_key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Status for the service incl. any open incident and active maintenance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceStatusDetail"}}}},"404":{"description":"Unknown service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/uptime":{"get":{"summary":"Uptime for a service in a period","description":"Returns both raw and SLA-adjusted uptime plus a daily series for charting. Periods older than roughly 13 months cannot be fully recomputed (heartbeat retention); there, the locked monthly reports are the authoritative source.","parameters":[{"name":"service","in":"query","required":true,"schema":{"type":"string"},"example":"mentions"},{"name":"period","in":"query","schema":{"type":"string","default":"30d"},"description":"30d, 90d, mtd or YYYY-MM"}],"responses":{"200":{"description":"Uptime figures","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Uptime"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/incidents":{"get":{"summary":"Incidents","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["open","resolved"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Incidents, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"incidents":{"type":"array","items":{"$ref":"#/components/schemas/Incident"}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/incidents/{id}":{"get":{"summary":"A single incident","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The incident","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Incident"}}}},"404":{"description":"Unknown incident","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/maintenance":{"get":{"summary":"Planned maintenance","parameters":[{"name":"upcoming","in":"query","schema":{"type":"boolean"},"description":"true = only active and upcoming windows"}],"responses":{"200":{"description":"Maintenance windows","content":{"application/json":{"schema":{"type":"object","properties":{"maintenance":{"type":"array","items":{"$ref":"#/components/schemas/Maintenance"}}}}}}}}}},"/health":{"get":{"summary":"Health of the status service itself","responses":{"200":{"description":"Database and probe are reachable (status ok/degraded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"503":{"description":"The database cannot be reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/reports":{"get":{"summary":"Monthly reports (authenticated)","security":[{"apiKey":[]}],"parameters":[{"name":"customer","in":"query","schema":{"type":"integer"},"description":"Customer id; may be omitted for customer-bound keys"},{"name":"period","in":"query","schema":{"type":"string"},"example":"2026-08"}],"responses":{"200":{"description":"Report(s) — latest version per period"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No report for the period","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/reports/{id}/export":{"get":{"summary":"Export a report (authenticated)","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","pdf"],"default":"csv"},"description":"CSV is semicolon-separated with Danish decimal comma (Excel-friendly)"}],"responses":{"200":{"description":"File as attachment"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/credits":{"get":{"summary":"Credit status and remaining exposure (authenticated)","security":[{"apiKey":[]}],"parameters":[{"name":"customer","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Credit overview incl. cap usage in a rolling 12-month period"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key issued by Available. Shown once at creation; can be revoked."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"StatusOverview":{"type":"object","properties":{"updated_at":{"type":["string","null"],"format":"date-time"},"overall":{"type":"string","enum":["operational","degraded","down","maintenance","unknown"]},"services":{"type":"array","items":{"$ref":"#/components/schemas/ServiceStatus"}}}},"ServiceStatus":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["operational","degraded","down","maintenance","unknown"]},"response_ms":{"type":["integer","null"]},"last_checked":{"type":["string","null"],"format":"date-time"}}},"ServiceStatusDetail":{"allOf":[{"$ref":"#/components/schemas/ServiceStatus"},{"type":"object","properties":{"open_incident":{"oneOf":[{"$ref":"#/components/schemas/Incident"},{"type":"null"}]},"active_maintenance":{"oneOf":[{"$ref":"#/components/schemas/Maintenance"},{"type":"null"}]}}}]},"Uptime":{"type":"object","properties":{"service":{"type":"string"},"period":{"type":"object","properties":{"label":{"type":"string"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"window_minutes":{"type":"number"},"downtime_minutes":{"type":"number","description":"Raw downtime within the service window incl. unknown"},"unknown_minutes":{"type":"number"},"excluded_minutes":{"type":"number"},"adjusted_downtime_minutes":{"type":"number"},"raw_uptime":{"type":["number","null"]},"adjusted_uptime":{"type":["number","null"]},"days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"window_minutes":{"type":"number"},"downtime_minutes":{"type":"number"},"unknown_minutes":{"type":"number"},"excluded_minutes":{"type":"number"},"raw_uptime":{"type":["number","null"]},"adjusted_uptime":{"type":["number","null"]}}}}}},"Incident":{"type":"object","properties":{"id":{"type":"integer"},"service":{"type":"string"},"status":{"type":"string","enum":["open","resolved"]},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"severity":{"type":"string","enum":["minor","major"]},"summary":{"type":["string","null"]},"attribution":{"type":"string","enum":["unattributed","available","third_party","maintenance","force_majeure","customer"]},"attribution_note":{"type":["string","null"]},"attribution_source_url":{"type":["string","null"]}}},"Maintenance":{"type":"object","properties":{"id":{"type":"integer"},"service":{"type":"string"},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"},"description":{"type":"string"},"notified_at":{"type":["string","null"],"format":"date-time"}}},"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded","error"]},"database":{"type":"boolean"},"probe_ok":{"type":"boolean"},"last_heartbeat":{"type":["string","null"],"format":"date-time"},"heartbeat_age_s":{"type":["integer","null"]}}}}}}