Webhooks
Gravity SMS uses two layers of webhooks: RingCentral-to-gateway (inbound SMS delivery) and gateway-to-app (fan-out to your applications). This guide explains the architecture and how to set up reliable webhook handling.
Webhook architecture
Two distinct webhook flows exist in the system:
- RingCentral → Gateway — RingCentral sends inbound SMS events to the gateway's webhook endpoint. The gateway handles handshake, verification, and event processing.
- Gateway → Your App — After processing an inbound SMS, the gateway fans out the message to every app in the tenant that has a
webhookUrlconfigured.
RingCentral webhook flow
When the gateway connects to RingCentral, it creates a webhook subscription for instant SMS events. RingCentral uses a two-phase verification process:
- Handshake — RingCentral sends a request with a
Validation-Tokenheader. The gateway echoes this header back in the response to confirm the endpoint. - Event delivery — Subsequent events include a
Verification-Tokenheader. The gateway verifies it against the stored token before processing.
App webhook fan-out
When an inbound SMS is processed, the gateway delivers it to your application:
- The gateway sends an HTTP POST to each app's
webhookUrlwith a JSON payload. - The request has a 5-second timeout. Return a 2xx response as quickly as possible and process the message asynchronously.
- If your endpoint is unreachable or times out, the message is not retried to your webhook but remains available via the messages API and WebSocket.
Inbound payload shape
{"type": "sms_inbound","messageId": "msg_a1b2c3d4e5f6","from": "+15559876543","to": "+15551234567","body": "Yes, I confirm","rcMessageId": "123456789","tenantId": "tenant_abc123def456abcd","timestamp": "2026-03-01T14:30:00.000Z"}
Configuring your webhook URL
Set the webhookUrl during app registration or update it afterwards:
curl -X PUT https://smsgateway-api.onrender.com/v1/apps/app_abc123def456abcd \-H "Authorization: Bearer YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{ "webhookUrl": "https://your-app.example.com/webhooks/sms" }'
To remove the webhook URL and stop receiving webhook deliveries:
curl -X PUT https://smsgateway-api.onrender.com/v1/apps/app_abc123def456abcd \-H "Authorization: Bearer YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{ "webhookUrl": null }'
Webhook URL requirements
| Requirement | Details |
|---|---|
| Protocol | HTTPS required in production. HTTP accepted in non-production environments. |
| Maximum length | 2,000 characters. |
| Format | Must be a valid URL. |
Testing webhooks
Use the test-webhook endpoint to send a test payload to your configured URL and verify it responds correctly:
curl -X POST https://smsgateway-api.onrender.com/v1/apps/app_abc123def456abcd/test-webhook \-H "Authorization: Bearer YOUR_API_KEY"
The response includes the HTTP status code and body returned by your endpoint.
Best practices
- Respond quickly — Return a 2xx status within 5 seconds. Queue heavy processing for later.
- Handle duplicates — Use the
messageIdfield to deduplicate messages in your system. - Use HTTPS — Always use TLS-secured endpoints in production.
- Fall back to polling — If webhooks fail, use
GET /v1/sms/messageswithdirection=inboundto retrieve missed messages.
Related docs
- Webhooks API Reference — RingCentral webhook endpoint
- Receiving SMS — Full inbound message flow
- Apps API Reference — Configure webhook URLs
- WebSocket Events — Alternative real-time delivery