vigotime / developers

Vigotime Planner API

Integriere die Dienstplanung headless: Du schickst einen self-contained Payload (Mitarbeiter, Schichten, Regeln, Abwesenheiten) — und bekommst einen fertigen Dienstplan zurück. Kein Wissen über die interne Datenhaltung nötig, kein Zwang zu unserer Oberfläche.

REST / JSON Stateless Async Job-Modell API-Key oder Firebase Tarif-Limits

Überblick

Drei Endpoints, asynchron: absenden → Status pollen → Ergebnis holen.

POST /api/v1/solve — Job absenden
GET /api/v1/solve/{job_id} — Status
GET /api/v1/solve/{job_id}/result — Ergebnis

Self-contained

Alle Entitäten reisen im Request mit — keine Vor-Synchronisation, kein Datenbankzugriff bei uns.

Asynchron

Der Solver läuft im Hintergrund; du pollst den Job-Status und holst das Ergebnis.

Pro Paket limitiert

Problemgröße, Solver-Zeit, Rate-Limit und Parallelität sind je Tarif konfiguriert.

Basis-URLs

UmgebungBasis-URL
Productionhttps://planner.vigotime.com
Staginghttps://staging-planner.vigotime.com
Lokal (dev)http://localhost:8000

Authentifizierung

Einer der beiden Header genügt. Der API-Key bestimmt zugleich den Tarif und damit die Limits.

# API-Key (für Drittanbieter)
X-API-Key: <dein-api-key>

# oder Firebase-Bearer (interne Nutzung)
Authorization: Bearer <firebase-id-token>

Quickstart

Job absenden, Status pollen, Ergebnis holen — mit curl und jq.

BASE=https://staging-planner.vigotime.com
KEY=<dein-api-key>

# 1) Job absenden
JOB=$(curl -s -X POST "$BASE/api/v1/solve" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{
    "start_date": "2026-07-01",
    "end_date": "2026-07-07",
    "department": { "id": "d1", "name": "Pflege Station 1" },
    "employees": [
      { "id": "e1", "primaryDepartmentId": "d1", "contractHoursPerWeek": 40, "qualificationIds": ["q_exam"] }
    ],
    "shifts": [
      { "id": "s_frueh", "departmentId": "d1", "name": "Frühdienst",
        "startTime": "06:00", "endTime": "14:00", "shiftType": "early", "minStaff": 1 }
    ],
    "config": { "timeout_seconds": 30 }
  }' | jq -r .job_id)

# 2) Status pollen
curl -s "$BASE/api/v1/solve/$JOB" -H "X-API-Key: $KEY" | jq .status

# 3) Ergebnis holen
curl -s "$BASE/api/v1/solve/$JOB/result" -H "X-API-Key: $KEY" | jq .

Beispiel-Antwort des Ergebnisses:

{
  "success": true,
  "status": "optimal",
  "assignments": [
    { "employee_id": "e1", "shift_id": "s_frueh", "date": "2026-07-01" }
  ],
  "unassigned_shifts": [],
  "execution_time_seconds": 0.8
}

Konzepte

Payload-Form

Mitarbeiter, Schichten und Abteilung werden in der Firestore-Dokument-Form (camelCase) übergeben — dieselbe Form, die unser System intern nutzt. Pflichtfeld je Entität ist id; alles Weitere hat sinnvolle Defaults. Daten-Maps wie wishes, vacations oder sick_leaves haben die Form { "employeeId": ["2026-07-03", …] }.

Asynchrones Job-Modell

POST /solve liefert sofort 202 mit einer job_id und dem aufgelösten tier. Pollen über GET /solve/{job_id} bis status = completed (oder failed); dann /result abrufen.

Status-Werte

Job-StatusSolver-Status (im Ergebnis)
pending, running, completed, failed optimal, feasible, infeasible, unknown, model_invalid

Limits pro Tarif

Der API-Key wird einem Tarif zugeordnet; dieser bestimmt die Grenzen. Die Solver-Laufzeit wird serverseitig hart gedeckelt (min(config.timeout_seconds, Tarif-Cap)).

Tarifmax. Problemgröße
(MA × Tage × Schichten)
Solver-ZeitReq/minparallel
free84015 s101
standard15 50030 s303
pro99 20060 s608
enterprise120 s20
Überschreitet ein Payload die Problemgröße, antwortet die API mit 422 bevor der Solver startet. Bei Überschreiten des Rate-Limits kommt 429 mit Retry-After.

Fehler

CodeBedeutung
401Keine/ungültige Authentifizierung
422Problemgröße über dem Tarif-Limit
429Rate-Limit des Tarifs überschritten
404Job nicht gefunden
400Ergebnis abgerufen, obwohl Job noch nicht fertig

Fehlerformat: { "detail": "…" } bzw. { "error": { "code", "message" } }.

Vollständige API-Referenz

Alle Felder, Schemas und Beispiele interaktiv: