Managing Notification Templates

7 views Markdown

The five endpoints that list, add, read, edit and remove notification templates.

Overview

A notification template lives in two places. Its behaviour sits in the settings file: whether it is on, who it reaches and by which channel. Its text sits in separate files per language: the subject, the e-mail body and the message.

That split reaches the endpoints. The listing gives the behaviour alone, and seeing the text wants one template read on its own.

Templates fall into groups and a group brings its own rules: attaching the invoice document means something in the invoice group and is ignored in the others.

Reference

Listing the Templates

get/api/v1/admin/notifications/templates
Notifications/GetNotificationTemplates admin

Returns every notification template under its group.

Response fields data[] — 3
groupstringThe group key.
namestringThe group's translated name.
templatesarrayThe templates in the group.
groupstringThe group it sits in.
keystringThe template key.
namestringIts translated name.
statusintWhether the template is on.
customboolWhether it was added by hand.
user_mailintWhether the client gets an e-mail.
admin_mailintWhether the staff get an e-mail.
user_smsintWhether the client gets a message.
admin_smsintWhether the staff get a message.
send_pdfintWhether the invoice document is attached. It comes empty outside the invoice group.
emailsstringExtra e-mail recipients.
phonesstringExtra phone recipients.
departmentsint[]The department ids tied to it.
variablesstringThe variables the template can use.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/notifications/templates' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/notifications/templates', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
const flat = data.flatMap((g) => g.templates);
const off  = flat.filter((t) => ! t.status);
$ch = curl_init('https://panel.example.com/api/v1/admin/notifications/templates');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The list is GROUPED and carries NO content: the subject and body come on the detail endpoint.
$groups = Api::Notifications()->GetNotificationTemplates()['data'];
$flat   = array_merge(...array_column($groups, 'templates'));

Adding a Template

post/api/v1/admin/notifications/templates
Notifications/CreateNotificationTemplate admin

Opens a new template under a group.

Body 2
groupstringreqThe group key.
keystringreqThe template key. A slash, dot or comma becomes a hyphen.
Response fields 201 — data — 14
dataobjectThe template made. Same shape as a template in the listing.
Errors 4
group_required422No group was given.
key_required422No key was given.
already_exists422A template with that group and key exists.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/notifications/templates' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"group":"account","key":"welcome-message"}'
const res = await fetch('https://panel.example.com/api/v1/admin/notifications/templates', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ group: 'account', key: 'welcome-message' }),
});

const { data } = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/notifications/templates');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['group' => 'account', 'key' => 'welcome-message']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// A new template is born EMPTY and the core never sends it by itself; you write the content and the trigger.
Api::Notifications()->CreateNotificationTemplate(['group' => 'account', 'key' => 'welcome-message']);
Api::Notifications()->UpdateNotificationTemplate([
    'group' => 'account', 'key' => 'welcome-message',
    'contents' => ['en' => ['subject' => 'Welcome', 'mail_content' => $html]],
]);

Reading a Template

get/api/v1/admin/notifications/templates/{group}/{key}
Notifications/GetNotificationTemplate admin

Returns a template's settings and its text in every language.

Response fields data — 15
groupstringThe group it sits in.
keystringThe template key.
namestringIts translated name.
statusintWhether the template is on.
customboolWhether it was added by hand.
user_mailintWhether the client gets an e-mail.
admin_mailintWhether the staff get an e-mail.
user_smsintWhether the client gets a message.
admin_smsintWhether the staff get a message.
send_pdfintWhether the invoice document is attached. It comes empty outside the invoice group.
emailsstringExtra e-mail recipients.
phonesstringExtra phone recipients.
departmentsint[]The department ids tied to it.
variablesstringThe variables the template can use.
contentsobjectThe text per language.
subjectstringThe e-mail subject.
mail_contentstringThe e-mail body.
sms_contentstringThe message text.
Errors 2
not_found404No such template.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/notifications/templates/invoice/invoice-created' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch(`https://panel.example.com/api/v1/admin/notifications/templates/${group}/${key}`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
const missing = langs.filter((l) => ! data.contents[l]?.subject);
$ch = curl_init('https://panel.example.com/api/v1/admin/notifications/templates/' . $group . '/' . $key);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The variables you may use are written here; another one written into a template goes out as TEXT.
$t = Api::Notifications()->GetNotificationTemplate(['group' => $g, 'key' => $k])['data'];
$allowed = $t['variables'];

Updating a Template

patch/api/v1/admin/notifications/templates/{group}/{key}
Notifications/UpdateNotificationTemplate admin

Writes the settings and text you send and leaves the rest alone.

Body 10
statusintWhether the template is on.
user_mailintWhether the client gets an e-mail.
admin_mailintWhether the staff get an e-mail.
user_smsintWhether the client gets a message.
admin_smsintWhether the staff get a message.
send_pdfintWhether the invoice document is attached. It is ignored outside the invoice group.
emailsstringExtra e-mail recipients.
phonesstringExtra phone recipients.
departmentsint[]The department ids. The list replaces rather than adds.
contentsobjectThe text per language.
subjectstringThe e-mail subject.
mail_contentstringThe e-mail body.
sms_contentstringThe message text.
Response fields data — 15
dataobjectThe template as it now stands. Same shape as the read endpoint.
Errors 3
not_found404No such template.
config_write_failed422The settings file could not be written.
insufficient_scope403The key lacks the required scope.
Request
curl -X PATCH 'https://panel.example.com/api/v1/admin/notifications/templates/invoice/invoice-created' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":1,"user_mail":1,"departments":[1,2]}'
const res = await fetch(`https://panel.example.com/api/v1/admin/notifications/templates/${group}/${key}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    status: 1,
    contents: { en: { subject: 'Your invoice', mail_content: html } },
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/notifications/templates/' . $group . '/' . $key);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['status' => 1]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The department list REPLACES what was there; read it first to add one.
$t = Api::Notifications()->GetNotificationTemplate(['group' => $g, 'key' => $k])['data'];
$t['departments'][] = $newDid;

Api::Notifications()->UpdateNotificationTemplate([
    'group' => $g, 'key' => $k, 'departments' => $t['departments'],
]);

Removing a Template

delete/api/v1/admin/notifications/templates/{group}/{key}
Notifications/DeleteNotificationTemplate admin

Removes a template and its text in every language.

Response fields data — 3
deletedboolWhether the delete ran.
groupstringThe group key.
keystringThe key of the template removed.
Errors 2
not_found404No such template.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/notifications/templates/account/welcome-message' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch(`https://panel.example.com/api/v1/admin/notifications/templates/${group}/${key}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/notifications/templates/' . $group . '/' . $key);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Removing one of the CORE's own templates silences that event entirely; turning the state off is enough.
Api::Notifications()->UpdateNotificationTemplate(['group' => $g, 'key' => $k, 'status' => 0]);

Pitfalls

The department list replaces what was there

The department list you send on an update replaces the one there. Sending only the department you meant to add takes the others out and they stop getting the notification. Read it first and merge the list.

An unknown variable goes out as text

The variables a template may use are written on its own record. Writing one that is not in that list raises no error; the notification goes out and the client sees the raw braces. Read the list allowed before writing the text.

A new template is never sent by itself

A template added by hand is a record and nothing more: no event in the core fires it. A module or a hook has to call it for anything to go out. Turning the template on produces no message on its own.

Two templates have their state tied to the sign-up setting

The on and off state of the e-mail and phone verification templates moves together with the sign-up verification setting. Closing the template closes the verification step in the sign-up flow as well. Changing it as though it were a display setting drops verification for new members.

The document attachment falls away quietly outside its group

The setting that attaches the invoice document works in the invoice group alone. Sending it on another group's template raises no error: the value is ignored and comes back empty on the read. That is not the save failing.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.