Salami Gateway supports receiving inbound SMS messages through three mechanisms: provider push endpoints, the SmsSync protocol, and the MSync protocol.
Most cloud-based SMS providers send inbound messages by pushing HTTP requests to a configured URL.
ANY /api/sms/apps/{sms_app}/receive
No Bearer token required. This endpoint is called directly by SMS providers.
| Parameter | Type | Description |
|---|---|---|
sms_app |
integer | SMS App ID |
https://your-domain.com/api/sms/apps/{app_id}/receive
Message record.folder: inbox.IpnCallReceived event fires, triggering webhooks and Slack notifications.Twilio: Set the "A Message Comes In" webhook URL in your Twilio phone number settings.
Africa's Talking: Configure the callback URL in the Africa's Talking dashboard under SMS > Callback URLs > Incoming Messages.
Vonage: Set the inbound SMS webhook URL in your Vonage application settings.
The response format varies by provider. Salami returns the appropriate response expected by each provider (e.g., TwiML for Twilio, empty 200 for most others).
{
"data": {
"id": 200,
"to": "+15551234567",
"from": "254712345678",
"message": "Hello from customer",
"status": "delivered",
"folder": "inbox",
"channel": "sms",
"app_id": 1,
"created_at": "2026-03-15T15:00:00.000000Z"
}
}
| Code | Description |
|---|---|
200 |
Message received and processed |
404 |
SMS App not found |
500 |
Processing error |
SMSSync is an open-source Android app that turns a phone into an SMS gateway. The phone sends received messages to your server and fetches outbound messages to send.
ANY /api/sms/smssync
No Bearer token required. The SmsSync app authenticates via its own secret/key mechanism.
https://your-domain.com/api/sms/smssync
The SmsSync app POSTs received messages with these parameters:
| Parameter | Type | Description |
|---|---|---|
from |
string | Sender's phone number |
message |
string | SMS message body |
sent_timestamp |
string | Timestamp when the SMS was received |
sent_to |
string | Phone number of the device |
message_id |
string | Unique message ID from the phone |
device_id |
string | Device identifier |
secret |
string | Shared secret for authentication |
Example request from SmsSync app:
POST /api/sms/smssync
from=254712345678&message=Hello&sent_timestamp=1710510600&sent_to=254700123456&message_id=abc123&device_id=device1&secret=mysecret
The server responds with a JSON payload. To send outbound messages via the phone, include them in the response:
{
"payload": {
"success": true,
"task": "send",
"secret": "mysecret",
"messages": [
{
"to": "254712345678",
"message": "Reply from server",
"uuid": "msg-uuid-123"
}
]
}
}
The SmsSync app can poll the endpoint to check for messages to send:
GET /api/sms/smssync?task=send&secret=mysecret
Response:
{
"payload": {
"task": "send",
"secret": "mysecret",
"messages": [
{
"to": "254712345678",
"message": "Scheduled message",
"uuid": "msg-uuid-456"
}
]
}
}
MSync is Salami's proprietary Android app for phone-based SMS gateway functionality. It provides richer features than SmsSync including device status monitoring, location tracking, and bidirectional sync.
ANY /api/sms/msync
No Bearer token required. The MSync app authenticates via device credentials.
https://your-domain.com/api/sms/msync
The MSync app sends received messages to the server:
POST /api/sms/msync
{
"action": "incoming",
"device_id": "device-uuid-123",
"messages": [
{
"from": "254712345678",
"message": "Hello",
"timestamp": "2026-03-15T15:00:00Z",
"sim_slot": 0
}
]
}
The app polls for messages to send:
POST /api/sms/msync
{
"action": "outgoing",
"device_id": "device-uuid-123"
}
Response:
{
"messages": [
{
"id": 157,
"to": "254712345678",
"message": "Your order is ready",
"uuid": "msg-uuid-789"
}
]
}
The MSync app periodically reports device health:
POST /api/sms/msync
{
"action": "status",
"device_id": "device-uuid-123",
"battery_level": 85,
"signal_strength": -67,
"network_type": "4G",
"sim_state": "ready"
}
POST /api/sms/msync
{
"action": "location",
"device_id": "device-uuid-123",
"latitude": -1.2921,
"longitude": 36.8219,
"accuracy": 15.0
}
The MSync app reports delivery confirmations:
POST /api/sms/msync
{
"action": "delivery",
"device_id": "device-uuid-123",
"reports": [
{
"uuid": "msg-uuid-789",
"status": "delivered",
"timestamp": "2026-03-15T15:00:05Z"
}
]
}
Regardless of the receiving mechanism, all inbound messages go through this pipeline:
sms_ipn_requests table.Message.folder: inbox.IpnCallReceived event fires.