Skip to content

Public API v1 & ausgehende Webhooks (Modul int.api)

Plan: plan-modularisierung §10. Die Public API nutzt dieselben Domain-Funktionen wie Web und Agent; Mandant, Rolle und Modul-Freischaltung werden serverseitig erzwungen.

Authentifizierung

  • Schlüssel anlegen: Einstellungen › Integrationen › API (Admin), oder POST /api/company/api-keys { name, scopes[] }. Der Klartext erscheint nur einmal.
  • Format w7_live_<prefix>_<secret>; gespeichert wird Prefix + SHA-256-Hash (Pepper API_KEY_PEPPER, Fallback NEXTAUTH_SECRET).
  • Header: Authorization: Bearer w7_live_…
  • Scopes: <modul>:read | <modul>:write (write schließt read ein). Scopes müssen innerhalb der gebuchten Module liegen; fällt ein Modul weg, antwortet der Endpunkt mit 403 module_disabled, der Schlüssel bleibt.
  • Rate-Limit: 600 Anfragen/Minute je Schlüssel (API_KEY_RATE_LIMIT_PER_MINUTE), 429 mit Retry-After.
  • Widerrufen: DELETE /api/company/api-keys/{id}.

Endpunkte

Basis /api/v1. Listen: ?limit=50&offset=0&q=…, Antwort { data: [...], pagination: { limit, offset, total, hasMore } }.

MethodePfadModul / ScopeHinweise
GET/mecore:readMandant, Schlüssel, Paket, aktive/inaktive Bereiche
GET/projectscore:readFilter status, kontakt_id
GET/projects/{id}core:readid oder Projektnummer
GET/kontaktecore:readFilter kind, status
GET/rapports, /rapports/{id}rapport:readFilter status, project_id, from, to
GET/invoices, /invoices/{id}rechnungen:readFilter wie Rapporte
GET/offers, /offers/{id}angebote:readFilter wie Rapporte
GET/time-entrieszeiterfassung:readpage, pageSize (max. 100)
GET/appointmentstermine:readPflicht user_id, from, to (YYYY-MM-DD)
GET/anfragenanfragen:readFilter status, q
POST/anfragenanfragen:write{ title, description?, source?, contact_name?, contact_email?, contact_phone?, objekt_street?, objekt_house_number?, objekt_postal_code?, objekt_city? } → 201

Fehlerformat: { error: 'unauthorized' | 'insufficient_scope' | 'module_disabled' | 'rate_limited' | 'validation_error', message, details? }.

Ausgehende Webhooks

  • Anlegen: Einstellungen › Integrationen › API oder POST /api/company/webhooks{ name, url (https), events[] } → Antwort enthält einmalig das secret.
  • Events sind pro Modul benannt (rapport.completed, invoice.paid, anfrage.created, appointment.updated, time_entry.created, …); Wildcards rapport.*. Nur aktive Module senden. Verfügbare Events: GET /api/company/webhooksavailableEvents.
  • Zustellung: POST mit JSON { id, type, companyId, createdAt, data } und Headern X-Work7-Event, X-Work7-Delivery, X-Work7-Timestamp, X-Work7-Signature: sha256=<hmac>. Signatur = HMAC-SHA256(secret, <timestamp>.<body>). Timestamp prüfen (± 5 min).
  • Retry: 5 Versuche mit Backoff 1/5/15/60/240 min, danach dead. Sichtbar unter GET /api/company/webhooks/deliveries.
  • Zusteller: POST /api/cron/webhook-out (Header Authorization: Bearer <CRON_SECRET>), wie die anderen Crons extern getriggert — empfohlen jede Minute.
  • Pausieren/Löschen: PATCH /api/company/webhooks/{id} { active }, DELETE …/{id}.

Export je Modul

GET /api/company/modules/{modul}/export (Admin) liefert JSON mit allen Tabellen des Moduls für den Mandanten — auch für abgeschaltete Module (Downgrade-Vertrag).

Betrieb

  • Migration 112_api_keys_webhooks.sql (Tabellen api_keys, webhook_subscriptions, webhook_deliveries).
  • Neue Env (optional): API_KEY_PEPPER, API_KEY_RATE_LIMIT_PER_MINUTE.
  • Neuer Cron-Aufruf: /api/cron/webhook-out.

Work7 · Software für Handwerksbetriebe