Darstellung
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 (PepperAPI_KEY_PEPPER, FallbackNEXTAUTH_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 mit403 module_disabled, der Schlüssel bleibt. - Rate-Limit: 600 Anfragen/Minute je Schlüssel (
API_KEY_RATE_LIMIT_PER_MINUTE),429mitRetry-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 } }.
| Methode | Pfad | Modul / Scope | Hinweise |
|---|---|---|---|
| GET | /me | core:read | Mandant, Schlüssel, Paket, aktive/inaktive Bereiche |
| GET | /projects | core:read | Filter status, kontakt_id |
| GET | /projects/{id} | core:read | id oder Projektnummer |
| GET | /kontakte | core:read | Filter kind, status |
| GET | /rapports, /rapports/{id} | rapport:read | Filter status, project_id, from, to |
| GET | /invoices, /invoices/{id} | rechnungen:read | Filter wie Rapporte |
| GET | /offers, /offers/{id} | angebote:read | Filter wie Rapporte |
| GET | /time-entries | zeiterfassung:read | page, pageSize (max. 100) |
| GET | /appointments | termine:read | Pflicht user_id, from, to (YYYY-MM-DD) |
| GET | /anfragen | anfragen:read | Filter status, q |
| POST | /anfragen | anfragen: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 dassecret. - Events sind pro Modul benannt (
rapport.completed,invoice.paid,anfrage.created,appointment.updated,time_entry.created, …); Wildcardsrapport.*. Nur aktive Module senden. Verfügbare Events:GET /api/company/webhooks→availableEvents. - Zustellung:
POSTmit JSON{ id, type, companyId, createdAt, data }und HeadernX-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 unterGET /api/company/webhooks/deliveries. - Zusteller:
POST /api/cron/webhook-out(HeaderAuthorization: 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(Tabellenapi_keys,webhook_subscriptions,webhook_deliveries). - Neue Env (optional):
API_KEY_PEPPER,API_KEY_RATE_LIMIT_PER_MINUTE. - Neuer Cron-Aufruf:
/api/cron/webhook-out.