Security
Gravity SMS implements multiple layers of security to protect API access, data in transit, and stored credentials.
Transport security
- HTTPS required — All API requests must use HTTPS in production. HTTP requests receive a
403 HTTPS requiredresponse. - TLS enforcement — The gateway only accepts TLS-encrypted connections, protecting data in transit including API keys and message content.
API key security
- Hashed storage — API keys are hashed using SHA-256 before storage. The plaintext key is only returned once at creation time and cannot be retrieved later.
- Prefix identification — Only the first 8 characters of the key (
sgw_prefix + 4 characters) are stored in plaintext for identification purposes. - Key rotation — API keys can be rotated via the rotate-key endpoint. The old key is immediately invalidated and a new key is generated.
WebSocket token security
Ephemeral WebSocket tokens allow browser-based applications to authenticate WebSocket connections without exposing API keys to client-side JavaScript.
- Short-lived — Tokens expire after 60 seconds. Unused tokens are automatically cleaned up.
- Single-use — Each token is consumed on first use and cannot be replayed.
- In-memory only — Tokens are stored in server memory, not persisted to disk or database.
- Scoped — Each token inherits the same appId, tenantId, and role as the API key that created it. No privilege escalation is possible.
Credential protection
RingCentral OAuth tokens are encrypted at rest using AES-256-GCM before being stored. Tokens are decrypted only when needed for API calls and are never exposed through any API endpoint.
Brute-force protection
The gateway tracks failed authentication attempts per IP address:
- After 10 failed attempts within 5 minutes, the IP is blocked for 15 minutes.
- Blocked IPs receive
429 Too many requestswith aRetry-Afterheader on all subsequent requests.
Security headers
The gateway sets standard security headers on all responses to mitigate common web vulnerabilities:
| Header | Purpose |
|---|---|
Strict-Transport-Security: max-age=31536000; includeSubDomains | Enforces HTTPS for 1 year via HSTS, including subdomains. |
X-Frame-Options: DENY | Prevents clickjacking via iframes. |
X-Content-Type-Options: nosniff | Prevents MIME type sniffing. |
X-XSS-Protection: 0 | Disables legacy XSS filter (modern CSP is preferred). |
Content-Security-Policy: default-src 'none' | Restricts all resource loading (API-only, no browser content served). |
Referrer-Policy: no-referrer | Prevents sending referrer information with requests. |
Cache-Control: no-store | Prevents caching of API responses. |
Error sanitization
In production, unexpected server errors (5xx) return a generic {"error": "Internal server error"} response. Internal error details, stack traces, and implementation information are never exposed to API consumers.
Request size limits
Request bodies are limited to 100 KB by default. Requests exceeding this limit receive a 413 Payload too large response.
Webhook security
- HTTPS required — Webhook URLs must use HTTPS in production environments, ensuring payloads are encrypted in transit.
- HMAC-SHA256 signatures — Every webhook delivery includes an
X-Gravity-Signatureheader containing an HMAC-SHA256 signature computed with the app's webhook secret. This allows you to verify that payloads are authentic and untampered. - Replay protection — The
X-Gravity-Timestampheader is included in the signature computation. Reject requests with timestamps older than 5 minutes to prevent replay attacks. - Per-app secrets — Each app receives a unique webhook secret (
whsec_prefix) at registration time. Secrets can be rotated independently without affecting other apps.
See the Webhooks guide for implementation details and a code example.
Best practices
- Rotate keys regularly — Use the rotate-key endpoint to periodically generate new API keys.
- Use environment variables — Never hard-code API keys in source code. Store them in environment variables or a secrets manager.
- Restrict key scope — Each API key is scoped to a single app. Use separate apps for different integrations to limit blast radius.
- Monitor for 429 responses — A spike in rate limit errors may indicate credential leakage or unauthorized usage.
- Verify webhook signatures — Always verify the
X-Gravity-Signatureheader on incoming webhooks using your app's webhook secret.
Related docs
- Authentication — API key format and roles
- Rate Limits — Brute-force protection details
- Webhooks — Signature verification and webhook handling
- Base URL & Versioning — HTTPS requirements