Skip to Content

External notifications

Register emails that your own system sent to a customer, so staff can see them in Tillor

Last updated on

Does your system send its own emails to customers (newsletter, booking confirmation, reminder)? Then register them in Tillor. Staff see them on the customer, on the invoice and in the Notifications overview, next to the notifications Tillor sends itself.

Tillor sends nothing: you register a message that has already been sent. External notifications always carry the label External with your source name in the app, so they never pass for a Tillor notification.

Access

The user behind the API key needs one of these permissions in the organisation. An administrator grants them in the organisation's user permissions, in the Notifications group (Register external notifications and Manage other external notifications).

PermissionWhat you can do
notifications:external:writeRegister notifications and update or delete your own registrations
notifications:external:manage-othersAlso update or delete registrations of other users or integrations

One user per integration

Ownership is tied to the user of the API key. Use a separate (service) user per integration, so one integration can never change the notifications of another.

Endpoints

All paths are under /api/orgs/:orgId. Exact schemas: OpenAPI, tag notifications.

MethodPathDescription
POST/notifications/externalRegister a notification
PATCH/notifications/external/{id}Update status, timestamps or content
DELETE/notifications/external/{id}Delete permanently
GET/notifications?source=EXTERNALList registered notifications (also filter on externalSource, externalReference, customerId, invoiceId)
GET/notifications/{id}Fetch one notification

Notifications that Tillor sent itself cannot be changed or deleted through these endpoints; they return 404.

Register

curl -X POST "https://tillor.eu/api/orgs/org_abc123/notifications/external" \
  -H "x-api-key: tkn_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "externalSource": "mailchimp",
    "externalReference": "campaign-42:member-9f3a",
    "name": "Boekingsbevestiging",
    "customerId": "clx789...",
    "channel": "EMAIL",
    "status": "SENT",
    "sentAt": "2026-09-19T08:15:00Z",
    "email": {
      "to": "jan@voorbeeld.nl",
      "from": "Recreatiepark Het Meer <info@recreatiepark-het-meer.be>",
      "subject": "Je boeking is bevestigd",
      "htmlBody": "<p>Dag Jan, ...</p>",
      "attachments": [{ "filename": "bevestiging.pdf", "contentType": "application/pdf", "size": 48211 }]
    }
  }'

All fields and limits are in OpenAPI. These fields have rules you need to know beforehand:

FieldRule
externalSourceName of your system in lowercase letters, digits, ., _ or - (e.g. mailchimp). Staff see this name on the notification
externalReferenceYour own ID for this message, unique within externalSource
nameShort label for staff (e.g. "Booking confirmation"). It can be searched on
customerId / invoiceIdAt least one of the two. Determines where the notification appears. If you only send invoiceId, Tillor also links the customer of that invoice. An unknown ID, or an invoice of a different customer, gives 400
statusSENT, FAILED, BOUNCED or COMPLAINED. Without sentAt for SENT, Tillor uses the moment of registration
sentAt, readAt, clickedAtISO 8601 with time zone, e.g. 2026-09-19T08:15:00Z. Other values are refused
email.attachmentsMetadata only (filename, contentType, size). The files themselves are not stored

Retrying safely

POST is idempotent on externalSource + externalReference. If you send the same combination again (for example after a timeout), you get the existing notification back and nothing is changed. If you want to change something, use PATCH.

No personal data in externalReference or name

externalSource, externalReference and name are stored unencrypted because they are searched on. Use a technical ID, not an email address or name. An externalReference with @ is refused. Recipient, subject, content and attachments are stored encrypted.

Update and delete

With PATCH, send only the fields that change, for example when an email bounces afterwards:

curl -X PATCH "https://tillor.eu/api/orgs/org_abc123/notifications/external/NOTIFICATION_ID" \
  -H "x-api-key: tkn_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "status": "BOUNCED", "errorMessage": "Mailbox bestaat niet" }'

DELETE removes the notification permanently, including its content. Also use this to comply with a deletion request (GDPR).

A PATCH that changes nothing does nothing: no change, no event. If you change the content (label, recipient, sender, subject, text, HTML or attachments) or delete a notification, it appears in the activity log of the customer or invoice, with the user who did it. Updates of status, readAt or clickedAt do not appear there, so you can keep syncing opens and clicks.

HTML and privacy

Tillor shows the HTML to staff as the customer received it, but treats it as untrusted content:

  • When saving, scripts, forms, iframes, embeds and event attributes (onclick, ...) are removed. Links open in a new tab
  • The preview runs in an isolated frame without scripts and without access to the Tillor session
  • External images and fonts do not load automatically, so opening a notification does not trigger a tracking pixel. The staff member can load images per notification

So do not count on "opened" tracking in your system firing when a staff member views the notification.

What Tillor does not do with external notifications

  • Does not send (again) or automatically retry
  • Does not fetch status updates from your mail provider: you keep the status up to date with PATCH
  • Does not count them in the lists Failed Notifications, Bounced Notifications and Pending Notifications or in the counters at the top of the notification overview, because Tillor cannot verify your status. They do appear under Recent Communications

Webhooks and SSE

EventWhen
notification-delivery:updatedOn registering and on every PATCH that changes something. Contains the full notification
notification-delivery:deletedOn DELETE. Contains only id, source, externalSource, externalReference, customerId and invoiceId

The field source is EXTERNAL for your registrations and INTERNAL for notifications from Tillor. Filter on it if you want to skip your own events. See Webhooks and SSE.

Related

Was this page helpful?

On this page