> For the complete documentation index, see [llms.txt](https://docs.statuspal.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.statuspal.io/next/platform/api-reference/services.md).

# Services

Manage services displayed on a status page

## GET /status\_pages/{subdomain}/services

> List services

```json
{"openapi":"3.1.0","info":{"title":"StatusPal Public API","version":"1"},"tags":[{"name":"Services","description":"Manage services displayed on a status page"}],"servers":[{"url":"https://next.statuspal.io/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Organization API key — issue one via the Rails console (management UI coming soon)"}},"schemas":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"slug":{"type":"string","description":"URL-safe identifier. May be supplied on create/update; if omitted, it is\nauto-generated from `name`. Uniqueness is enforced per status page.\n"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"],"description":"When `scope` is `containers`, the worst-case status across the containers this service is included in. When `scope` is `global`, the service's own status.\nRead-only here; change it with a notice update, from the operational dashboard, or by writing `status` / `container_statuses` on update.\n","readOnly":true},"order":{"type":"integer"},"scope":{"type":"string","readOnly":true,"enum":["global","containers"],"description":"Whether this service applies status-page-wide (`global`) or is scoped to specific containers (`containers`).\nDerived, not stored: a service with at least one container is `containers`, and a service with none is `global`. It is computed per response and cannot be written directly — set `containers` on create or update instead.\n"},"containers":{"type":"array","readOnly":true,"items":{"type":"string"},"description":"Slugs of the containers this service is included in. Empty when `scope` is `global`. Containers on the status page that are absent from this list are ones the service is explicitly excluded from.\n"},"container_statuses":{"type":"array","readOnly":true,"items":{"$ref":"#/components/schemas/ContainerStatusEntry"},"description":"Live status for each container this service is included in. Empty when `scope` is `global`. Containers the service is excluded from produce no entry.\n"},"created_at":{"type":"string","format":"date-time","readOnly":true},"updated_at":{"type":"string","format":"date-time","readOnly":true}}},"ContainerStatusEntry":{"type":"object","required":["container_slug","status"],"properties":{"container_slug":{"type":"string"},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"]}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"AccountPendingActivation":{"description":"The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/status_pages/{subdomain}/services":{"get":{"summary":"List services","operationId":"listServices","tags":["Services"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Service"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/AccountPendingActivation"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## POST /status\_pages/{subdomain}/services

> Create a service

```json
{"openapi":"3.1.0","info":{"title":"StatusPal Public API","version":"1"},"tags":[{"name":"Services","description":"Manage services displayed on a status page"}],"servers":[{"url":"https://next.statuspal.io/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Organization API key — issue one via the Rails console (management UI coming soon)"}},"schemas":{"ServiceCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":255},"slug":{"type":"string","description":"Optional URL-safe identifier. If omitted, it is auto-generated from `name`.\nIf a non-unique value is provided, a numeric suffix is appended (e.g. `api-1`).\n"},"description":{"type":["string","null"]},"containers":{"type":"array","items":{"type":"string"},"description":"The containers to include this service in, by slug. This is what determines the service scope: listing one or more containers creates a Container Service, while passing an explicit empty array creates a Global Service.\nOmitting the field defaults to every container on the status page, which keeps existing clients working unchanged. On a page with no containers that default is empty, so the service is Global. An unknown slug returns 422.\n"},"container_statuses":{"type":"array","items":{"$ref":"#/components/schemas/ContainerStatusEntry"},"description":"Optional initial status per container, for a Container Service.\nEvery `container_slug` must be one this service is included in — otherwise 422. Included containers not listed default to `ok`. Ignored for a Global Service; use `status` there instead.\n"},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"],"description":"Optional initial status for a Global Service. Defaults to `ok`.\nIgnored for a Container Service; use `container_statuses` there instead.\n"}}},"ContainerStatusEntry":{"type":"object","required":["container_slug","status"],"properties":{"container_slug":{"type":"string"},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"]}}},"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"slug":{"type":"string","description":"URL-safe identifier. May be supplied on create/update; if omitted, it is\nauto-generated from `name`. Uniqueness is enforced per status page.\n"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"],"description":"When `scope` is `containers`, the worst-case status across the containers this service is included in. When `scope` is `global`, the service's own status.\nRead-only here; change it with a notice update, from the operational dashboard, or by writing `status` / `container_statuses` on update.\n","readOnly":true},"order":{"type":"integer"},"scope":{"type":"string","readOnly":true,"enum":["global","containers"],"description":"Whether this service applies status-page-wide (`global`) or is scoped to specific containers (`containers`).\nDerived, not stored: a service with at least one container is `containers`, and a service with none is `global`. It is computed per response and cannot be written directly — set `containers` on create or update instead.\n"},"containers":{"type":"array","readOnly":true,"items":{"type":"string"},"description":"Slugs of the containers this service is included in. Empty when `scope` is `global`. Containers on the status page that are absent from this list are ones the service is explicitly excluded from.\n"},"container_statuses":{"type":"array","readOnly":true,"items":{"$ref":"#/components/schemas/ContainerStatusEntry"},"description":"Live status for each container this service is included in. Empty when `scope` is `global`. Containers the service is excluded from produce no entry.\n"},"created_at":{"type":"string","format":"date-time","readOnly":true},"updated_at":{"type":"string","format":"date-time","readOnly":true}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"AccountPendingActivation":{"description":"The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/status_pages/{subdomain}/services":{"post":{"summary":"Create a service","operationId":"createService","tags":["Services"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Service"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/AccountPendingActivation"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}}}}
```

## GET /status\_pages/{subdomain}/services/{service\_slug}

> Get a service

```json
{"openapi":"3.1.0","info":{"title":"StatusPal Public API","version":"1"},"tags":[{"name":"Services","description":"Manage services displayed on a status page"}],"servers":[{"url":"https://next.statuspal.io/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Organization API key — issue one via the Rails console (management UI coming soon)"}},"schemas":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"slug":{"type":"string","description":"URL-safe identifier. May be supplied on create/update; if omitted, it is\nauto-generated from `name`. Uniqueness is enforced per status page.\n"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"],"description":"When `scope` is `containers`, the worst-case status across the containers this service is included in. When `scope` is `global`, the service's own status.\nRead-only here; change it with a notice update, from the operational dashboard, or by writing `status` / `container_statuses` on update.\n","readOnly":true},"order":{"type":"integer"},"scope":{"type":"string","readOnly":true,"enum":["global","containers"],"description":"Whether this service applies status-page-wide (`global`) or is scoped to specific containers (`containers`).\nDerived, not stored: a service with at least one container is `containers`, and a service with none is `global`. It is computed per response and cannot be written directly — set `containers` on create or update instead.\n"},"containers":{"type":"array","readOnly":true,"items":{"type":"string"},"description":"Slugs of the containers this service is included in. Empty when `scope` is `global`. Containers on the status page that are absent from this list are ones the service is explicitly excluded from.\n"},"container_statuses":{"type":"array","readOnly":true,"items":{"$ref":"#/components/schemas/ContainerStatusEntry"},"description":"Live status for each container this service is included in. Empty when `scope` is `global`. Containers the service is excluded from produce no entry.\n"},"created_at":{"type":"string","format":"date-time","readOnly":true},"updated_at":{"type":"string","format":"date-time","readOnly":true}}},"ContainerStatusEntry":{"type":"object","required":["container_slug","status"],"properties":{"container_slug":{"type":"string"},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"]}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"AccountPendingActivation":{"description":"The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/status_pages/{subdomain}/services/{service_slug}":{"get":{"summary":"Get a service","operationId":"getService","tags":["Services"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Service"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/AccountPendingActivation"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## DELETE /status\_pages/{subdomain}/services/{service\_slug}

> Delete a service

```json
{"openapi":"3.1.0","info":{"title":"StatusPal Public API","version":"1"},"tags":[{"name":"Services","description":"Manage services displayed on a status page"}],"servers":[{"url":"https://next.statuspal.io/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Organization API key — issue one via the Rails console (management UI coming soon)"}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"AccountPendingActivation":{"description":"The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}},"paths":{"/status_pages/{subdomain}/services/{service_slug}":{"delete":{"summary":"Delete a service","operationId":"deleteService","tags":["Services"],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/AccountPendingActivation"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## PATCH /status\_pages/{subdomain}/services/{service\_slug}

> Update a service

```json
{"openapi":"3.1.0","info":{"title":"StatusPal Public API","version":"1"},"tags":[{"name":"Services","description":"Manage services displayed on a status page"}],"servers":[{"url":"https://next.statuspal.io/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Organization API key — issue one via the Rails console (management UI coming soon)"}},"schemas":{"ServiceUpdate":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"slug":{"type":"string","description":"Optional. If provided, replaces the URL slug (with uniqueness suffixing if needed)."},"description":{"type":["string","null"]},"order":{"type":"integer","description":"Position in the display list (1-indexed). Other services shift accordingly."},"containers":{"type":"array","items":{"type":"string"},"description":"Replaces the set of containers this service is included in, by slug, and with it the service scope. Passing an empty array makes the service Global; passing one or more containers makes it a Container Service. An unknown slug returns 422.\nStatus is preserved across a scope change, never reset. Switching Global to Container-scoped gives every newly-included container the service current status. Switching Container-scoped to Global discards the per-container configuration and keeps the worst-case of the discarded statuses — the status the public page was already showing.\n"},"container_statuses":{"type":"array","items":{"$ref":"#/components/schemas/ContainerStatusEntry"},"description":"Sets the live status of this service in the named containers — the API equivalent of the operational dashboard.\nEvery `container_slug` must be one this service is included in — otherwise 422. Containers not listed keep their current status. Rejected with 422 for a Global Service; use `status` there instead.\n"},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"],"description":"Sets the live status of a Global Service — the API equivalent of the operational dashboard.\nRejected with 422 for a Container Service; use `container_statuses` there instead.\n"}}},"ContainerStatusEntry":{"type":"object","required":["container_slug","status"],"properties":{"container_slug":{"type":"string"},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"]}}},"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","readOnly":true},"slug":{"type":"string","description":"URL-safe identifier. May be supplied on create/update; if omitted, it is\nauto-generated from `name`. Uniqueness is enforced per status page.\n"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["ok","minor","major","critical","maintenance"],"description":"When `scope` is `containers`, the worst-case status across the containers this service is included in. When `scope` is `global`, the service's own status.\nRead-only here; change it with a notice update, from the operational dashboard, or by writing `status` / `container_statuses` on update.\n","readOnly":true},"order":{"type":"integer"},"scope":{"type":"string","readOnly":true,"enum":["global","containers"],"description":"Whether this service applies status-page-wide (`global`) or is scoped to specific containers (`containers`).\nDerived, not stored: a service with at least one container is `containers`, and a service with none is `global`. It is computed per response and cannot be written directly — set `containers` on create or update instead.\n"},"containers":{"type":"array","readOnly":true,"items":{"type":"string"},"description":"Slugs of the containers this service is included in. Empty when `scope` is `global`. Containers on the status page that are absent from this list are ones the service is explicitly excluded from.\n"},"container_statuses":{"type":"array","readOnly":true,"items":{"$ref":"#/components/schemas/ContainerStatusEntry"},"description":"Live status for each container this service is included in. Empty when `scope` is `global`. Containers the service is excluded from produce no entry.\n"},"created_at":{"type":"string","format":"date-time","readOnly":true},"updated_at":{"type":"string","format":"date-time","readOnly":true}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"AccountPendingActivation":{"description":"The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnprocessableEntity":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/status_pages/{subdomain}/services/{service_slug}":{"patch":{"summary":"Update a service","operationId":"updateService","tags":["Services"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUpdate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Service"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/AccountPendingActivation"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}}}}}
```
