Skip to main content

Notifications API

API endpoints for managing email templates and automation rules.

Email Templates

List Templates

GET /api/v1/admin/messaging/templates

Query Parameters:

ParameterTypeDescription
templateKeystringFilter by template key
languageCodestringFilter by language code (e.g., fi, en)
templateTypestringFilter by type (email or sms)
siteIdstringFilter by site (includes tenant + global)
includeGlobalbooleanInclude 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:

ParameterTypeDescription
languageCodestringLanguage code (default: en)
siteIdstringPrefer 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"
}
FieldTypeRequiredDescription
templateKeystringYesTemplate key (e.g., booking_confirmed)
languageCodestringNoLanguage code (default: en)
subjectTemplatestringYesSubject line (supports {{variables}})
bodyTemplatestringYesHTML body (supports {{variables}})
templateTypestringNoemail (default) or sms
siteIdstringNoSite 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:

ParameterTypeDescription
triggerEventstringFilter by trigger event
isActivebooleanFilter by active status
templateKeystringFilter 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:

ValueDescription
booking_createdWhen a new booking is created
booking_confirmedWhen payment is confirmed
booking_completedWhen booking is marked complete
booking_dateRelative to booking start time

Trigger Offset Units:

ValueDescription
hoursOffset in hours
daysOffset 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

VariableTypeDescription
customerNamestringCustomer's full name
customerEmailstringCustomer's email address
customerPhonestringCustomer's phone number

Booking Details

VariableTypeDescription
bookingIdstringBooking UUID
bookingReferencestringHuman-readable reference
bookingDateTimeISO 8601Booking start date/time
partySizenumberNumber of participants
statusstringCurrent booking status

Product & Location

VariableTypeDescription
productNamestringName of the booked product
siteNamestringLocation name
siteAddressstringLocation address

Business Information

VariableTypeDescription
businessNamestringTenant business name
supportEmailstringSupport email address
supportPhonestringSupport phone number

Financial

VariableTypeDescription
totalAmountnumberTotal booking amount
currencystringCurrency code (e.g., EUR)

Confirmation-Specific

VariableTypeDescription
confirmedAtISO 8601When booking was confirmed
paymentMethodstringPayment method used
paymentReferencestringPayment transaction ID

Handlebars Helpers

Date Formatting

{{formatDate bookingDateTime 'MMMM d, yyyy'}}
FormatOutput
MMMM d, yyyyJanuary 15, 2025
dd/MM/yyyy15/01/2025
h:mm a2:30 PM
HH:mm14:30

Currency Formatting

{{formatCurrency totalAmount currency}}

Outputs: €25.00 or $25.00 based on currency

Conditionals

{{#if siteAddress}}
Address:
{{siteAddress}}
{{/if}}

{{#unless isPaid}}
Payment pending
{{/unless}}

Comparison

{{#ifEquals status 'CONFIRMED'}}
Your booking is confirmed!
{{/ifEquals}}

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

EndpointLimit
GET endpoints100 requests/minute
POST/PUT/DELETE30 requests/minute

Authentication

All endpoints require admin authentication via JWT token:

Authorization: Bearer <token>
X-Tenant-ID: <tenant_id>

See Authentication for details.