Skip to main content

Security Best Practices

Never Hardcode Credentials

Bad practice - credentials baked into source code:
Hardcoded Credentials (Never Do This)
Good practice - load from environment or a secrets manager:
Use Environment Variables

Use HTTPS for All Requests

Always use https:// URLs when calling the API. Never send authentication tokens or sensitive data over unencrypted HTTP connections. Our API only responds to HTTPS.

Rotate Credentials Regularly

  • Change trunk passwords every 90 days
  • Change account passwords regularly and invalidate old refresh tokens
  • Immediately rotate if credentials are suspected to be compromised
  • Use sub-accounts for different applications/teams to limit blast radius

Whitelist IP Addresses

For production SIP trunks with static IPs, use IP authentication instead of passwords:
IP Whitelist Configuration
This eliminates password-based attacks and simplifies configuration for trusted systems.

Validate Input on Client Side

Implement client-side validation before sending requests to prevent injection attacks:
  • Sanitize phone numbers (remove special characters, validate E.164 format)
  • Validate email addresses match RFC 5322 spec
  • Limit string lengths (trunk names, usernames, etc.)
  • Reject suspicious patterns (SQL injection attempts, XSS payloads)

Authentication & Authorization

Token Storage

Frontend Applications
  • Store access tokens in memory or sessionStorage (expires when tab closes)
  • Never store tokens in localStorage (vulnerable to XSS attacks)
  • Use httpOnly cookies for refresh tokens if possible
Backend Applications
  • Store tokens in environment variables or secrets manager
  • Encrypt tokens at rest if storing in database
  • Use secure memory storage for short-lived tokens

Automatic Token Refresh

Implement automatic token refresh before expiration (30 minutes for access tokens):
Token Refresh Pattern

Use Sub-Accounts for Separation

Create separate sub-accounts for different applications, environments, or teams:
  • Development: Separate sub-account for testing
  • Production: Dedicated sub-account with stricter controls
  • Partners: Sub-accounts for each integration partner
  • Departments: Sales, Support, Engineering teams get own sub-accounts

Performance Optimization

Implement Caching

Cache infrequently changing data to reduce API calls:

Use Pagination Wisely

Don’t fetch all records at once. Use pagination for large datasets:
Efficient Pagination

Batch Operations

Instead of making multiple individual requests, consider implementing client-side batching:
  • Batch CDR queries by date ranges instead of querying each day separately
  • Combine multiple resource updates in a single transaction when possible
  • Use bulk operations for importing/exporting large datasets

Connection Pooling

Reuse HTTP connections instead of creating new ones for every request:
Connection Pooling (Node.js)

Reliability & Error Handling

Implement Retry Logic

Retry failed requests with exponential backoff for transient errors:
Retry with Exponential Backoff

Circuit Breaker Pattern

Prevent cascading failures by implementing a circuit breaker:
  • Track consecutive failures for each service
  • After 5 failures, “open” circuit and fail fast for 30 seconds
  • After timeout, allow one request through (“half-open” state)
  • If successful, close circuit; if failed, reopen for longer

Handle Rate Limits Gracefully

When you receive a 429 (Rate Limit) response:
Handle Rate Limits

Retry Billable Writes Carefully

Apply the retry logic above to reads and to writes you can safely repeat. For a write that charges your balance - such as Purchase from Inventory, which debits the setup fee and monthly fee - read the account state first and skip the retry if the earlier attempt already landed. List Account Phone Numbers accepts a search query parameter that filters by phone number, which makes it a cheap way to confirm ownership before you send the purchase again:
Confirm Before Retrying a Purchase
Keep the literal + in the JSON body, and URL-encode it in the search query parameter as shown above.

Monitoring & Logging

Log All API Requests

Maintain detailed logs for debugging and auditing:
Request Logging

Track Key Metrics

  • API request success/failure rates
  • Average response times per endpoint
  • Error distribution by error code
  • Token refresh frequency
  • Balance consumption rate
  • Call success rates (ASR)
  • Rate limit violations

Set Up Alerts

Configure alerts for critical events:
  • Balance Low: Alert when balance drops below threshold
  • Error Spike: Alert when error rate exceeds 5% of requests
  • Trunk Down: Alert when trunk authentication fails repeatedly
  • Rate Limit Hit: Alert when approaching rate limits

Testing Strategies

Use Separate Accounts for Testing

Create dedicated test accounts/sub-accounts with separate credentials. Never test in production with real customer data or active trunks.

Test Error Scenarios

Don’t just test happy paths. Verify your application handles errors correctly: invalid credentials, insufficient balance, rate limits, network timeouts, etc.

Automate Integration Tests

Integrate automated API tests into your CI/CD pipeline to catch regressions early. Run tests on every commit to the main branch to ensure reliability.

Monitor Test Call Quality

Make regular test calls and verify:
  • Call connects within 3 seconds (low PDD)
  • Audio quality is clear (no packet loss)
  • CDR is generated correctly
  • Balance is debited accurately

Load Testing

Before going live, test with realistic load:
  • Simulate expected CPS (calls per second)
  • Test concurrent call limits
  • Verify rate limiting behaves as expected
  • Monitor API response times under load

Number Utilization

Improve connectivity, reduce spam flagging, and stay compliant.

DLT Registration

Step-by-step DLT registration - Principal Entity, header, and template approval.

140 & 160 Acquisition

Process, documents, and scenarios for 140/160 numbers.

Error Handling

Understand error codes and handle them gracefully.