Zum Inhalt springen

API-Referenz

Übersicht der Veasytor REST API. Alle Endpunkte erfordern Authentifizierung via Supabase Session (Cookie-basiert), sofern nicht anders angegeben.

Veasytor verwendet Supabase Auth (Client-seitig). Zusaetzlich stehen server-seitige API-Routen fuer Login und Magic-Link zur Verfuegung (ADR-PS-262).

MethodeBeschreibung
E-Mail + Passwortsupabase.auth.signInWithPassword() (Client) oder POST /api/auth/login (Server)
Magic Linksupabase.auth.signInWithOtp() (Client) oder POST /api/auth/magic-link (Server)
Google OAuthsupabase.auth.signInWithOAuth()

Auth API-Routen:

EndpunktMethodeBeschreibung
/api/auth/loginPOSTServer-seitiger Login mit E-Mail + Passwort (ADR-PS-262)
/api/auth/magic-linkPOSTMagic-Link per E-Mail senden (ADR-PS-262)
/api/auth/check-emailGETE-Mail-Existenz prüfen
/api/auth/verify-emailGETE-Mail-Verifizierung
/api/auth/redeem-codePOSTEinladungscode einlösen
/api/auth/resend-verificationPOSTVerifizierungs-E-Mail erneut senden
/api/auth/reset-passwordPOSTPasswort zurücksetzen
/api/auth/sessionsGETAktive Sessions abfragen
/api/auth/sessionANYCatch-All: JSON 404 mit Verweis auf /api/auth/sessions (Plural). Verhindert HTML-404 fuer fehlerhafte Aufrufe (ADR-PS-268).
/api/auth/redirectGETAuth-Redirect-Handler
/api/auth/track-loginPOSTLogin-Tracking: Erstellt USER_LOGIN AuditLog-Einträge pro aktiver Tenant-Membership mit Subdomain-Kontext (portal/go/admin). System-Admins ohne Memberships erhalten keinen Eintrag.
EndpunktMethodeBeschreibung
/api/parking-spacesGETParkplätze der aktiven Liegenschaft
/api/parking-spaces/[id]GET/PUT/DELETEEinzelner Parkplatz
/api/parking-spaces/reservePOSTParkplatz reservieren
/api/parking-reservationsGETAktive Reservierungen
EndpunktMethodeBeschreibung
/api/admin/bookingsGETBuchungen auflisten (Portal)
/api/bookings/[id]/cancelPOSTBuchung stornieren
/api/bookings/[id]/extendPOSTBuchung verlängern
/api/bookings/[id]/end-earlyPOSTBuchung vorzeitig beenden
EndpunktMethodeBeschreibung
/api/admin/usersGETBenutzer auflisten (System-Admin)
/api/user/createPOSTBenutzer erstellen
/api/user/roleGET/PUTBenutzerrolle abfragen/ändern
/api/user/settingsGET/PUTBenutzereinstellungen
/api/user/preferencesGET/POSTSprach- & Benachrichtigungspräferenzen (nur in /app/-Routen)
/api/user/profile-statusGETProfilstatus
/api/user/membershipsGETLiegenschafts-Mitgliedschaften
/api/user/subdomain-accessGETSubdomain-Zugriffsrechte
/api/user/notificationsGETBenachrichtigungen
/api/user/notifications/readPOSTAls gelesen markieren
/api/user/push-tokenPOSTPush-Token registrieren
/api/user/data-exportPOSTDSGVO-Datenexport
/api/user/delete-requestPOSTDSGVO-Löschanfrage

Mandant – Support-Zugang (ADR-PS-306, ersetzt ADR-PS-294)

Abschnitt betitelt „Mandant – Support-Zugang (ADR-PS-306, ersetzt ADR-PS-294)“
EndpunktMethodeBeschreibung
/api/tenant/support-accessGETAktive SupportAccessRequests + 30-Tage-History für den aktuellen Mandanten. Portal: OWNER/MANAGER.
/api/tenant/support-access/[requestId]/revokePOSTSupportAccessRequest widerrufen. Cascade: DATA_VIEW-Widerruf entzieht auch TENANT_ACCESS. Audit-Log SUPPORT_ACCESS_REVOKED.

DSGVO-Maskierung: Ohne aktiven Support-Zugang werden personenbezogene Daten (E-Mail, Name) in allen Admin-API-Responses maskiert. In der globalen Benutzerliste (/api/admin/users ohne tenantId-Filter) sind PII immer maskiert.

EndpunktMethodeBeschreibung
/api/tenant/members/invitePOSTNeuen Benutzer einladen (Team oder Property)
/api/tenant/members/resendPOSTEinladung erneut senden
/api/tenant/members/[id]PUT/DELETEMitglied/Einladung verwalten. PUT Body: roles, optional propertyId/apartmentId fuer Property-Rollen. PropertyMember wird automatisch erstellt/entfernt (ADR-PS-273)
/api/tenant/invitations/acceptPOSTAuto-Join nach E-Mail-Verifikation. Erstellt TenantMember + PropertyMember. Idempotent/race-safe via upsert (ADR-PS-273, ADR-PS-274)
/api/invite/acceptPOSTEinladung annehmen mit Passwort-Setup. Erstellt TenantMember + PropertyMember (ADR-PS-273)
/api/tenant/invitePOSTTenant-Einladung
/api/residents/send-invitationPOSTEinladung an bestehenden Bewohner senden (ADR-PS-237)
/api/residents/active-invitationsGETAktive Einladungen abrufen
/api/residents/revoke-invitationPOSTEinladung widerrufen
/api/residents/leave-propertyPOSTLiegenschaft verlassen. Loescht TenantMember (nur RESIDENT-Rolle) + PropertyMember + VisitorPropertyAccess. Body: \{ propertyId \}
EndpunktMethodeBeschreibung
/api/apartmentsGET/POSTWohnungen auflisten/erstellen
/api/apartments/[id]GET/PUT/DELETEEinzelne Wohnung
/api/apartments/[id]/detailsGETWohnungsdetails
/api/apartments/[id]/usersGETBewohner einer Wohnung
/api/apartments/generate-tokenPOSTEinladungstoken generieren
EndpunktMethodeBeschreibung
/api/propertiesGETLiegenschaften des Nutzers
/api/properties/[id]GET/PUTEinzelne Liegenschaft
/api/admin/propertiesGETAlle Liegenschaften (System-Admin)
/api/admin/properties/[id]GET/PUT/DELETELiegenschaft verwalten (System-Admin)
EndpunktMethodeBeschreibung
/api/tenant/subscriptionGETAbo-Informationen (Plan, Status, Limits, Testphase)
/api/billing/invoicesGETStripe-Rechnungen (Status: PAID/PENDING/OVERDUE/CANCELLED)
/api/billing/portalPOSTStripe Customer Portal Session erstellen
/api/webhooks/stripePOSTStripe Webhook Handler

Hinweis: GET /api/billing existiert nicht. Abo-Informationen werden über /api/tenant/subscription abgerufen, Rechnungen über /api/billing/invoices.

EndpunktMethodeBeschreibung
/api/dashboard/statsGETDashboard-Statistiken (Auslastung etc.)
/api/dashboard/chartGETDashboard Chart-Daten
/api/dashboard/overstaysGETÜberschreitungen
/api/tenant/statsGETMandanten-Statistiken (Management-Übersicht)
/api/statistics/bookingsGETBuchungs-Statistiken (Datumsbereich, Liegenschaft)
/api/statistics/bookings-chartGETBuchungs-Zeitreihe (Tag/Woche/Monat)
/api/statistics/incidentsGETVorfälle-Statistiken inkl. hourlyDistribution, selfResolutionRate, participationRate, avgResponsesPerInquiry, timezone-Parameter (Default: Europe/Zurich)
/api/statistics/incidents-chartGETVorfälle-Zeitreihe
/api/statistics/audit-actionsGETAudit-Log Aktionen (aggregiert)
/api/statistics/top-listsGETTop-Listen (nur type=bookings oder type=incidents). Incidents: mostActiveRespondents, mostAffectedApartments, fastestResolutions, recurringPlates, mostReporters, mostIncidentSpaces
/api/statistics/parking-usageGETParkplatz-Auslastung
/api/statistics/property-visitorsGETBesucher pro Liegenschaft
/api/statistics/user-visitorsGETBesucher pro Nutzer (Go App)
/api/statistics/resident-activityGETBewohner-Aktivität
/api/statistics/visitor-countGETBesucherzählung
/api/statistics/reservation-durationGETReservierungsdauer
/api/statistics/platform-statsGETPlattform-Statistiken (öffentlich)
/api/admin/statsGETSystem-Admin Statistiken

Hinweis: GET /api/statistics existiert nicht. Statistiken werden über spezifische Endpunkte abgerufen (z.B. /api/statistics/bookings, /api/dashboard/stats).

EndpunktMethodeBeschreibung
/api/inquiriesGET/POSTParkplatz-Anfragen
/api/inquiries/[id]GET/PUTEinzelne Anfrage
/api/inquiries/[id]/claimPOSTDSGVO-konforme Besucher-Verifizierung (“Blind Claim”). Rate-limited (5 Versuche/10 Min)
/api/inquiries/[id]/warnPOSTAbschleppwarnung für gemeldetes Fahrzeug senden
/api/inquiries/respondPOSTAuf Anfrage antworten (Ja/Nein/Veto)
/api/messagesGET/POSTNachrichten
/api/messages/[id]GETEinzelne Nachricht
/api/notificationsGETSystem-Benachrichtigungen
EndpunktMethodeBeschreibung
/api/support/listGETSupport-Tickets auflisten
/api/support/createPOSTNeues Ticket erstellen (authentifiziert)
/api/support/create-publicPOSTTicket ohne Authentifizierung erstellen (Rate-limited: 5/Stunde). Für öffentliche Support-Seite
/api/support/[id]GET/PUTEinzelnes Ticket. PII-Maskierung basierend auf SupportAccessRequest-Status (ADR-PS-306)
/api/support/[id]/access/requestPOSTSupport-Zugriffsanfrage erstellen (DATA_VIEW oder TENANT_ACCESS). Auto-Split bei TENANT_ACCESS (ADR-PS-306)
/api/support/[id]/access/[requestId]/grantPOSTZugriffsanfrage gewähren. Zwei-Tier-Auth: Orphaned User oder Tenant OWNER/MANAGER (ADR-PS-306)
/api/support/[id]/access/[requestId]/denyPOSTZugriffsanfrage ablehnen. CASCADE: DATA_VIEW-Deny entzieht auch TENANT_ACCESS (ADR-PS-306)
/api/support/[id]/claimPOSTTicket beanspruchen (SUPPORT/ADMIN). Setzt Status auf ASSIGNED (ADR-PS-306)
/api/support/[id]/reassignPOSTTicket neu zuweisen (ADMIN). Widerruft alle Zugänge des bisherigen Bearbeiters (ADR-PS-306)
/api/support/[id]/replyPOSTAntwort auf Ticket. Optional: newStatus (z.B. RESOLVED, CLOSED) für Manager – setzt den Ticket-Status direkt in der DB. Auto-Revoke des Datenzugangs bei RESOLVED/CLOSED
/api/support/[id]/messagesGETTicket-Nachrichten abrufen
EndpunktMethodeBeschreibung
/api/admin/tenantsGETMandanten auflisten (inkl. isActive, deactivatedAt, deactivationGracePeriodDays)
/api/admin/tenantsPOSTMandant erstellen
/api/admin/tenantsPATCHMandant aktualisieren. Actions: DEACTIVATE (setzt isActive=false, revoked alle Member-Sessions), REACTIVATE (setzt isActive=true), CREDIT_DAYS (Tage-Gutschrift, kumulative Berechnung, 730-Tage-Cap). Body: \{ tenantId, action, data? \}
/api/admin/tenants/[id]/statsGETAggregierte Tenant-Statistiken (Buchungen, Vorfälle, Scans, Logins, Nutzung, Aktivitäts-Chart). Query-Params: period (7d/30d/90d/365d), propertyId (optional). SuperAdmin-only.
/api/admin/tenants/[id]/creditsGETGutschrift-Historie für einen Mandanten
/api/admin/tenantsDELETEMandant endgültig löschen. Kaskadierende Löschung aller zugehörigen Daten (inkl. TenantCredit, 17+ Tabellen) in einer Transaktion. Body: \{ id \}
/api/admin/system-alertsGET/POSTSystem-Warnungen
/api/admin/system-alerts/[id]PUT/DELETEWarnung bearbeiten
/api/admin/rulesGET/PATCHRegelwerk (GET: ?propertyId=…, PATCH: Body mit propertyId + Regeln)
/api/properties/settings/[id]GET/PUTVollständige Liegenschafts-Einstellungen (inkl. Regeln, Reservierungen, Abschleppen)
/api/admin/settingsGET/PUTSystem-Einstellungen
/api/admin/releasesGET/POSTRelease Notes
/api/admin/feedbacksGETFeedback-Übersicht
/api/admin/subscription-plansGET/POSTAbo-Pläne
EndpunktMethodeBeschreibung
/api/bulk/validatePOSTBulk-Import validieren
/api/bulk/executePOSTBulk-Import ausführen
/api/bulk/templateGETImport-Template
/api/bulk/generate-pdfPOSTPDF generieren

Alle Endpunkte verwenden konsistente Fehler-Formate:

{
"error": "Beschreibung des Fehlers",
"code": "ERROR_CODE"
}
HTTP StatusBedeutung
200Erfolg
207Multi-Status – Aktion teilweise erfolgreich (z.B. Einladung erstellt, aber E-Mail konnte nicht gesendet werden). Frontend zeigt Warning-Toast.
307Redirect (z.B. unauthentifizierter Zugriff auf geschuetzte Routen → Login)
400Ungültige Anfrage
401Nicht authentifiziert
403Keine Berechtigung
404Nicht gefunden
500Server-Fehler

Geschuetzte Subdomains (Portal, Admin, Go) verwenden ein Auth-First Pattern: Unauthentifizierte Requests auf beliebige Pfade erhalten einen HTTP 307 Redirect zur Login-Seite – nicht 404. Dies ist ein Sicherheitsprinzip, das verhindert, dass Applikationsstruktur an unauthentifizierte Nutzer preisgegeben wird.

  • www.veasytor.app: Oeffentlich, kein Auth-Check (ADR-PS-257: ProtectedRoute Bypass). 404 fuer nicht-existierende Seiten.
  • portal.veasytor.app: 307 → Login (unauthentifiziert), 404 via Next.js (authentifiziert).
  • admin.veasytor.app: 307 → Login (unauthentifiziert), 404 via Next.js (authentifiziert).
  • go.veasytor.app: 307 → Login (unauthentifiziert), 404 via Next.js (authentifiziert).

Alle Marketing-Seiten (www) verwenden NextSeo fuer OpenGraph und Twitter Meta-Tags:

  • Default-Konfiguration in next-seo.config.ts (og:type, og:locale, og:siteName, og:image /icons/icon-512.png 512x512, Twitter summary_large_image). Fallback-Rewrites fuer /images/og-image.jpg und /images/og-image.png in next.config.mjs (ADR-PS-265/269).
  • Per-Page Overrides mit <NextSeo openGraph=\{\{...\}\} /> fuer Titel, Beschreibung und Canonical-URL.
  • Language-Alternates (DE, EN, FR, IT) fuer internationale SEO.
  • SSR-Rendering: OG- und Twitter-Meta-Tags werden server-seitig im initialen HTML gerendert, sodass Crawler (Google, Facebook, Twitter, LinkedIn) und Tools wie curl korrekte Vorschauen erhalten (ADR-PS-254).

4 themenspezifische SEO-Landingpages fuer den CH-Markt:

URLHauptkeywordSlug
/parkraummanagement-wohnanlagenParkraummanagement Wohnanlagenparkraummanagement
/besucherparkplaetze-verwaltenBesucherparkplaetze verwaltenbesucherparkplaetze
/falschparker-loesenFalschparker loesenfalschparker
/parkplatz-software-schweizParkplatz-Software SchweizparkplatzSoftware

Jede Seite hat: Hero, Problem (mit Bullet-Points), Solution, Benefits Grid (6 Cards), USP-Highlight (Bewohner-Crowdsourcing), Social Proof, FAQ (5 Fragen, JSON-LD FAQPage Schema), CTA, Related Topics. Alle Texte in DE/EN/FR/IT via src/locales/*/seoLanding.ts. Wiederverwendbares Layout: src/components/marketing/landing/SeoLandingPage.tsx.

SSR-Architektur (ADR-PS-270): Content wird server-seitig via getSeoLandingData() in getServerSideProps aufgeloest und als typisierte Props an die Komponenten uebergeben. Dadurch enthaelt der initiale HTML-Response den vollstaendigen Content (800+ Woerter), korrekte JSON-LD Schemas (SoftwareApplication + FAQPage) und Meta-Tags mit echten Texten – wichtig fuer Crawler (Google, Facebook, etc.). Die Komponenten nutzen kein useTranslation() fuer SEO-Inhalte.

Alle Subdomains teilen eine gemeinsame Supabase-Session via Cookie mit domain=.veasytor.app:

  • Browser-Client (component.ts): Setzt/entfernt Cookies mit domain=.veasytor.app in Production.
  • Server-Middleware (middleware.ts): Setzt Cookies ebenfalls mit domain=.veasytor.app in Production (ADR-PS-252).
  • Sprache: veasytor_lang-Cookie mit domain=.veasytor.app (ADR-PS-167).
  • Logout: supabase.auth.signOut() loescht das geteilte Session-Cookie → Logout propagiert automatisch zu allen Subdomains.