---
title: "Schedules (Bereitschaftspläne)"
description: "Incident-Management-Bereitschaftspläne auflisten und erstellen: die Rotation, die festlegt, wer für ein Team wann Bereitschaft hat."
---

`GET /api/im/schedules` · `POST /api/im/schedules`

Ein **Schedule** (Bereitschaftsplan) gehört zu genau einem Team und definiert dessen On-Call-Rotation: eine oder mehrere Schichten von Usern, die jeweils `daily`, `weekly` oder `custom` rotieren, optional eingeschränkt auf bestimmte Tageszeiten. Ein Hintergrund-Worker materialisiert die Rotation etwa 90 Tage im Voraus zu konkreten Schichten (`im_schedule_shift`), genau die, die [Wer hat Bereitschaft](./on-call) und die Eskalations-Engine zur Laufzeit tatsächlich lesen. Dieser Endpunkt verwaltet die *Definition* der Rotation, nicht direkt die materialisierten Schichten.

## Authentifizierung

Erfordert den Basis-IM-Zugriff, den jeder Endpunkt dieser API benötigt (eine IM-berechtigte Rolle, oder einen organisationsweiten API-Token; Incident Management muss für die Organisation aktiviert sein). Das Auflisten steht jeder IM-berechtigten Rolle offen. Das **Erstellen** eines Schedules erfordert zusätzlich die Schreib-Hürde: Deine Rolle muss `admin` sein, oder du musst Team-Admin des Schedule-Teams sein. Ein organisationsweiter API-Token erfüllt die Organisations-Admin-Hürde.

## Schedules auflisten

`GET /api/im/schedules`

Liefert jeden Schedule deiner Organisation, mit dem Namen des zugehörigen Teams.

### Beispiel (cURL)

```bash
curl -X GET "$BASE_URL/api/im/schedules" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
```

### Antwort (Response)

`200 OK`: ein Array, sortiert nach Name.

```json
[
  {
    "id": 7,
    "organizationId": 1,
    "teamId": 3,
    "teamName": "Platform Team",
    "name": "Primary On-Call",
    "timezone": "Europe/Berlin",
    "rotation": [
      {
        "users": ["u_abc123", "u_def456"],
        "type": "weekly",
        "handoverTime": "09:00",
        "startDate": "2026-01-05"
      }
    ],
    "createdAt": "2026-01-01T00:00:00.000Z",
    "updatedAt": "2026-01-01T00:00:00.000Z"
  }
]
```

## Schedule erstellen

`POST /api/im/schedules`

### Request Body

| Feld | Typ | Erforderlich | Beschreibung |
|-------|------|----------|--------------|
| `teamId` | number | Ja | Das Team, dem der Schedule gehört. Muss zu deiner Organisation gehören. |
| `name` | string | Ja | Name des Schedules, bis zu 120 Zeichen. |
| `timezone` | string | Ja | IANA-Zeitzone (z. B. `Europe/Berlin`). Jede Übergabe und tageszeitliche Einschränkung wird in dieser Zone ausgewertet, auch über die Sommerzeit hinweg. |
| `rotation` | array | Nein | Rotationsschichten, bis zu 20. Standard ist ein leeres Array (ein Schedule ohne Rotation alarmiert niemanden, bis Schichten hinzugefügt werden). Jede Schicht: `{ users: string[], type: 'daily' \| 'weekly' \| 'custom', intervalDays?: number, handoverTime: "HH:mm", startDate: "yyyy-MM-dd", restrictions?: Array<{ dow: number[], from: "HH:mm", to: "HH:mm" }> }`. `intervalDays` ist erforderlich (und nur relevant), wenn `type` `custom` ist. `dow` in `restrictions` nutzt ISO-Wochentage (1 = Montag .. 7 = Sonntag), bis zu 30 Restriktionen pro Schicht. Bis zu 200 User pro Schicht. |

Jede User-ID in `rotation[].users` muss zu deiner Organisation gehören. Eine Rotation, die einen organisationsfremden User nennt, wird strikt abgelehnt statt stillschweigend verworfen, da `im_schedule_shift.user_id` selbst keine Organisationsgrenze kennt.

### Beispiel (cURL)

```bash
curl -X POST "$BASE_URL/api/im/schedules" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "teamId": 3,
    "name": "Primary On-Call",
    "timezone": "Europe/Berlin",
    "rotation": [
      {
        "users": ["u_abc123", "u_def456"],
        "type": "weekly",
        "handoverTime": "09:00",
        "startDate": "2026-01-05"
      }
    ]
  }'
```

### Antwort (Response)

`200 OK`: die neu erstellte Schedule-Zeile (gleiche Form wie oben in der Liste, ohne `teamName`).

## Häufige Fehler

- `401 Unauthorized` wenn du nicht authentifiziert bist
- `403 Forbidden` (`imAccessDenied`) bei Verwendung eines kunden-gescopten Tokens, oder wenn deine Session keine IM-berechtigte Rolle hat
- `403 Forbidden` (`imNotEnabled`) wenn Incident Management für die Organisation nicht aktiviert ist
- `403 Forbidden` (`imTeamWriteDenied`) (nur beim Erstellen) wenn deine Rolle nicht `admin` ist und du kein Team-Admin von `teamId` bist
- `404 Not Found` (`imTeamNotFound`) (nur beim Erstellen) wenn `teamId` nicht existiert oder zu einer anderen Organisation gehört
- `400 Bad Request` (`invalidRequestBody`) (nur beim Erstellen) wenn `name`, `timezone` oder ein Rotationsschicht-Feld fehlt oder fehlerhaft ist (siehe Feldbeschreibungen oben), oder eine Schicht-/Restriktions-/User-Listen-Grenze überschritten wird
