WebSocket
Receive real-time SMS delivery status updates and inbound SMS notifications over a persistent WebSocket connection.
/wsIn-band (first message after connect)Upgrade to a WebSocket connection for real-time events.
Connection URL
wss://smsgateway-api.onrender.com/ws
Authentication
After opening the WebSocket connection, the first message must be an auth message. No other messages are processed until authentication succeeds. Two authentication methods are supported:
Token-based authentication (recommended for browsers)
Use ephemeral tokens when the WebSocket connection originates from a browser or any environment where you do not want to expose the API key. Request a token server-side, then pass it to the client for authentication.
/v1/ws/tokenappGenerate a short-lived, single-use token for WebSocket authentication.
Response
| Name | Type | Required | Description |
|---|---|---|---|
token | string | Required | Ephemeral token prefixed with wst_. Single-use; consumed when used to authenticate a WebSocket connection. |
expiresIn | integer | Required | Token lifetime in seconds (currently 60). The token cannot be used after this period. |
{"token": "wst_a1b2c3d4e5f6789012345678abcdef90a1b2c3d4e5f6789012345678abcdef90","expiresIn": 60}
curl -X POST https://smsgateway-api.onrender.com/v1/ws/token \-H "Authorization: Bearer YOUR_API_KEY"
Then authenticate the WebSocket connection with the token:
{"type": "auth","token": "wst_a1b2c3d4e5f6789012345678abcdef90a1b2c3d4e5f6789012345678abcdef90"}
API key authentication (server-to-server)
For server-side applications, you can authenticate directly with your API key. Only use this method in environments where the key is not exposed to end users.
{"type": "auth","apiKey": "sgw_a1b2c3d4e5f6789012345678abcdef90"}
Success
{"type": "auth_ok"}
Errors
On auth failure, the server sends an error message and closes the connection with code 1008 (Policy Violation).
{"type": "auth_error","error": "Invalid JSON"}
{"type": "auth_error","error": "Invalid API key"}
{"type": "auth_error","error": "Invalid or expired token"}
{"type": "auth_error","error": "Send auth first"}
Event types
sms_status
Sent when an outbound message changes status (queued → sending → sent/failed).
{"type": "sms_status","messageId": "msg_a1b2c3d4e5f6","appId": "app_abc123def456abcd","tenantId": "tenant_abc123def456abcd","status": "sent","rcMessageId": "12345678","timestamp": "2026-03-01T10:00:02.000Z"}
{"type": "sms_status","messageId": "msg_a1b2c3d4e5f6","appId": "app_abc123def456abcd","tenantId": "tenant_abc123def456abcd","status": "failed","error": "Phone number +15559876543 is not registered in this RingCentral account","timestamp": "2026-03-01T10:00:02.000Z"}
sms_inbound
Sent when an inbound SMS is received.
{"type": "sms_inbound","messageId": "msg_f6e5d4c3b2a1","from": "+15551234567","to": "+15559876543","body": "Hey, is my appointment still on?","rcMessageId": "12345678","tenantId": "tenant_abc123def456abcd","timestamp": "2026-03-01T14:30:00.000Z"}
ping
Heartbeat sent by the server every 30 seconds. No response required.
{"type": "ping"}
Event scoping
Event scoping works identically for both authentication methods. A token inherits the same role and tenant scope as the API key that generated it.
Example — token auth (browser)
// 1. Request an ephemeral token from your serverconst res = await fetch("/api/ws-token");const { token, wsUrl } = await res.json();// 2. Connect to the gateway WebSocketconst ws = new WebSocket(wsUrl + "/ws");ws.onopen = () => {// 3. Authenticate with the token (API key stays server-side)ws.send(JSON.stringify({ type: "auth", token }));};ws.onmessage = (event) => {const data = JSON.parse(event.data);switch (data.type) {case "auth_ok":console.log("Authenticated");break;case "sms_status":console.log("Status update:", data.messageId, data.status);break;case "sms_inbound":console.log("Inbound SMS:", data.from, data.body);break;case "ping":break;}};
Example — API key auth (server)
const ws = new WebSocket("wss://smsgateway-api.onrender.com/ws");ws.onopen = () => {ws.send(JSON.stringify({type: "auth",apiKey: "YOUR_API_KEY"}));};ws.onmessage = (event) => {const data = JSON.parse(event.data);switch (data.type) {case "auth_ok":console.log("Authenticated");break;case "sms_status":console.log("Status update:", data.messageId, data.status);break;case "sms_inbound":console.log("Inbound SMS:", data.from, data.body);break;case "ping":break;}};
Related docs
- WebSocket Events Guide — Connection management and reconnection
- Webhooks — HTTP-based alternative for inbound SMS
- Authentication — API key format and WebSocket tokens
- Security — WebSocket token security properties