Danvas
Danvas
DashboardSupportWelcome

👤 USER DOCS

User Guides

Getting Started

Getting StartedDashboard & OnboardingApp Settings

Tutorials

Tutorial: Setting Up Shift Tasks & ClosersTutorial: Managing Incidents in the InboxTutorial: Tracking Compliance & Sync StatusTutorial: Operational Workflows with the AI AssistantTutorial: Building & Deploying Custom Checklists

Daily Operations (Staff)

Shift Workspace & TasksService Day SetupDaily Line-UpStaff Service Day ReportsForms

Communication & Chat

Messages & AnnouncementsUnified Operations InboxAI Assistant

Manager & Admin Guides

Daily Line-Up SetupStaff SchedulingManaging LocationsNPS and Guest FeedbackCouponsContacts and Guest HistoryManager CloseoutsDaily Line-Up & ComplianceAnalyticsIncident ReportingWhistleblower Concerns & FeedbackAdmin Tools

⚙️ DEVELOPER DOCS

Getting Started

Getting StartedDevelopmentDeployment Guide

Architecture

Architecture OverviewExplanation: AI Integration & Tenant SecurityExplanation: Dynamic Forms Engine DesignExplanation: Compliance Ledger DesignExplanation: Live Sync & Data FreshnessData FlowArchitecture Decision Records

Core Domain

Core DomainDatabase ReferenceLocations DomainAuth & RBACScheduling DomainReports DomainIncidents DomainUnified Operations InboxLive Sync Data FreshnessToast Sync PipelineNotifications DomainCoupons and Guest NPSAudit Log & Compliance ArchitectureDesign Audit FindingsAI Chat IntegrationAnalytics & Tips Integration

Frontend

Frontend ArchitectureFormsLoading SkeletonsComponentsPWA & Offline ShellScreenshots

API Reference

API Reference

Endpoints

POS Sales APIOptimization Data APISchedule Shifts APIEmployee Export APIReports APIIncidents APIAI Chat APIPush Notifications APIWebhooks APICron API

Contributing

ContributingCode Examples

Security

Security & Compliance

Release Notes

What's New

Push Notifications API

Web Push subscription lifecycle and sending endpoints

Danvas exposes Web Push subscription and sending endpoints. A provider-accepted push is not a guarantee that a browser displayed or a user acknowledged the notification; delivery outcomes are governed by the notification operations runbook.

POST
/api/push/subscribe

Authorization

sessionAuth
cookie__session<token>

Clerk session cookie

Request Body

application/json
  1. body
  1. body
  2. …
endpoint*string

Push endpoint URL from the browser

keys*
expirationTime?|

Optional subscription expiration time in milliseconds

Response Body

Subscription saved

application/json
  1. response
  1. response
  2. …
success?boolean
curl -X POST "https://example.com/api/push/subscribe" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint": "string",
    "keys": {
      "p256dh": "string",
      "auth": "string"
    }
  }'
{
  "success": true
}
DELETE
/api/push/subscribe

Authorization

sessionAuth
cookie__session<token>

Clerk session cookie

Request Body

application/json
  1. body
  1. body
  2. …
endpoint*string

Push endpoint URL from the browser

Response Body

Subscription removed

application/json
  1. response
  1. response
  2. …
success?boolean
deleted?boolean
curl -X DELETE "https://example.com/api/push/subscribe" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint": "string"
  }'
{
  "success": true,
  "deleted": true
}
POST
/api/push/send

Authorization

bearerAuth
headerAuthorizationBearer <token>

Clerk JWT token from session

Request Body

application/json
  1. body
  1. body
  2. …
title?string

Notification title

body?string

Notification body text

url?string

Deep link URL when notification is clicked

targetUserId?string

Optional user ID to send to; another user requires admin authentication and must be in the current team

Response Body

Notification sent

application/json
  1. response
  1. response
  2. …
success?boolean
sent?integer
failed?integer
expired?integer
curl -X POST "https://example.com/api/push/send" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "success": true,
  "sent": 0,
  "failed": 0,
  "expired": 0
}

Authentication and lifecycle

  • POST /api/push/subscribe creates or updates the authenticated caller’s current-device subscription.
  • DELETE /api/push/subscribe removes only the authenticated caller’s subscription identified by endpoint; it cannot delete another user’s subscription.
  • POST /api/push/send allows self-targeting. Targeting another targetUserId requires an admin role. The send URL must be a safe relative same-origin path.
  • Expired subscriptions are removed before send, and stale 404/410 provider responses trigger cleanup. Subscribe/unsubscribe and send operations are rate-limited by the current route contracts.

VAPID Keys

Push notifications use VAPID (Voluntary Application Server Identification) for security:

# Environment variables
NEXT_PUBLIC_VAPID_PUBLIC_KEY=<public key>
VAPID_PRIVATE_KEY=<private key>

Generate keys with:

npx web-push generate-vapid-keys

Notification display

When the browser receives a push, the service worker may display a native notification. Payload URLs must be relative app paths so notification clicks stay same-origin:

self.registration.showNotification(title, {
  body,
  icon: "/apple-icon.png",
  badge: "/favicon.ico",
  data: { url }
});

Related files

FilePurpose
apps/app/src/app/api/push/subscribe/route.tsCreate/update and delete the caller’s subscription
apps/app/src/app/api/push/send/route.tsAuthenticated push send endpoint
apps/app/src/app/sw.tsService-worker push handling
packages/notifications/push.tsServer-side push helper, expiry cleanup, and URL safety
docs/features/push-subscription-lifecycle.mdCanonical feature contract

AI Chat API

Conversational data querying with streaming responses

Webhooks API

Lifecycle event handlers for Clerk and Svix

On this page

Authentication and lifecycleVAPID KeysNotification displayRelated files