Bulk Templates

7 views Markdown

The six endpoints that manage reusable bulk notification campaigns.

Overview

A bulk template is a campaign saved for reuse: the message, the subject, the channel and the audience filters kept together. Instead of rebuilding the same announcement each time, you write it once and store it.

A template sends nothing on its own. Sending happens on a separate endpoint, and sending one on a regular basis is what scheduled tasks are for.

Reference

Listing the Templates

get/api/v1/admin/tools/bulk/templates
Tools/GetBulkTemplates admin paged

Returns the saved bulk notification campaigns.

Query parameters 4
template_typestringFilters by channel.
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
searchstringSearches the templates.
Response fields data[] — 10
idintId of the template.
template_namestringThe template name. For you only; the client never sees it.
template_typestringThe channel: mail or sms.
typestringThe audience: member for clients, staff for staff.
subjectstringThe message subject.
submission_typestringThe envelope: single one each, multiple all together.
newsletterstringThe newsletter key. When filled, the newsletter list is used instead of the filters.
created_atstring | nullWhen it was created.
updated_atstring | nullWhen it last changed.
last_sentstring | nullWhen it was last sent.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl -G 'https://panel.example.com/api/v1/admin/tools/bulk/templates' \
  -H "Authorization: Bearer $API_KEY" \
  -d template_type=mail
const url = new URL('https://panel.example.com/api/v1/admin/tools/bulk/templates');
url.searchParams.set('template_type', 'mail');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$url = 'https://panel.example.com/api/v1/admin/tools/bulk/templates?' . http_build_query(['template_type' => 'mail']);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The list carries neither the message body nor the filters; those come on the detail only.
$templates = Api::Tools()->GetBulkTemplates([], ['template_type' => 'mail'])['data'];

Template Detail

get/api/v1/admin/tools/bulk/templates/{id}
Tools/GetBulkTemplate admin the filters are here

Returns a campaign with its message and its audience filters.

Response fields data — 24
idintId of the template.
template_namestringThe template name. For you only; the client never sees it.
template_typestringThe channel: mail or sms.
typestringThe audience: member for clients, staff for staff.
subjectstringThe message subject.
submission_typestringThe envelope: single one each, multiple all together.
newsletterstringThe newsletter key. When filled, the newsletter list is used instead of the filters.
created_atstring | nullWhen it was created.
updated_atstring | nullWhen it last changed.
last_sentstring | nullWhen it was last sent.
messagestringThe message body.
ccstringAddresses to copy in.
without_productsintTargets clients with no product at all.
birthday_marketingintTargets clients whose birthday it is.
auto_submissionintWhether the template is sent on its own by a scheduled task.
user_groupsarrayThe client group filter.
departmentsarrayThe department filter.
countriesarrayThe country filter.
languagesarrayThe language filter.
servicesarrayThe product filter.
serversarrayThe server filter.
addonsarrayThe add-on filter.
services_statusarrayThe service status filter.
client_statusarrayThe client status filter.
Errors 3
invalid_id422The id is not valid.
not_found404No such template.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/tools/bulk/templates/5' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/tools/bulk/templates/5', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/bulk/templates/5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// To see how many a template would reach, hand its filters to the counting endpoint.
$tpl   = Api::Tools()->GetBulkTemplate(['id' => 5])['data'];
$count = Api::Tools()->GetBulkContacts([
    'user_type'   => $tpl['type'] === 'staff' ? 'staff' : 'client',
    'user_groups' => $tpl['user_groups'],
    'countries'   => $tpl['countries'],
])['data']['count'];

Creating a Template

post/api/v1/admin/tools/bulk/templates
Tools/CreateBulkTemplate admin 201

Saves a campaign to reuse. Saving sends nothing.

Body 11
template_namestringrequiredThe template name.
messagestringrequiredThe message body.
subjectstringThe message subject. Required on e-mail.
template_typestringThe channel. It defaults to e-mail.
typestringThe audience. Whatever you send for clients is stored as member.
submission_typestringThe envelope form.
newsletterstringThe newsletter key.
ccstringAddresses to copy in.
without_productsintTargets clients with no product at all.
birthday_marketingintTargets clients whose birthday it is.
*arrayThe nine filter arrays: groups, departments, countries, languages, products, servers, add-ons, service status and client status.
Response fields data — 24
dataobjectThe campaign saved, with the filter arrays already decoded. Same shape as the detail endpoint. To send it, hand the new id to the submit endpoint or give it a schedule.
Errors 4
template_name_required422The template name was empty.
subject_required422The subject was empty on an e-mail.
body_required422The message body was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/tools/bulk/templates' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"template_name":"Welcome Campaign","template_type":"mail","type":"member","subject":"Welcome","message":"Hello!","user_groups":[1]}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/bulk/templates', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    template_name: 'Welcome Campaign',
    template_type: 'mail',
    type: 'member',
    subject: 'Welcome',
    message: 'Hello!',
    user_groups: [1],
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/bulk/templates');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'template_name' => 'Welcome Campaign',
        'subject'       => 'Welcome',
        'message'       => $html,
        'user_groups'   => [1],
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Saving a template SENDS NOTHING: call the bulk submit endpoint separately to send it.
$tpl = Api::Tools()->CreateBulkTemplate([
    'template_name' => 'Welcome Campaign',
    'subject'       => 'Welcome',
    'message'       => $html,
    'user_groups'   => [1],
])['data'];

Updating a Template

patch/api/v1/admin/tools/bulk/templates/{id}
Tools/UpdateBulkTemplate admin

Applies the fields you send; the name, the message and the subject cannot be emptied.

Body 11
template_namestringrequiredThe template name.
messagestringrequiredThe message body.
subjectstringThe message subject. Required on e-mail.
template_typestringThe channel. It defaults to e-mail.
typestringThe audience. Whatever you send for clients is stored as member.
submission_typestringThe envelope form.
newsletterstringThe newsletter key.
ccstringAddresses to copy in.
without_productsintTargets clients with no product at all.
birthday_marketingintTargets clients whose birthday it is.
*arrayThe nine filter arrays: groups, departments, countries, languages, products, servers, add-ons, service status and client status.
Response fields data — 24
dataobjectThe campaign as it now stands, with the filter arrays already decoded. Same shape as the detail endpoint.
Errors 5
not_found404No such template.
template_name_required422The name you sent was empty.
subject_required422The subject you sent was empty.
body_required422The message you sent was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X PATCH 'https://panel.example.com/api/v1/admin/tools/bulk/templates/5' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"subject":"Welcome (updated)","message":"Hi there!"}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/bulk/templates/5', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    subject: 'Welcome (updated)',
    message: 'Hi there!',
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/bulk/templates/5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'subject' => 'Welcome (updated)',
        'message' => $html,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// If a scheduled task points at this template, the change takes effect on its NEXT run.
Api::Tools()->UpdateBulkTemplate([
    'id'      => 5,
    'subject' => 'Welcome (updated)',
]);

Deleting a Template

delete/api/v1/admin/tools/bulk/templates/{id}
Tools/DeleteBulkTemplate admin its records go too

Deletes the campaign and the send records belonging to it.

Response fields data — 2
deletedboolWhether the delete succeeded.
idintId of the deleted template.
Errors 2
not_found404No such template.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/tools/bulk/templates/5' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/tools/bulk/templates/5', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/bulk/templates/5');
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);
// The delete also removes the campaign's SEND HISTORY; when it went and to whom is lost.
Api::Tools()->DeleteBulkTemplate(['id' => 5]);

Deleting in Bulk

post/api/v1/admin/tools/bulk/templates/bulk-delete
Tools/BulkDeleteBulkTemplates admin the panel asks for a password

Deletes several campaigns.

Body 1
idsint[]requiredIds of the templates to delete.
Response fields data — 2
deletedboolWhether the delete ran.
countintHow many templates were deleted.
Errors 2
ids_required422No id was given.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/tools/bulk/templates/bulk-delete' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"ids":[5,6,7]}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/bulk/templates/bulk-delete', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ ids: [5, 6, 7] }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/bulk/templates/bulk-delete');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['ids' => [5, 6, 7]]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The panel asks for the admin password here; on the API the key's scope is enough.
Api::Tools()->BulkDeleteBulkTemplates(['ids' => [5, 6, 7]]);

Pitfalls

Saving is not sending

Creating or updating a template sends no message; it only writes the record. Sending the campaign means calling the bulk submit endpoint separately, and sending it regularly means defining a scheduled task.

The filters are not in the list

The list endpoint does not return the message body or the nine filter arrays; those come only on a single template's detail. Seeing who a campaign would reach means reading the detail and handing its filters to the counting endpoint.

Deleting takes the send history too

Deleting a template removes not only the campaign but the send records that belong to it. Which announcement went when, and to whom, is lost. If you are merely done with a campaign, consider leaving it in place rather than deleting it.

A change takes effect on the next run

When a scheduled task points at a template, updating it sends nothing at that moment; the new text is used on the next run. Correcting a wrong text does nothing about the sends that already went out.

The panel asks for a password, the API for a scope

The bulk delete asks for the admin password in the panel. The API has no such second step: the key's scope is enough. Hand out a key carrying this scope knowing exactly who holds it.

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.