nisebookings docs

Notifications and e-mail

Every automatic mail is driven by a template that a business can edit in the admin (Meldingen). The service renders the mail when the event happens, puts it in an outbox, and sends it from there in the background with retries. Nothing is sent directly from the request that created the booking — mail failures can never fail a booking.

Contents

Lifecycle

event (booking, status change, reminder window, waitlist offer, …)
   │
   ├─ match active templates of that type (status filter, service filter)
   ├─ resolve recipients (customer / staff / admins / extra addresses)
   ├─ render subject + body per recipient  ← template codes, business time zone, locale
   ├─ dedupe (a unique dedupe key per recipient + event) and add to the outbox
   ▼
outbox (status pending → sending → sent | failed)
   ▲
   └─ every minute: send what is due → retry with backoff

Rendering happens at enqueue time, so the mail shows the data as it was at that moment.

Types

Type UI label Fires when
new_booking Nieuwe afspraak a booking/order is created (immediately for local/free orders; after payment for Mollie orders; also on waitlist joins and package purchases the corresponding type is used instead)
status_changed Statuswijziging a booking's status changes (admin action, cancellation, refund-rejection, automatic status change)
reminder Herinnering the reminder window for an upcoming appointment opens
waitlisted Wachtlijst a customer joins a waiting list
waitlist_offer Plek vrij (wachtlijst) a seat frees up and the customer gets a claim link
package_new Nieuw pakket a package is bought or created (mail contains the personal planning link)
event_tickets Tickets an event order is placed (a "codes follow after payment" variant) and again once the order is approved with the actual codes

New accounts get a default template set for every type on signup (Dutch), so mail works out of the box.

Recipients

Each template has four recipient switches:

Switch Who Reply-To
Klant (customer) the booking customer's e-mail your Antwoordadres (reply_to), or the platform sender when empty
Medewerker (staff) the staff member of the appointment (skipped when archived); for packages the package staff the customer's e-mail
Beheerders (admins) every member of the account with role owner or admin the customer's e-mail
Andere adressen (custom) the newline-separated addresses in the template the customer's e-mail

Sender: display name = your Naam afzender (or company name), address = the platform's MAIL_FROM. At least one recipient must be enabled; custom recipients require at least one address.

Timing

Status filter (Bij status): send only when the booking has that status; Elke status matches everything. Note that Elke status in a reminder never includes cancelled or rejected bookings.

Service filter: all services, or a ticked subset.

Reminder timing (only for reminder):

Reminders dedupe on a key that includes the appointment start time, so rescheduling re-arms the reminder while nothing is sent twice for the same booking.

Template language

Placeholders and conditionals in both subject and body:

{client_name},
Je afspraak voor {service_name} is bevestigd op {appointment_date} om {appointment_time}.

{#if extras}
Extra's: {extras}
{/if}
{#if number_of_persons > 1}
We reserveren {number_of_persons} plaatsen.
{/if}

Rules:

Codes

{code} list as offered in the editor (Dutch labels in the admin):

Bedrijf — company_name, company_phone, company_address, company_website Klant — client_name, client_email, client_phone Afspraak — appointment_date ("dinsdag 14 oktober 2026"), appointment_time, appointment_end_time, appointment_notes (the customer's remark), booking_number, number_of_persons, extras ("Haarmasker (2×), Föhnen"), extras_total_price, order_count, appointment_schedule (one line per appointment of the order), online_meeting_url and online_meeting_join_url (empty unless the appointment has an online meeting), series_count, status (Dutch label), internal_note (only for staff/admin recipients), cancel_appointment_url (/b/<token>), cancel_order_url (/o/<order token>), cancellation_reason (currently always empty) Dienst — service_name, service_info, service_price, service_duration ("1 uur 30 min"), category_name, fields (the booking's answers to the service's Velden, one "Vraag: antwoord" line per answer; a per-person answer gets one line per person. Empty without answers. A field that was deleted later keeps showing its old answer, labelled with the field's id. A Bestand answer shows the file name only: its download link is signed and short-lived, and mails are kept.) Medewerker — staff_name, staff_email, staff_phone Betaling — total_price (empty when free), amount_paid, amount_due, payment_type (Ter plaatse / Online / Gratis), payment_status (Dutch), coupon, total_tax Wachtlijst — waitlist_url (only waitlist_offer) Pakket — package_url, package_name, package_size, package_remaining, package_expires (only package_new) Evenement — event_title, event_start_date, event_start_time, event_end_time, event_info, attendees_count, ticket_codes (before payment: "Je codes krijg je na betaling."), order_total (only event_tickets)

Which codes a template may use depends on its type: package and ticket templates have no appointment, so they only offer company/client codes plus their own group.

Attachments and reply-to

Agenda-bestand (.ics) meesturen attaches a standards-compliant calendar file (UTC times, escaped, folded at 75 octets) for booking-based mails. It follows the appointment's current time; rescheduling does not rewrite already-sent mails.

One mail per order, one per booking

A single checkout can contain a cart, chain parts, compound/collaborative parts and a whole recurring series. To keep this readable:

Deferred mail for online payments

For Mollie orders nothing is mailed at order time: the customer should not receive "your appointment is confirmed" before paying. The confirmation mail is queued when the payment completes (webhook, return poll, or the expiry check noticing the payment went through). Local and free orders are mailed immediately. Ticket orders are the exception: they get a "codes follow after payment" mail right away, and the codes mail once approved.

Delivery, retries and the log

Background processing

Everything timed runs as one scheduled pass, once a minute: queue the reminders that are due, expire unpaid payments, apply the automatic status change, send the waiting-list offers, and deliver queued mail. The service runs this itself — nothing to configure — but it is worth knowing because it explains the timing you and your customers see:

Admin reference

Meldingen (/app/notifications) — grouped by type with an Aan/Uit switch per template. The editor fields: Naam, Soort, Actief, Ontvangers (Klant / Medewerker / Beheerders / Andere adressen), Bij status, Diensten (alle or a selection), reminder timing, Onderwerp, Bericht, Agenda-bestand (.ics) meesturen, and the code table. Existing templates also have Test versturen and Verwijderen.

Verzendlog (/app/notifications/log) — the outbox, newest first, 50 per page.

Relevant settings: Instellingen → Bedrijf en e-mail (Naam afzender, Antwoordadres, Verzendmarge herinneringen, Annuleren tot) and Instellingen → Algemeen (Tijdzone — all mail times use it).

The display name comes from Instellingen → Bedrijf en e-mail (Naam afzender), replies go to the Antwoordadres, and the links in mails point at the pages this service serves (/b/…, /p/…, /w/…, /o/…). Mail is sent from the platform's own sending domain; you do not configure it.

Not implemented