SMS Events
SMS events track the full lifecycle of messages and bulk campaigns on PBXware in real time. Each SMS message is self-contained. A single event captures everything about one message.
Message Events
Two event types cover the two directions of SMS traffic. Outbound messages fire a second event when the gateway reports a delivery outcome, so a single sent message can produce up to two event_sms_message_sent events.
Inbound:
[Gateway receives message] ──→ event_sms_message_received
Outbound:
[Extension sends message]
│
↓
event_sms_message_sent (status: SENT)
│
↓ (gateway reports back)
event_sms_message_sent (status: DELIVERED or FAILED)
| Event | When it fires |
|---|---|
event_sms_message_received | An inbound message arrives at the gateway |
event_sms_message_sent | An outbound message is submitted to the gateway (SENT), and again when the gateway reports a delivery outcome (DELIVERED or FAILED) |
Common Payload Fields
All message events include these fields:
| Field | Type | Description |
|---|---|---|
uid | String | Unique identifier of the SMS message |
gateway_id | Number | SMS gateway used to send or receive the message |
extension | String | Extension associated with the message event |
from_number | String | Sender's SMS number |
to_number | String | Recipient's SMS number |
body | String | Text content of the message |
type | String | SMS or MMS |
event_sms_message_received · Full spec
Fires when PBXware receives an inbound SMS message.
Additional field:
| Field | Type | Description |
|---|---|---|
associated_extensions | Array of Strings | All extensions configured for the receiving SMS number — useful when one number is shared by multiple agents |
event_sms_message_sent · Full spec
Fires when an extension sends an outbound SMS, and again when the gateway reports a delivery update.
Additional field:
| Field | Type | Possible values | Description |
|---|---|---|---|
status | String | SENT, DELIVERED, FAILED | Delivery state of the outbound message |
Two firings:
event_sms_message_sentfires once when the message is submitted to the gateway (SENT) and again when the gateway confirms delivery or failure (DELIVEREDorFAILED). AFAILEDstatus means the gateway could not deliver the message to the recipient. Both events carry the sameuid— use it to correlate the delivery update to the original send.
Campaign Events
Bulk SMS campaigns produce two event types: one when the campaign starts, and one after each batch of messages is dispatched. A campaign with many recipients may produce several batch events.
event_sms_campaign_started
│
└──(1 or more)─→ event_sms_campaign_messages_batch_sent
| Event | When it fires |
|---|---|
event_sms_campaign_started | The campaign begins — fires once regardless of recipient count |
event_sms_campaign_messages_batch_sent | After each batch of messages is dispatched; a large campaign produces multiple batch events |
Common Payload Fields
All campaign events include these fields:
| Field | Type | Description |
|---|---|---|
campaign_id | String | Unique identifier of the bulk SMS campaign |
sms_number | String | Sender SMS number used for the campaign |
message | String | Campaign message content |
event_sms_campaign_started · Full spec
Fires when a bulk SMS campaign starts. Fires once per campaign regardless of recipient count. The payload contains the common campaign fields only.
event_sms_campaign_messages_batch_sent · Full spec
Fires after each batch of messages is dispatched. Totaling successful + failed across all batch events for a campaign_id gives the overall campaign result.
Additional fields:
| Field | Type | Description |
|---|---|---|
successful | Number | Messages successfully sent in this batch |
failed | Number | Messages that failed to send in this batch |
UID Correlation
Message events: Both event_sms_message_sent firings for the same outbound message carry an identical uid. Store the record on the SENT event and look it up by uid when the DELIVERED or FAILED event arrives.
Campaign events: All events for the same campaign share the same campaign_id. Use it to group event_sms_campaign_started with every subsequent event_sms_campaign_messages_batch_sent.
Example: Inbound SMS
An external number sends an SMS to extension 1001.
| # | Event | uid | Notes |
|---|---|---|---|
| 1 | event_sms_message_received | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | Message arrives on gateway 390; associated_extensions lists all extensions linked to the receiving SMS number |
Raw event payload
{
"event": "event_sms_message_received",
"event_id": "69b32e0c-77e0-42d8-b6d1-3941e1bcea0d",
"spec_version": "1.0",
"tenant_code": "200",
"event_time_info": { "timestamp": 1742306400, "date": "2026-03-18", "time": "14:00:00" },
"payload": {
"uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"gateway_id": 390,
"extension": "1001",
"from_number": "+15559876543",
"to_number": "+15551234567",
"body": "Hello, your appointment is confirmed for tomorrow.",
"type": "SMS",
"associated_extensions": ["1001", "1002"]
}
}
Example: Outbound SMS — Send and Delivery
Extension 1001 sends a message. Two events are emitted: the first when the message is submitted, the second when the gateway confirms delivery.
+0s +15s
EXT 1001 ●────────────────────────────────●
SENT DELIVERED
| # | Event | uid | status | Notes |
|---|---|---|---|---|
| 1 | event_sms_message_sent | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | SENT | Message submitted to gateway |
| 2 | event_sms_message_sent | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | DELIVERED | Gateway confirms delivery |
Raw event payloads
{
"event": "event_sms_message_sent",
"event_id": "69b32e0c-77e0-42d8-b6d1-3941e1bcea0d",
"spec_version": "1.0",
"tenant_code": "200",
"event_time_info": { "timestamp": 1742306400, "date": "2026-03-18", "time": "14:00:00" },
"payload": {
"uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"gateway_id": 387,
"extension": "1001",
"from_number": "+15551234567",
"to_number": "+15559876543",
"body": "Hello, your appointment is confirmed for tomorrow.",
"type": "SMS",
"status": "SENT"
}
}
{
"event": "event_sms_message_sent",
"event_id": "c3d21f4a-88b1-4e92-a01f-6c7d8e9f0a1b",
"spec_version": "1.0",
"tenant_code": "200",
"event_time_info": { "timestamp": 1742306415, "date": "2026-03-18", "time": "14:00:15" },
"payload": {
"uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"gateway_id": 387,
"extension": "1001",
"from_number": "+15551234567",
"to_number": "+15559876543",
"body": "Hello, your appointment is confirmed for tomorrow.",
"type": "SMS",
"status": "DELIVERED"
}
}
Example: Campaign Batch
A campaign starts and dispatches a batch of 1000 messages.
| # | Event | campaign_id | Notes |
|---|---|---|---|
| 1 | event_sms_campaign_started | 42 | Campaign begins; message content and sender number are set |
| 2 | event_sms_campaign_messages_batch_sent | 42 | First batch dispatched: 950 delivered, 50 failed |
Raw event payloads
{
"event": "event_sms_campaign_started",
"event_id": "69b32e0c-77e0-42d8-b6d1-3941e1bcea0d",
"spec_version": "1.0",
"tenant_code": "200",
"event_time_info": { "timestamp": 1742306400, "date": "2026-03-18", "time": "14:00:00" },
"payload": {
"campaign_id": "42",
"sms_number": "+15551234567",
"message": "Hello, your appointment is confirmed for tomorrow."
}
}
{
"event": "event_sms_campaign_messages_batch_sent",
"event_id": "d4e32a5b-99c2-5f03-b12e-7d8e9f0a1b2c",
"spec_version": "1.0",
"tenant_code": "200",
"event_time_info": { "timestamp": 1742306460, "date": "2026-03-18", "time": "14:01:00" },
"payload": {
"campaign_id": "42",
"sms_number": "+15551234567",
"message": "Hello, your appointment is confirmed for tomorrow.",
"successful": 950,
"failed": 50
}
}
Integration Examples
Log Incoming SMS to CRM
app.post('/webhook', (req, res) => {
res.sendStatus(200); // acknowledge immediately
const { event, payload, event_id } = req.body;
if (event !== 'event_sms_message_received') return;
crm.logMessage({
idempotencyKey: event_id, // prevent duplicate logging on retries
messageId: payload.uid,
from: payload.from_number,
to: payload.to_number,
extension: payload.extension,
body: payload.body,
type: payload.type,
});
});
Track Outbound Delivery Status
Use the uid field to correlate the initial send event with the subsequent delivery update.
const pendingMessages = new Map(); // uid → message record
app.post('/webhook', (req, res) => {
res.sendStatus(200);
const { event, payload } = req.body;
if (event !== 'event_sms_message_sent') return;
if (payload.status === 'SENT') {
pendingMessages.set(payload.uid, {
to: payload.to_number,
extension: payload.extension,
body: payload.body,
sentAt: Date.now(),
});
}
if (payload.status === 'DELIVERED' || payload.status === 'FAILED') {
const msg = pendingMessages.get(payload.uid);
if (msg) {
analytics.recordDelivery({
messageId: payload.uid,
status: payload.status,
to: msg.to,
latencyMs: Date.now() - msg.sentAt,
});
pendingMessages.delete(payload.uid);
}
}
});
Campaign Progress Monitoring
Accumulate batch results to track overall campaign delivery and alert on high failure rates.
const campaignTotals = new Map(); // campaign_id → { successful, failed }
app.post('/webhook', (req, res) => {
res.sendStatus(200);
const { event, payload } = req.body;
if (event === 'event_sms_campaign_started') {
campaignTotals.set(payload.campaign_id, { successful: 0, failed: 0 });
}
if (event === 'event_sms_campaign_messages_batch_sent') {
const totals = campaignTotals.get(payload.campaign_id) ?? { successful: 0, failed: 0 };
totals.successful += payload.successful;
totals.failed += payload.failed;
campaignTotals.set(payload.campaign_id, totals);
const failRate = totals.failed / (totals.successful + totals.failed);
if (failRate > 0.1) {
alerts.send({
subject: `High failure rate in campaign ${payload.campaign_id}`,
body: `${(failRate * 100).toFixed(1)}% of messages failed (${totals.failed} failed, ${totals.successful} delivered).`,
});
}
}
});