Skip to content

SMS 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, campaign jobs, and anything that already holds a persistent platform connection.

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": "SmsSendMessage",
  "extID": "8f2a1c",
  "data": {
    "sendToParentType": "CUSTOMER",
    "sendToParentId": 140,
    "phone": "+380951234567",
    "message": "Your code is 4821"
  }
}
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": {
    "smsId": 812,
    "status": "PENDING",
    "parts": 1,
    "scheduleReason": "IMMEDIATE"
  }
}

An error keeps the same envelope: the outcome is in status, and data carries the message.

{
  "extID": "8f2a1c",
  "status": 409,
  "data": "Phone 380950000000 is blacklisted: opt-out"
}

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"}.

SmsSendMessage answers as soon as the message 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 sms = await platform.SmsSendMessage({
  sendToParentType: 'CUSTOMER',
  sendToParentId: 140,
  phone: '+380951234567',
  message: 'Your code is 4821',
  kind: 'TRANSACTIONAL',
  idempotencyKey: 'login-code-140-1755000000'
});

if (sms.status === 200) {
  console.log('queued', sms.data.smsId, sms.data.parts, 'segment(s)');
} else {
  // On failure `data` is the message text, not an object.
  console.error(sms.status, sms.data);
}

idempotencyKey matters for exactly this caller: a retried HTTP request or a restarted job must not send the customer a second confirmation code. Repeating the call with the same key returns the original message with idempotent: true.

Commands

Messages

Command Description
SmsSendMessage Queue a message with an explicit text
SmsSendFromTemplate Queue a message rendered from a template
SmsSendBulk Queue up to 10 000 recipients as one campaign
SmsResendMessage Send a copy of an existing message
SmsCancelMessage Cancel a message still in the queue
SmsPreviewMessage Text, encoding and segments without sending
SmsGetMessage One message with attempts and webhook events
SmsGetMessages Message history with filters and aggregates
SmsGetStats Volume, segments, spend and delivery rate
SmsGetLastMessagesByParents Last message time for a batch of recipients

Templates and triggers

Command Description
SmsAddTemplate Create a template
SmsUpdateTemplate Update a template
SmsCloneTemplate Copy a template
SmsDeleteTemplate Delete a template
SmsGetTemplates Templates of the brand
SmsAddTrigger Subscribe an event to templates
SmsUpdateTrigger Update a trigger
SmsDeleteTrigger Delete a trigger
SmsFireTrigger Fire an event by hand
SmsGetTriggers Triggers of the brand
SmsGetTriggerSubscriptions What the module listens to

Providers, profiles and agents

Command Description
SmsGetProviderAdapters Implemented adapters and capabilities
SmsAddProvider Register a provider
SmsUpdateProvider Update a provider
SmsDeleteProvider Soft-delete a provider
SmsGetProviders Provider catalogue
SmsAddProfile Create a provider profile
SmsUpdateProfile Update a provider profile
SmsDeleteProfile Soft-delete a provider profile
SmsGetProfiles Provider profiles of the brand
SmsGetMyProfiles Profiles available to the current manager
SmsGetProfileBalance Provider balance and low-balance flags
SmsAddAgent Link a manager to a sender identity
SmsUpdateAgent Update the link
SmsDeleteAgent Remove the link
SmsGetAgents Links of the brand

Blacklist, send windows, webhooks, service

Command Description
SmsAddBlacklistPhone Blacklist a number
SmsImportBlacklistPhones Bulk import numbers
SmsDeleteBlacklistPhone Remove a number
SmsCheckBlacklistPhone Check one number
SmsGetBlacklist Blacklist entries
SmsAddSendWindow Add a send window
SmsUpdateSendWindow Update a send window
SmsDeleteSendWindow Delete a send window
SmsCheckSendWindow Whether a number can be messaged now
SmsGetSendWindows Send windows
SmsAddWebhook Create a delivery-report URL
SmsUpdateWebhook Update a webhook
SmsDeleteWebhook Delete a webhook
SmsGetWebhooks Webhooks of the brand
SmsGetWebhookEvents Raw provider events
SmsHandleWebhook Public provider endpoint (HTTP only in practice)
SmsPing Liveness probe with a problem list
SmsHealth Full module state

Events

Message progress is delivered as events on the same connection, so an integration does not poll SmsGetMessages:

Event When
sms.message.queued Message accepted into the queue
sms.message.sent Provider accepted the message
sms.message.final Delivered, undelivered, rejected, expired or failed
platform.emitter.on('sms.message.final', e => {
  console.log(e.data.smsId, e.data.status, e.data.price);
});

A message whose provider never reports a final status is closed by the module as EXPIRED, so the event always arrives and a waiting integration cannot hang forever.

Monitoring the module

SmsPing 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 messages pile up in PENDING while nothing is sent — an empty problems list is what actually means healthy.