Notifications API
API endpoints for managing email templates and automation rules.
Email Templates
List Templates
GET /api/v1/admin/messaging/templates
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
templateKey | string | Filter by template key |
languageCode | string | Filter by language code (e.g., fi, en) |
templateType | string | Filter by type (email or sms) |
siteId | string | Filter by site (includes tenant + global) |
includeGlobal | boolean | Include global default templates (default: true) |
Response:
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenantId": "t_ae",
"siteId": "s_laserareena_helsinki",
"templateKey": "booking_confirmed",
"languageCode": "fi",
"subjectTemplate": "Varausvahvistus — {{bookingReference}}",
"bodyTemplate": "<html>...</html>",
"templateType": "email",
"isGlobal": false,
"createdAt": "2026-03-22T10:30:00Z",
"updatedAt": "2026-03-22T10:30:00Z"
}
]
Get Template Types
GET /api/v1/admin/messaging/templates/types
Returns available template keys and their descriptions.
Response:
[
{
"key": "booking_confirmation",
"name": "Booking Confirmation",
"description": "Sent when a booking is confirmed",
"availableVariables": [
"customerName",
"bookingReference",
"bookingDateTime",
"productName"
]
},
{
"key": "booking_reminder",
"name": "Booking Reminder",
"description": "Sent before the booking date",
"availableVariables": [
"customerName",
"bookingReference",
"bookingDateTime",
"productName",
"siteName"
]
}
]
Get Template
GET /api/v1/admin/messaging/templates/:id
Response: Same shape as list item above.
Get Template by Key
GET /api/v1/admin/messaging/templates/key/:templateKey
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
languageCode | string | Language code (default: en) |
siteId | string | Prefer site-specific template |
Returns the best-matching template using the resolution chain (site → tenant → global → English fallback).
Create Template
POST /api/v1/admin/messaging/templates
Request Body:
{
"templateKey": "booking_confirmed",
"languageCode": "fi",
"subjectTemplate": "Varausvahvistus — {{bookingReference}}",
"bodyTemplate": "<html>...</html>",
"templateType": "email",
"siteId": "s_laserareena_helsinki"
}
| Field | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | Template key (e.g., booking_confirmed) |
languageCode | string | No | Language code (default: en) |
subjectTemplate | string | Yes | Subject line (supports {{variables}}) |
bodyTemplate | string | Yes | HTML body (supports {{variables}}) |
templateType | string | No | email (default) or sms |
siteId | string | No | Site ID for site-specific template (null = tenant-wide) |
Response: Created template object (201 Created)
Update Template
PUT /api/v1/admin/messaging/templates/:id
Request Body:
{
"subjectTemplate": "Updated subject line",
"bodyTemplate": "Updated body content..."
}
Only tenant-owned templates can be updated (not global defaults).
Response: Updated template object (200 OK)
Delete Template
DELETE /api/v1/admin/messaging/templates/:id
Response: 204 No Content
Preview Template
POST /api/v1/admin/messaging/templates/preview
Request Body:
{
"subjectTemplate": "Varausvahvistus — {{bookingReference}}",
"bodyTemplate": "<h1>Hei {{customerName}}</h1><p>Varauksesi on vahvistettu.</p>",
"sampleData": {
"customerName": "Matti Meikäläinen",
"bookingReference": "BK-2026-001",
"productName": "Luolaseikkailu",
"siteName": "Luolaseikkailu Tampere",
"businessName": "Active Entertainment"
}
}
Response:
{
"subject": "Varausvahvistus — BK-2026-001",
"body": "<h1>Hei Matti Meikäläinen</h1><p>Varauksesi on vahvistettu.</p>",
"warnings": []
}
Automation Rules
List Rules
GET /api/v1/admin/messaging/automation-rules
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
triggerEvent | string | Filter by trigger event |
isActive | boolean | Filter by active status |
templateKey | string | Filter by template key |
Response:
[
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"tenantId": "t_demo",
"name": "24-Hour Booking Reminder",
"description": "Send reminder 24 hours before booking",
"triggerEvent": "booking_date",
"triggerOffset": -24,
"triggerOffsetUnit": "hours",
"templateKey": "booking_reminder",
"templateId": null,
"productIds": [],
"siteIds": [],
"isActive": true,
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}
]
Get Rule
GET /api/v1/admin/messaging/automation-rules/:id
Response: Automation rule object
Create Rule
POST /api/v1/admin/messaging/automation-rules
Request Body:
{
"name": "24-Hour Booking Reminder",
"description": "Send reminder 24 hours before booking",
"triggerEvent": "booking_date",
"triggerOffset": -24,
"triggerOffsetUnit": "hours",
"templateKey": "booking_reminder",
"productIds": [],
"siteIds": [],
"isActive": true
}
Trigger Events:
| Value | Description |
|---|---|
booking_created | When a new booking is created |
booking_confirmed | When payment is confirmed |
booking_completed | When booking is marked complete |
booking_date | Relative to booking start time |
Trigger Offset Units:
| Value | Description |
|---|---|
hours | Offset in hours |
days | Offset in days |
Response: Created rule object (201 Created)
Update Rule
PUT /api/v1/admin/messaging/automation-rules/:id
Request Body:
{
"name": "Updated Rule Name",
"triggerOffset": -48,
"isActive": false
}
Response: Updated rule object (200 OK)
Delete Rule
DELETE /api/v1/admin/messaging/automation-rules/:id
Response: 204 No Content
Template Variables Reference
Customer Information
| Variable | Type | Description |
|---|---|---|
customerName | string | Customer's full name |
customerEmail | string | Customer's email address |
customerPhone | string | Customer's phone number |
Booking Details
| Variable | Type | Description |
|---|---|---|
bookingId | string | Booking UUID |
bookingReference | string | Human-readable reference |
bookingDateTime | ISO 8601 | Booking start date/time |
partySize | number | Number of participants |
status | string | Current booking status |
Product & Location
| Variable | Type | Description |
|---|---|---|
productName | string | Name of the booked product |
siteName | string | Location name |
siteAddress | string | Location address |
Business Information
| Variable | Type | Description |
|---|---|---|
businessName | string | Tenant business name |
supportEmail | string | Support email address |
supportPhone | string | Support phone number |
Financial
| Variable | Type | Description |
|---|---|---|
totalAmount | number | Total booking amount |
currency | string | Currency code (e.g., EUR) |
Confirmation-Specific
| Variable | Type | Description |
|---|---|---|
confirmedAt | ISO 8601 | When booking was confirmed |
paymentMethod | string | Payment method used |
paymentReference | string | Payment transaction ID |
Handlebars Helpers
Date Formatting
| Format | Output |
|---|---|
MMMM d, yyyy | January 15, 2025 |
dd/MM/yyyy | 15/01/2025 |
h:mm a | 2:30 PM |
HH:mm | 14:30 |
Currency Formatting
Outputs: €25.00 or $25.00 based on currency
Conditionals
Comparison
Error Responses
400 Bad Request
{
"statusCode": 400,
"message": "Validation failed",
"errors": [
{
"field": "templateKey",
"message": "Template key is required"
}
]
}
404 Not Found
{
"statusCode": 404,
"message": "Template not found"
}
409 Conflict
{
"statusCode": 409,
"message": "Template with key 'booking_confirmed' and language 'fi' already exists"
}
Rate Limits
| Endpoint | Limit |
|---|---|
| GET endpoints | 100 requests/minute |
| POST/PUT/DELETE | 30 requests/minute |
Authentication
All endpoints require admin authentication via JWT token:
Authorization: Bearer <token>
X-Tenant-ID: <tenant_id>
See Authentication for details.