Everything you need to integrate with SmsSync.
SmsSync uses two authentication methods:
Send your API key in the X-API-Key header:
X-API-Key: smssync_your_api_key_hereSend the JWT token from login in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...When an SMS is received, SmsSync sends a POST request to your webhook URL with the following JSON payload:
SmsSync forwards every SMS exactly as received — raw sender ID and full message content. No parsing, no filtering. You get the raw data and decide what to do with it on your server.
{
"event": "sms.received",
"timestamp": 1709640000000,
"data": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"sender": "MobileMoney",
"content": "You have received GHS 50.00 from JOHN DOE 0244123456. Transaction ID: 1234567890. Your new balance is GHS 150.00",
"receivedAt": "2026-03-05T12:00:00.000Z",
"sim": "SIM1",
"deviceId": "pixel_7a"
}
}event — always "sms.received"timestamp — Unix timestamp in millisecondsdata.id — unique message ID in our databasedata.sender — sender ID exactly as shown on the phone (e.g. "MobileMoney", "+233244123456", "DataMart")data.content — full raw SMS textdata.receivedAt — ISO 8601 timestamp when SMS was receiveddata.sim — which SIM received the SMS (SIM1 or SIM2)data.deviceId — identifier of the phone that received the SMSContent-Type: application/json
X-Webhook-Timestamp: 1709640000000
X-Webhook-Event: sms.received
X-Webhook-Signature: sha256=abc123... (if secret configured)
User-Agent: SmsSync-Webhook/1.0/api/auth/registerAuth: NoneCreate a new account
/api/auth/loginAuth: NoneLogin and get JWT token
/api/auth/meAuth: JWTGet current user profile
/api/sms/incomingAuth: API KeyReceive SMS from Flutter app
/api/smsAuth: JWTList all SMS (paginated)
/api/sms/searchAuth: JWTSearch SMS (by sender, content, date range)
/api/sms/statsAuth: JWTGet SMS statistics
/api/webhooksAuth: JWT/API KeyList webhooks
/api/webhooksAuth: JWT/API KeyCreate webhook
/api/webhooks/:idAuth: JWT/API KeyUpdate webhook
/api/webhooks/:idAuth: JWT/API KeyDelete webhook
/api/webhooks/:id/testAuth: JWT/API KeySend test webhook
/api/device/statusAuth: JWTGet device status
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
const { event, data } = req.body;
console.log('SMS received from:', data.sender);
console.log('Content:', data.content);
console.log('Received at:', data.receivedAt);
console.log('Device:', data.deviceId, '| SIM:', data.sim);
// Process the raw SMS however you need
// e.g. check sender ID, parse content, update your database
res.json({ received: true });
});
app.listen(3000);from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.json
sms = payload.get('data', {})
print(f"SMS from {sms.get('sender')}: {sms.get('content')}")
# Process the raw SMS however you need
# e.g. check sender ID, parse content, update your database
return jsonify({"received": True})
if __name__ == '__main__':
app.run(port=3000)curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
https://your-server.com/api/sms?page=1&limit=20https://your-server.com)If you configured a webhook secret, SmsSync signs each request with HMAC-SHA256. Verify the signature to ensure the webhook is authentic:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return signature === expected;
}
// In your webhook handler:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhook(req.body, signature, 'your_secret');
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process the webhook...
res.json({ received: true });
});