Skip to main content

Security Best Practices

Protect your Orbit integration with proper API key management, webhook signature verification, and security hardening.

API Key Management

Key Types

Orbit uses three types of API keys:
Key TypePrefixUsagePermissions
Live Secret Keydv_live_sk_Server-side onlyFull API access
Test Secret Keydv_test_sk_Server-side testingSandbox only
Public Keydv_live_pk_Client-side (web SDK)Limited read-only

Key Security Rules

  1. Never expose secret keys in client-side code. Secret keys (sk_) should only be used in server-side environments.
❌ Client-side JavaScript
const orbit = new Devotel({ apiKey: 'dv_live_sk_xxxx' }) // NEVER

✅ Server-side only
// Node.js backend, Python server, etc.
const orbit = new Devotel({ apiKey: process.env.DEVOTEL_API_KEY })
  1. Use environment variables. Never hardcode keys in source code.
# .env (never commit this file)
DEVOTEL_API_KEY=dv_live_sk_your_key_here
  1. Rotate keys regularly. Generate new keys quarterly and revoke old ones.
  2. Use separate keys per environment. Use test keys (dv_test_sk_) for development.
  3. Restrict key permissions. Create keys with minimum required scopes in the dashboard under Settings > API Keys.

Revoking a Compromised Key

If a key is exposed:
  1. Go to Settings > API Keys in the Orbit dashboard
  2. Click Revoke on the compromised key
  3. Generate a new key
  4. Update your application configuration immediately
Revoking a key is immediate and irreversible. All requests using the revoked key will return 401 INVALID_API_KEY.

Webhook Verification

Every webhook from Orbit includes an HMAC-SHA256 signature in the X-Devotel-Signature header. Always verify this signature before processing webhook payloads.

How Verification Works

  1. Orbit signs the raw request body using your webhook secret
  2. The signature is sent in the X-Devotel-Signature header
  3. Your server recomputes the signature and compares it

Implementation

Node.js

import crypto from 'node:crypto'

function verifyWebhookSignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex')

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  )
}

app.post('/webhooks/orbit', (req, res) => {
  const signature = req.headers['x-devotel-signature']
  const isValid = verifyWebhookSignature(
    req.rawBody,
    signature,
    'whsec_your_secret',
  )

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' })
  }

  // Process the webhook
  const event = req.body
  res.status(200).json({ received: true })
})

Python

import hmac
import hashlib

def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        payload,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

@app.route("/webhooks/orbit", methods=["POST"])
def handle_webhook():
    signature = request.headers.get("X-Devotel-Signature")
    if not verify_webhook_signature(request.data, signature, "whsec_your_secret"):
        return jsonify({"error": "Invalid signature"}), 401

    event = request.get_json()
    return jsonify({"received": True}), 200

Go

func verifyWebhookSignature(payload []byte, signature, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(payload)
    expected := hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(signature), []byte(expected))
}

Webhook Security Checklist

  • Verify X-Devotel-Signature on every request
  • Use timingSafeEqual (or equivalent) to prevent timing attacks
  • Respond with 200 within 30 seconds to avoid retries
  • Use HTTPS for all webhook endpoints
  • Store webhook secrets securely (environment variables, secret manager)

Transport Security

HTTPS Required

All Orbit API endpoints require HTTPS (https://orbit-api.devotel.io). HTTP requests are rejected.

TLS Requirements

  • Minimum TLS 1.2
  • TLS 1.3 recommended
  • Weak cipher suites are not supported

Webhook Endpoint Requirements

Your webhook endpoints must:
  • Use HTTPS with a valid SSL certificate (not self-signed)
  • Support TLS 1.2 or higher
  • Respond within 30 seconds
  • Return a 2xx status code to acknowledge receipt

IP Allowlisting

If your firewall restricts inbound traffic, allowlist Orbit’s webhook delivery IPs:
34.141.0.0/16    (europe-west1 — primary)
35.195.0.0/16    (europe-west1 — secondary)
IP ranges may change. Subscribe to the Orbit status page for notifications about infrastructure changes.

Data Security

PII Handling

  • Orbit masks phone numbers in logs (+1415555****)
  • API responses include full data; mask PII in your own logs
  • Use metadata fields for internal identifiers instead of PII

Data Retention

Data TypeRetentionNotes
Message content90 daysConfigurable per account
Call recordings30 daysConfigurable; auto-deleted after
Webhook delivery logs30 daysAvailable in dashboard
API access logs1 yearIncludes request IDs

Encryption

  • In transit: TLS 1.2+ for all API and webhook traffic
  • At rest: AES-256 encryption for all stored data
  • Recordings: Encrypted at rest with per-tenant keys

RBAC (Role-Based Access Control)

Orbit supports five roles with increasing permissions:
RoleAPI KeysSend MessagesManage AgentsBillingTeam
viewerRead onlyNoNoNoNo
developerCreate/manageYesYesNoNo
adminFull accessYesYesViewInvite
billingNoNoNoFullNo
ownerFull accessYesYesFullFull
Assign the minimum role needed for each team member.

Security Headers

Orbit API responses include security headers:
HeaderValue
X-Request-IdUnique request identifier for tracing
Strict-Transport-Securitymax-age=31536000; includeSubDomains
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
Found a security vulnerability? Report it to security@devotel.io. We take all reports seriously and respond within 24 hours.