Skip to main content

openschichtplaner5-api

CI PyPI ghcr.io GitHub release License: MIT

The REST API behind OpenSchichtplaner5 — a pip-installable FastAPI service over libopenschichtplaner5 (sp5lib), serving shift-planning data from the original Schichtplaner5 FoxPro .DBF files or the SQLite/PostgreSQL mirror: auth/2FA with JWT sessions, employees, schedule, absences, reports/exports (incl. the original personnel table via GET /api/personnel-table and statistics over a free evaluation period), leave-entitlement administration (POST /api/leave-entitlements/forfeit, annual close), notifications (SSE), webhooks, iCal feeds and more. All Soll/Ist/demand figures are computed by the sp5lib calculation facade — the API carries no arithmetic of its own.

Import name: the distribution is openschichtplaner5-api, but the importable package is sp5api (mirroring libopenschichtplaner5sp5lib). It was extracted from the main app's backend/api/ with full git history.

📖 Detailed documentation lives in the project wiki — endpoint overview, auth & permissions, full environment reference, deployment guides. Architecture notes are in docs/architecture.md.

What's inside

Module Purpose
sp5api.main The FastAPI application (sp5api.main:app) — middlewares, health/metrics, SPA serving
sp5api.routers.* One router per domain: auth, employees, schedule, absences, reports, notifications, availability, overtime, qualification_matrix, recurring_shifts, ical, webhooks, admin, …
sp5api.dependencies Session store, JWT, rate limiting, logging, DB wiring
sp5api.schemas / sp5api.types Pydantic models / type aliases
sp5api.cache / sp5api.rate_limit_store Response caching, rate-limit event log

Permissions

Roles (Leser < Planer < Admin) gate read/write access; on top of that the granular 5USER rights of the original (WDUTIES, WABSENCES, WOVERTIMES, WNOTES, WDEVIATION, WCYCLEASS, WSWAPONLY, ADDEMPL, WPAST) are enforced per write route and exposed as a permissions object on GET /api/auth/me; WPAST=0 blocks every write with a date in the past, bulk routes included. The built-in Admin account and the last remaining administrator cannot be demoted or deleted. Full details: wiki → Auth & Permissions.

Installation

pip install openschichtplaner5-api

Prefer containers? See Docker below — the image runs standalone without a local Python environment.

Running

SP5_DB_PATH=/path/to/SP5/Daten python -m uvicorn sp5api.main:app --host 0.0.0.0 --port 8000

Key environment variables

Variable Default Purpose
SP5_DB_PATH (set it!) Directory with the Schichtplaner5 .DBF files
SP5_JWT_SECRET / SECRET_KEY random per process JWT signing secret — set it in production
SP5_BACKEND_DIR package parent dir Resource root (data/, api/data/, uploads), shared contract with sp5lib — set it in installed deployments
SP5_BACKUP_DIR <SP5_DB_PATH>/../backups Target directory for (auto-)backups; if it is not writable, the startup auto-backup is skipped with an info log
DB_BACKEND / DATABASE_URL dbf Switch to the PostgreSQL mirror (via sp5lib)

Everything else (SPA serving, CORS, rate limits, brute-force lockout, SMTP, logging, password policy …) is covered by the wiki → environment reference and the main app's .env.example.

Docker

Production-ready multi-stage image (slim runtime, non-root, HEALTHCHECK on /api/health, EXPOSE 8000; SP5_DB_PATH=/app/data, SP5_BACKEND_DIR=/app/backend):

# local operation: DBF dir + optional .env (SECRET_KEY!), see docker-compose.yml
SP5_DBF_DIR=/path/to/SP5/Daten docker compose up --build

Each release publishes a multi-arch image (amd64+arm64) to the GitHub Container Registry, so no local build is needed. Standalone — mount the DBF directory to /app/data and pass the environment via .env (at minimum SECRET_KEY, see Key environment variables):

echo "SECRET_KEY=$(openssl rand -hex 32)" > .env

# published image (no build required):
docker run -d --name sp5-api -p 8000:8000 \
  -v /path/to/SP5/Daten:/app/data \
  --env-file .env \
  ghcr.io/mschabhuettl/openschichtplaner5-api:latest   # or :1.6.0

# or build it locally instead:
docker build -t openschichtplaner5-api .
docker run -d --name sp5-api -p 8000:8000 \
  -v /path/to/SP5/Daten:/app/data \
  --env-file .env \
  openschichtplaner5-api

# health check
curl http://localhost:8000/api/health
# → {"status":"healthy","checks":{"db":"ok",...},"version":"1.2.0",...}

The build installs the library from PyPI by default (libopenschichtplaner5[postgres]==1.7.0). To build against a different state, override the build arg:

docker build --build-arg LIB_SOURCE=git+https://github.com/mschabhuettl/libopenschichtplaner5.git@main .

PostgreSQL mode (standalone)

With DB_BACKEND=postgresql and DATABASE_URL set, the API runs against the PostgreSQL mirror. The initial schema is created automatically by the ORM (sp5lib) on first connect — no Alembic tree is required. The Alembic migration tree lives in the main application repo (backend/alembic) and is intentionally not bundled with this package (a copy would drift), so the startup auto-migration is skipped with an info log when no alembic.ini is found. To apply future schema migrations in a standalone deployment, point SP5_BACKEND_DIR at a directory containing alembic.ini + alembic/ (e.g. a checkout of the main app's backend/).

Development

python3 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
ruff check .
pytest

To develop against a local clone of the library instead of the PyPI release:

pip install -e "../libopenschichtplaner5[postgres]"

data/ and api/data/ at the repo root are runtime-state seeds (skills, wishes, notification settings) used by the test suite — the same layout the main app keeps under backend/, resolved via SP5_BACKEND_DIR. tests/fixtures/ holds the DBF fixture database.

Releasing

Tag vX.Y.Z and push — the release workflow builds sdist+wheel and publishes to PyPI via Trusted Publishing (OIDC).

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openschichtplaner5_api-1.17.0.tar.gz (437.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openschichtplaner5_api-1.17.0-py3-none-any.whl (204.7 kB view details)

Uploaded Python 3

File details

Details for the file openschichtplaner5_api-1.17.0.tar.gz.

File metadata

  • Download URL: openschichtplaner5_api-1.17.0.tar.gz
  • Upload date:
  • Size: 437.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openschichtplaner5_api-1.17.0.tar.gz
Algorithm Hash digest
SHA256 6589709a5b3b427973a742fe546318d159c04ec4dbf47f57153976a4b79cd83a
MD5 126de0d18fd700d2a6f132b11f9a90a1
BLAKE2b-256 d9dd583496bc308ca23a8426df20202b97fa5cbe390e5ba092ab35ebdbe47c77

See more details on using hashes here.

Provenance

The following attestation bundles were made for openschichtplaner5_api-1.17.0.tar.gz:

Publisher: release.yml on mschabhuettl/openschichtplaner5-api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openschichtplaner5_api-1.17.0-py3-none-any.whl.

File metadata

File hashes

Hashes for openschichtplaner5_api-1.17.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c768bb61115687cfef7a9dca6f0541a3d02191f1ac0a00d065f87c0f755d3939
MD5 676b22cc36868d67583d20473245996e
BLAKE2b-256 ec6e66ac92455d41647c28c9c32b8da03d11c6a1c4c372c4222524f9f4ca4565

See more details on using hashes here.

Provenance

The following attestation bundles were made for openschichtplaner5_api-1.17.0-py3-none-any.whl:

Publisher: release.yml on mschabhuettl/openschichtplaner5-api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page