Sending Notifications

1k مشاهدات Markdown

The five endpoints that send a client a template, an e-mail or an SMS, and read the result back.

Overview

These endpoints send a message to a client and read back what was sent. There are three ways to send: a stored template, a free e-mail and a free SMS.

Every send is synchronous. The response comes after the dispatch attempt finishes; nothing is queued. A slow provider slows your request down with it.

Reference

Previewing the Recipients

get/api/v1/admin/clients/{id}/notifications/recipients
Clients/GetClientNotificationRecipients admin sends nothing

Returns who a template would reach, without sending anything.

Query parameters 2
templatestringThe template id, in group/name form.
channelstringemail or sms. Give it and you get only that channel's recipients.
Response fields data — 2
mailobject[]The e-mail recipients. Each element carries email and name.
smsobject[]The SMS recipients. An empty array when the client has no phone.
Errors 3
not_found404No such client.
template_invalid422template is not in group/name form.
insufficient_scope403The key lacks the required scope.
Request
curl -G 'https://panel.example.com/api/v1/admin/clients/42/notifications/recipients' \
  -H "Authorization: Bearer $API_KEY" \
  -d template=user/welcome
const url = new URL('https://panel.example.com/api/v1/admin/clients/42/notifications/recipients');
url.searchParams.set('template', 'user/welcome');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$url = 'https://panel.example.com/api/v1/admin/clients/42/notifications/recipients?' . http_build_query(['template' => 'user/welcome']);

$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);
// Check for recipients first: with none, the send returns sent: false.
$preview = Api::Clients()->GetClientNotificationRecipients([
    'id'       => 42,
    'template' => 'user/welcome',
], ['channel' => 'email']);

if (!($preview['data']['mail'] ?? [])) {
    return;
}
Response
{
  "data": {
    "mail": [
      { "email": "[email protected]", "name": "John Doe" }
    ],
    "sms": []
  }
}

Sending a Template

post/api/v1/admin/clients/{id}/notifications/template
Clients/SendClientTemplate admin synchronous

Sends a stored notification template to the client.

Body 2
templatestringrequiredThe template id, in group/name form. Both halves have to be filled: user/welcome.
channelstringemail or sms. Defaults to email.
Response fields data — 5
sentbooltrue when the client was reached on the channel. A send that reached nobody returns false with a reason, still as a 200.
reasonstringOnly when sent is false: disabled, blocked, module_not_configured, no_recipients or send_failed.
messagestringOnly when sent is false: an English explanation. For send_failed it carries the module's own error.
channelstringThe channel that was used.
templatestringId of the template.
Errors 3
not_found404No such client.
template_invalid422template is not in group/name form.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/clients/42/notifications/template' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"template":"user/welcome","channel":"email"}'
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/notifications/template', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ template: 'user/welcome', channel: 'email' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/notifications/template');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'template' => 'user/welcome',
        'channel'  => 'email',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->SendClientTemplate([
    'id'       => 42,
    'template' => 'user/welcome',
    'channel'  => 'email',
]);

Sending a Custom E-mail

post/api/v1/admin/clients/{id}/notifications/email
Clients/SendClientEmail admin synchronous

Sends an e-mail with a free subject and body, without going through a template.

Body 3
subjectstringrequiredThe subject line.
messagestringrequiredThe body.
copy_to_adminboolCopies the sending admin. Off by default.
Response fields data — 3
sentbooltrue when the client was reached. The copy to the sending admin alone does not count.
reasonstringOnly when sent is false. Same codes as the template send.
messagestringOnly when sent is false: an English explanation.
Errors 4
not_found404No such client.
subject_required422subject was empty.
message_required422message was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/clients/42/notifications/email' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"subject":"An update about your account","message":"Hello, your request has been processed.","copy_to_admin":true}'
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/notifications/email', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    subject: 'An update about your account',
    message: 'Hello, your request has been processed.',
    copy_to_admin: true,
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/notifications/email');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'subject'       => 'An update about your account',
        'message'       => 'Hello, your request has been processed.',
        'copy_to_admin' => true,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->SendClientEmail([
    'id'      => 42,
    'subject' => 'An update about your account',
    'message' => 'Hello, your request has been processed.',
]);

// sent is false when the client was not reached; reason says why.
$failed = !($response['data']['sent'] ?? false);

Sending a Custom SMS

post/api/v1/admin/clients/{id}/notifications/sms
Clients/SendClientSms admin synchronous

Sends the client an SMS with free content.

Body 2
messagestringrequiredThe message body.
copy_to_adminboolCopies the phone on the sending admin's profile. Off by default; skipped when that profile has no phone.
Response fields data — 3
sentbooltrue when the client was reached.
reasonstringOnly when sent is false. With no SMS module selected it is module_not_configured.
messagestringOnly when sent is false: an English explanation.
Errors 3
not_found404No such client.
message_required422message was empty.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/clients/42/notifications/sms' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"message":"Hello, your request has been processed."}'
const res = await fetch('https://panel.example.com/api/v1/admin/clients/42/notifications/sms', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ message: 'Hello, your request has been processed.' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/clients/42/notifications/sms');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['message' => 'Hello, your request has been processed.']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Clients()->SendClientSms([
    'id'      => 42,
    'message' => 'Hello, your request has been processed.',
]);

Reading a Sent Message

get/api/v1/admin/clients/messages/preview
Clients/GetMessagePreview admin decrypted

Returns the content of an e-mail or SMS that was sent earlier.

Query parameters 2
typestringrequiredemail ya da sms.
idintrequiredThe log record id. Not the client id, the record's own id.
Response fields data — 2
typestringThe record type.
contentstringThe decrypted message content.
Errors 2
invalid_request422type or id is missing or invalid.
insufficient_scope403The key lacks the required scope.
Request
curl -G 'https://panel.example.com/api/v1/admin/clients/messages/preview' \
  -H "Authorization: Bearer $API_KEY" \
  -d type=email \
  -d id=901
const url = new URL('https://panel.example.com/api/v1/admin/clients/messages/preview');
url.searchParams.set('type', 'email');
url.searchParams.set('id', '901');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$url = 'https://panel.example.com/api/v1/admin/clients/messages/preview?' . http_build_query(['type' => 'email', 'id' => 901]);

$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);
$response = Api::Clients()->GetMessagePreview([], [
    'type' => 'email',
    'id'   => 901,
]);

$content = $response['data']['content'];

Pitfalls

A 200 does not mean the client got it

A send that reached nobody still returns 200, with sent set to false and a reason: the template is turned off, a rule blocked it, no module is selected for the channel, the client has no address on it, or delivery failed. Branch on sent, then on reason. A copy to the sending admin does not count as sent.

A client with no address is not an error

If the client has no e-mail or phone the response is sent: false with no_recipients. To skip such clients up front, call the preview endpoint first and leave out the ones whose list comes back empty.

The request waits for the dispatch

Nothing is queued. If you are writing a batch job you pay the provider's response time for every client, so set your timeout accordingly.

هل كان هذا مفيدًا؟

شكرًا على ملاحظاتك!

هل ما زلت بحاجة إلى مساعدة؟

فريق الدعم متاح على مدار الساعة لمساعدتك في كل ما لم تجده أعلاه.