Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vobiz.ai/llms.txt

Use this file to discover all available pages before exploring further.

Security Best Practices

Never Hardcode Credentials

Bad practice - credentials baked into source code:
Hardcoded Credentials (Never Do This)
const API_KEY = "sk_live_abc123def456";  // NEVER DO THIS
const PASSWORD = "my_secret_password";    // NEVER DO THIS
Good practice - load from environment or a secrets manager:
Use Environment Variables
// Load from environment variables
const API_KEY = process.env.VOBIZ_API_KEY;
const PASSWORD = process.env.VOBIZ_PASSWORD;

// Or use a secrets manager
const secrets = await secretsManager.getSecret("vobiz/credentials");

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
{
  "authType": "ip",
  "ipWhitelist": [
    "203.0.113.10",  // Production PBX
    "203.0.113.11"   // Backup PBX
  ]
}
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
async function makeAuthenticatedRequest(url, options) {
  // Check if token expires in next 5 minutes
  if (tokenExpiresAt - Date.now() < 5 * 60 * 1000) {
    await refreshAccessToken();
  }

  return fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      'Authorization': `Bearer ${access_token}`
    }
  });
}

async function refreshAccessToken() {
  const response = await fetch('https://api.vobiz.ai/api/v1/auth/refresh', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refreshToken })
  });

  const data = await response.json();
  accessToken = data.access_token;
  tokenExpiresAt = Date.now() + (30 * 60 * 1000);
}

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:
ResourceCache TTLNotes
Account info15 minutesRarely changes
Trunk list5 minutesInvalidate on create/delete
Balance1 minuteFrequently updated
CDRsNo cacheAlways fetch fresh

Use Pagination Wisely

Don’t fetch all records at once. Use pagination for large datasets:
Efficient Pagination
// Fetch CDRs in batches of 100
async function getAllCDRs(auth_id, startDate, endDate) {
  const allCDRs = [];
  let offset = 0;
  const limit = 100;

  while (true) {
    const response = await fetch(
      `https://api.vobiz.ai/api/v1/Account/${auth_id}/cdr?start_date=${startDate}&end_date=${endDate}&limit=${limit}&offset=${offset}`
    );
    const data = await response.json();

    allCDRs.push(...data.data.cdrs);

    if (!data.data.pagination.hasMore) break;
    offset += limit;
  }

  return allCDRs;
}

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)
const https = require('https');

// Create agent with connection pooling
const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000
});

// Reuse agent for all requests
fetch(url, { agent });

Reliability & Error Handling

Implement Retry Logic

Retry failed requests with exponential backoff for transient errors:
Retry with Exponential Backoff
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      // Don't retry 4xx errors (client errors)
      if (response.status >= 400 && response.status < 500) {
return response;
      }

      // Retry 5xx errors and network failures
      if (response.ok) {
return response;
      }

      if (attempt === maxRetries) {
throw new Error(`Failed after ${maxRetries} retries`);
      }

      // Exponential backoff: 1s, 2s, 4s, 8s...
      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));

    } catch (error) {
      if (attempt === maxRetries) throw error;

      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

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
async function handleRateLimit(response) {
  if (response.status === 429) {
    const retryAfter = response.headers.get('Retry-After') || 60;

    console.log(`Rate limited. Retrying after ${retryAfter} seconds`);

    await new Promise(resolve =>
      setTimeout(resolve, retryAfter * 1000)
    );

    // Retry the request
    return fetch(url, options);
  }

  return response;
}

Idempotency Keys

For critical operations (purchases, transactions), use idempotency keys to prevent duplicates:
Idempotent Requests
const idempotencyKey = `purchase-${Date.now()}-${Math.random()}`;

await fetch('https://api.vobiz.ai/api/v1/Account/ACC123/numbers/purchase', {
  method: 'POST',
  headers: {
    'Idempotency-Key': idempotencyKey,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ phoneNumber: '+14155551234' })
});

Monitoring & Logging

Log All API Requests

Maintain detailed logs for debugging and auditing:
Request Logging
function logAPIRequest(method, url, status, duration, requestId) {
  console.log({
    timestamp: new Date().toISOString(),
    method,
    url,
    status,
    duration: `${duration}ms`,
    requestId,
    service: 'vobiz-api'
  });
}

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 for 1400 & 1600 series.

140 & 160 Acquisition

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

Error Handling

Understand error codes and handle them gracefully.