Mailer TCP API¶
The TCP transport addresses a module method by command name. It is the entry point for server-to-server integrations: CRM backends, notification services, statement jobs, campaign schedulers.
The same methods are available over HTTP — see REST API. The command name and the HTTP path are two addresses of one method, with identical fields and results.
Request envelope¶
{
"command": "MailerSendEmail",
"extID": "8f2a1c",
"data": {
"sendToParentType": "CUSTOMER",
"sendToParentId": 140,
"to": "[email protected]",
"templateId": 4,
"data": { "name": "John", "amount": "250 EUR" }
}
}
| Field | Type | Description |
|---|---|---|
command |
string | Method name, exactly as published by the module |
extID |
string | Caller-generated correlation id; the response carries it back |
data |
object | Method parameters |
extID is what makes the connection full-duplex: responses and streamed events share one
socket, so a reply is matched to its request by extID rather than by arrival order.
Response¶
{
"extID": "8f2a1c",
"status": 200,
"data": {
"emailId": 812,
"status": "PENDING",
"scheduleReason": "IMMEDIATE",
"idempotent": false
}
}
An error keeps the same envelope: the outcome is in status, and data carries the message.
{
"extID": "8f2a1c",
"status": 403,
"data": "Address [email protected] is suppressed: HARD_BOUNCE"
}
Status codes are the same as in REST. 502 means the module itself is
not on the bus — the platform answers instead of hanging the request. A malformed request never
reaches the module and comes back as 400 with {"error": "NO_COMMAND_OR_EXT_ID"} or
{"error": "INVALID_JSON_OBJECT"}.
MailerSendEmail answers as soon as the email is queued, not when it is delivered. The
delivery outcome arrives later as an event.
Node.js SDK¶
scaletrade-server-api exposes any
published command as a method, so no client update is needed when a module adds methods:
const STPlatform = require('scaletrade-server-api');
const platform = new STPlatform(
'broker.scaletrade.com:8080',
'notification-service',
{},
null, null,
'your-jwt-auth-token'
);
const mail = await platform.MailerSendEmail({
sendToParentType: 'CUSTOMER',
sendToParentId: 140,
to: '[email protected]',
templateId: 4,
data: { name: 'John', amount: '250 EUR' },
kind: 'TRANSACTIONAL',
idempotencyKey: 'deposit-140-1755000000'
});
if (mail.status === 200) {
console.log('queued', mail.data.emailId);
} else {
// On failure `data` is the message text, not an object.
console.error(mail.status, mail.data);
}
idempotencyKey matters for exactly this caller: a retried request or a restarted job must not
send the customer a second confirmation email. Repeating the call with the same key returns the
original email with idempotent: true.
Commands¶
Emails¶
| Command | Description |
|---|---|
| MailerSendEmail | Queue one email |
| MailerSendBulk | Queue up to 10 000 recipients |
| MailerResendEmail | Send a copy of an existing email |
| MailerCancelEmail | Cancel an email still in the queue |
| MailerPreviewEmail | Assemble the message without sending |
| MailerLintEmail | Pre-send warnings |
| MailerSendTestEmail | Send a test to your own address |
| MailerFindEmail | Find emails by address, provider id or campaign |
| MailerGetEmail | One email with attempts and events |
| MailerGetEmails | Email history with filters and aggregates |
| MailerGetStats | Delivery, bounce, complaint, open and click rates |
| MailerGetLastEmailsByParents | Last email time for a batch of recipients |
Campaigns¶
| Command | Description |
|---|---|
| MailerAddCampaign | Create a campaign over a CRM segment |
| MailerUpdateCampaign | Update a campaign |
| MailerCancelCampaign | Stop a campaign and its queued emails |
| MailerResumeCampaign | Continue an interrupted campaign |
| MailerEstimateCampaignRecipients | Count recipients before the rollout |
| MailerDeleteCampaign | Delete a campaign |
| MailerGetCampaigns | Campaigns with rollout progress |
Templates and triggers¶
| Command | Description |
|---|---|
| MailerAddTemplate | Create a template |
| MailerUpdateTemplate | Update a template |
| MailerCloneTemplate | Copy a template |
| MailerDeleteTemplate | Delete a template |
| MailerGetTemplates | Templates of the brand |
| MailerAddTrigger | Subscribe an event to templates |
| MailerUpdateTrigger | Update a trigger |
| MailerDeleteTrigger | Delete a trigger |
| MailerFireTrigger | Fire an event by hand |
| MailerGetTriggers | Triggers of the brand |
| MailerGetTriggerSubscriptions | What the module listens to |
Providers, profiles and agents¶
| Command | Description |
|---|---|
| MailerGetProviderAdapters | Implemented adapters and capabilities |
| MailerAddProvider | Register a provider |
| MailerUpdateProvider | Update a provider |
| MailerDeleteProvider | Soft-delete a provider |
| MailerGetProviders | Provider catalogue |
| MailerAddProfile | Create a provider profile |
| MailerUpdateProfile | Update a provider profile |
| MailerDeleteProfile | Soft-delete a provider profile |
| MailerGetProfiles | Profiles with domain and pause state |
| MailerGetMyProfiles | Profiles available to the current manager |
| MailerGetProfileBalance | Provider quota and low-balance flags |
| MailerVerifyProfileDomain | DKIM and SPF state of the sender domain |
| MailerAddAgent | Link a manager to a sender address |
| MailerUpdateAgent | Update the link |
| MailerDeleteAgent | Remove the link |
| MailerGetAgents | Links of the brand |
Suppressions, send windows, webhooks, service¶
| Command | Description |
|---|---|
| MailerAddSuppression | Suppress an address |
| MailerImportSuppressions | Import a suppression list |
| MailerDeleteSuppression | Remove a suppression |
| MailerCheckSuppression | Check an address before sending |
| MailerGetSuppressions | Suppression entries |
| MailerHandleUnsubscribe | Public one-click unsubscribe (HTTP in practice) |
| MailerAddSendWindow | Add a send window |
| MailerUpdateSendWindow | Update a send window |
| MailerDeleteSendWindow | Delete a send window |
| MailerCheckSendWindow | Whether a country can be emailed now |
| MailerGetSendWindows | Send windows |
| MailerAddWebhook | Create a provider event URL |
| MailerUpdateWebhook | Update a webhook |
| MailerDeleteWebhook | Delete a webhook |
| MailerGetWebhooks | Webhooks of the brand |
| MailerGetWebhookEvents | Raw provider events |
| MailerHandleWebhook | Public provider endpoint (HTTP in practice) |
| MailerPing | Liveness probe with a problem list |
| MailerHealth | Full module state |
Events¶
Email progress is delivered as events on the same connection, so an integration does not poll
MailerGetEmails:
| Event | When |
|---|---|
mailer.email.queued |
Email accepted into the queue |
mailer.email.sent |
Provider accepted the email |
mailer.email.final |
Delivered, bounced, complained, rejected, expired or failed |
mailer.email.engagement |
Open or click recorded |
mailer.recipient.unsubscribed |
Recipient unsubscribed |
mailer.profile.paused |
Profile paused by the reputation guard |
platform.emitter.on('mailer.email.final', e => {
console.log(e.data.emailId, e.data.status, e.data.bounceType);
});
platform.emitter.on('mailer.profile.paused', e => {
console.error('sending paused:', e.data.profileId, e.data.reason);
});
Two of these deserve a subscriber in any serious integration. mailer.email.final with
status: "BOUNCED" is how a CRM learns that an address is dead. mailer.profile.paused means
the module stopped sending through a profile because its bounce or complaint rate crossed the
threshold — nobody else will notice that the confirmation emails stopped going out.
An email whose provider never reports a final event is closed by the module as EXPIRED, so the
event always arrives and a waiting integration cannot hang forever.
Monitoring the module¶
MailerPing is the probe to call from a monitor: it answers ok plus a problems list and
costs one SELECT 1. A process that answers on the bus can still have lost its database or its
queue cron, and in that state emails pile up in PENDING while nothing is sent — an empty
problems list is what actually means healthy.
MailerHealth adds what a probe cannot: the queue depth, the
per-profile bounce and complaint rates, and how many emails sit in SENT with no delivery
event.