gRPC Messaging

📦v1.0.0📅2026-03-10🔄Updated 2026-04-28👤Admin Team
developergrpcprotobufsmsmessagingstreaming

SMS Service

Messaging service responsible for SMS submission and message lifecycle management.

For authentication details (JWT tokens, metadata headers, error codes), see gRPC Authentication.

Service name:

sms.v1.SmsService

SendMessage

Sends a single SMS message (unary RPC).

rpc SendMessage(SmsRequest) returns (SmsResponse)

Request Fields

FieldTypeRequiredDescription
task_idint64NoClient-defined task identifier for grouping messages (e.g., campaign ID)
transaction_idstringNoClient-defined UUID for end-to-end message tracing. If omitted, the platform generates one
app_idint64YesApplication identifier (must match app_id in metadata)
esmeint64YesTarget SMPP link ID or pool ID. Determines the routing destination
stonint32NoSource TON (Type of Number). Default: 0 (Unknown)
snpiint32NoSource NPI (Numbering Plan Indicator). Default: 0 (Unknown)
saddrstringYesSource address (sender ID) — phone number or alphanumeric string
dtonint32NoDestination TON. Default: 1 (International)
dnpiint32NoDestination NPI. Default: 1 (ISDN/E.164)
daddrstringYesDestination phone number in international format (e.g., 998901234567)
messagestringYesSMS text content. Long messages are automatically segmented
sent_atint64NoUnix timestamp indicating when the message was originally created
strategystringNoMCP contact policy strategy to apply: cp1, onbuild_cp1, cp2, blacklist. If omitted, no contact policy is applied
{
  "task_id": 11,
  "transaction_id": "550e8400-e29b-41d4-a716-446655440000",
  "app_id": 1,
  "esme": 1000,
  "ston": 0,
  "snpi": 5,
  "saddr": "MYBRAND",
  "dnpi": 1,
  "dton": 1,
  "daddr": "998901234567",
  "message": "Hello World",
  "sent_at": 1937082918,
  "strategy": "cp1"
}

Response Fields

FieldTypeDescription
successbooltrue if the message was accepted for delivery
errorstringError description if submission failed, empty string on success
esmeint64SMPP link ID that was used for routing (may differ from request if a pool was specified)
transaction_idstringTransaction identifier for end-to-end tracing
message_idstringPlatform-generated message identifier for delivery tracking
statusstringSubmission status: submitted, or MCP rejection reason (daily_cp, weekly_cp, duplicate, blacklist)
sms_idsrepeated stringSMSC-assigned IDs for each message segment. Multiple IDs indicate the message was split into parts
task_idint64Echoed task identifier from the request
{
  "success": true,
  "error": "",
  "esme": 1000,
  "transaction_id": "550e8400-e29b-41d4-a716-446655440000",
  "message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "submitted",
  "sms_ids": [
    "smsc-seg-001"
  ],
  "task_id": 11
}

Processing Pipeline

This method performs the full SMS processing pipeline:

  1. Authentication — validates JWT token and app_id
  2. Rate limiting — checks L1 (in-process) and L2 (Redis) limits
  3. Contact policy — validates against MCP strategy (if specified)
  4. SMPP routing — selects target link or load-balances across pool
  5. Submission — sends message to SMSC over SMPP v3.4
  6. Persistence — stores message state in Aerospike for delivery tracking

grpcurl Example

grpcurl \
  -plaintext \
  -H 'authorization: Bearer <jwt-token>' \
  -H 'app_id: 1' \
  -d '{
    "app_id": 1,
    "esme": 1000,
    "saddr": "MYBRAND",
    "daddr": "998901234567",
    "message": "Hello from gRPC",
    "strategy": "cp1"
  }' \
  127.0.0.1:44044 \
  sms.v1.SmsService/SendMessage

SendMessageStream

Bidirectional streaming interface for high-throughput message submission.

rpc SendMessageStream(stream SmsRequest) returns (stream SmsResponse)

Description

Allows clients to maintain a persistent gRPC connection and send multiple SMS messages over a single stream. Each incoming SmsRequest produces a corresponding SmsResponse.

This is the recommended method for high-volume integrations because it eliminates the overhead of establishing a new connection for each message.

When to Use Streaming

ScenarioRecommended Method
Sending a single messageSendMessage (unary)
Campaign with hundreds or thousands of messagesSendMessageStream (streaming)
Real-time event-driven messagingSendMessageStream (streaming)
Simple integration or testingSendMessage (unary)

Request and Response

The request and response messages are the same as SendMessageSmsRequest and SmsResponse. The only difference is the transport: messages flow continuously in both directions over a single connection.

Example: Go Client

// Establish a streaming connection
stream, err := client.SendMessageStream(ctx)
if err != nil {
    log.Fatal(err)
}

// Send messages
for _, msg := range messages {
    err := stream.Send(&pb.SmsRequest{
        AppId:         1,
        Esme:          1000,
        Saddr:         "MYBRAND",
        Daddr:         msg.Phone,
        Message:       msg.Text,
        TransactionId: msg.TxID,
        Strategy:      "cp1",
    })
    if err != nil {
        log.Printf("send error: %v", err)
        break
    }

    // Receive response for each sent message
    resp, err := stream.Recv()
    if err != nil {
        log.Printf("recv error: %v", err)
        break
    }
    log.Printf("message %s: %s", resp.TransactionId, resp.Status)
}

stream.CloseSend()

Example: Python Client

import grpc
import sms_pb2, sms_pb2_grpc

channel = grpc.insecure_channel("127.0.0.1:44044")
stub = sms_pb2_grpc.SmsServiceStub(channel)

metadata = [
    ("authorization", "Bearer <jwt-token>"),
    ("app_id", "1"),
]

def message_generator():
    for phone, text in messages:
        yield sms_pb2.SmsRequest(
            app_id=1,
            esme=1000,
            saddr="MYBRAND",
            daddr=phone,
            message=text,
            strategy="cp1",
        )

responses = stub.SendMessageStream(message_generator(), metadata=metadata)
for resp in responses:
    print(f"{resp.transaction_id}: {resp.status}")

CheckESME

Checks the availability of a specific SMPP link.

rpc CheckESME(CheckESMERequest) returns (CheckESMEResponse)

Request Fields

FieldTypeRequiredDescription
esmeint64YesSMPP link ID to check
{
  "esme": 101
}

Response Fields

FieldTypeDescription
persistbooltrue if the SMPP connection is currently active
system_idstringSMPP system ID of the connected SMSC
{
  "persist": true,
  "system_id": "smpp-client-1"
}

Use this endpoint to verify SMPP connectivity before sending messages. A persist: false response indicates the link is disconnected — the proxy will automatically reconnect when the SMSC becomes available.


CheckTextLen

Analyzes SMS text and calculates encoding and segmentation.

rpc CheckTextLen(CheckTextLenRequest) returns (CheckTextLenResponse)

Request Fields

FieldTypeRequiredDescription
textstringYesSMS text content to analyze
{
  "text": "Hello World"
}

Response Fields

FieldTypeDescription
errorstringError description if analysis failed, empty string on success
encodestringDetected encoding: GSM7 (standard 7-bit) or UCS2 (Unicode 16-bit)
symbolsint32Number of characters in the message
partsint32Number of SMS segments required to deliver the message
{
  "error": "",
  "encode": "GSM7",
  "symbols": 11,
  "parts": 1
}

Segmentation Rules

SMS messages have character limits that depend on encoding:

EncodingSingle SMSEach Segment (multipart)
GSM7 (Latin, digits, basic symbols)160 characters153 characters
UCS2 (Cyrillic, Arabic, emoji, CJK)70 characters67 characters

When a message exceeds the single SMS limit, it is automatically split into segments. The reduced per-segment limit accounts for the User Data Header (UDH) used for reassembly.

Use this endpoint to preview segmentation before sending — for example, to estimate costs or warn users about multipart messages in a UI.


SmsInfo

Returns delivery information about a previously sent message.

rpc SmsInfo(SmsStatusRequest) returns (SmsStatusResponse)

Request Fields

FieldTypeRequiredDescription
esmeint64YesSMPP link ID the message was sent through
message_idstringYesMessage identifier returned by SendMessage or SendMessageStream
{
  "esme": 100,
  "message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Response Fields

FieldTypeDescription
message_idstringPlatform message identifier
modestringsingle for single-segment SMS, multipart for segmented messages
partsmap<string, string>Per-segment delivery status. Key is the segment number (1-based), value is the delivery status
delivered_countint32Number of segments that have been delivered
sent_atint64Unix timestamp when the message was submitted
updated_atint64Unix timestamp of the last status update
transaction_idstringEnd-to-end transaction identifier
task_idint64Client-defined task identifier
statusstringOverall message status (see table below)
errorstringError description if the query failed
{
  "message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "mode": "single",
  "parts": {
    "1": "DELIVERED"
  },
  "delivered_count": 1,
  "sent_at": 1937082918,
  "updated_at": 1937082925,
  "transaction_id": "550e8400-e29b-41d4-a716-446655440000",
  "task_id": 11,
  "status": "DELIVERED",
  "error": ""
}

Message Status Values

StatusDescription
submittedMessage was sent to the SMSC, waiting for delivery receipt
DELIVEREDMessage was successfully delivered to the recipient
UNDELIVERABLESMSC reported the message could not be delivered
EXPIREDDelivery timed out before the SMSC confirmed receipt
REJECTEDSMSC rejected the message

gRPC Request Lifecycle

A typical gRPC request follows the same processing pipeline as REST:

Client
 ↓
Authentication Interceptor (JWT + app_id validation)
 ↓
L1 Rate Limiter (in-process)
 ↓
L2 Distributed Rate Limiter (Redis)
 ↓
Contact Policy (MCP, if strategy is specified)
 ↓
SMPP Router (link selection or pool load balancing)
 ↓
SMSC

Each stage validates and processes the message before forwarding it to the next component. If any stage rejects the message, the response is returned immediately with the appropriate error.


Service Summary

ServiceMethodTypeDescription
SmsServiceSendMessageUnarySend a single SMS message
SmsServiceSendMessageStreamBidirectional streamingHigh-throughput streaming submission
SmsServiceCheckESMEUnaryCheck SMPP link availability
SmsServiceCheckTextLenUnaryAnalyze text encoding and segmentation
SmsServiceSmsInfoUnaryQuery message delivery status