# Managing Notification Templates

https://dev.wisecp.com/es/managing-notification-templates

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.

templatesarray templates[]The 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 JavaScript PHP (HTTP) PHP (Internal)

```bash
curl 'https://panel.example.com/api/v1/admin/notifications/templates' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
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);
```

```php
$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);
```

```php
// 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 JavaScript PHP (HTTP) PHP (Internal)

```bash
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"}'
```

```javascript
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();
```

```php
$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);
```

```php
// 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.

contentsobject contents.The 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 JavaScript PHP (HTTP) PHP (Internal)

```bash
curl 'https://panel.example.com/api/v1/admin/notifications/templates/invoice/invoice-created' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
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);
```

```php
$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);
```

```php
// 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.

contentsobject contents.The 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 JavaScript PHP (HTTP) PHP (Internal)

```bash
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]}'
```

```javascript
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();
```

```php
$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);
```

```php
// 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 JavaScript PHP (HTTP) PHP (Internal)

```bash
curl -X DELETE 'https://panel.example.com/api/v1/admin/notifications/templates/account/welcome-message' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
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();
```

```php
$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);
```

```php
// 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.

## Related Articles

- [Notification Layout](https://dev.wisecp.com/en/notification-layout)
- [Staff Departments](https://dev.wisecp.com/en/staff-departments)
- [Language Packages](https://dev.wisecp.com/en/language-packages)
