SinchFunctions Developer Documentation

Everything you need to know about developing with SinchFunctions

Welcome to SinchFunctions!

SinchFunctions is a powerful serverless platform designed specifically for voice applications:

  • Voice-First Platform: Native SVAML support with built-in Sinch Voice integration
  • Secure Development: OS keychain integration for secrets management
  • Developer Experience: F5 debugging in VS Code, hot reload, and production parity
  • Multi-language Support: Node.js, C#, and Python templates available

Quick Start Guide

Get Started in 5 Minutes
1. Install the CLI
npm install -g @sinch/functions-cli
2. Authenticate with Sinch
sinch auth login

This stores your Sinch credentials securely in your OS keychain (Windows Credential Manager, macOS Keychain, or Linux Secret Service).

3. Create Your First Function
# Interactive mode - we'll help you choose a template
sinch functions init

# Or specify directly
sinch functions init --template node/simple-voice-ivr --name my-ivr
4. Start Development
cd my-ivr
sinch functions dev

The CLI will offer to create an ngrok tunnel for testing with real phone calls!

5. Deploy to Production
sinch functions deploy

Authentication & Setup

Secure Authentication with OS Keychain

SinchFunctions uses your operating system's secure credential storage:

Initial Setup
sinch auth login

You'll be prompted for:

  • Project ID - From your Sinch Dashboard
  • Key ID - From Project → Access Keys
  • Key Secret - Stored securely in OS keychain
  • Voice Application Key - For voice functions
  • Voice Application Secret - Stored securely in OS keychain
Check Authentication Status
sinch auth status

# Output:
🔐 Authentication Status
✅ Authenticated
  Project ID: 31196b37-7298-4269-b920-c978825799ac
  Key ID: b8c9d234-5678-90ab-cdef-123456789012
  Application Key: 7f8e9d10-1234-5678-90ab-cdef12345678
  (Secrets stored securely in OS keychain)
✅ Connection active
Security Architecture
🔒 Enterprise-Grade Security:
  • Windows: Credential Manager
  • macOS: Keychain
  • Linux: Secret Service API
Secrets are never stored in plain text files!

Secrets Management

Managing Custom Secrets

Beyond Sinch credentials, you can store custom secrets for your functions:

Add a Secret
# Store API keys, database passwords, etc.
sinch secrets add STRIPE_API_KEY sk_test_123456789
sinch secrets add DATABASE_PASSWORD mySecurePassword123
List Your Secrets
sinch secrets list

# Output:
Custom Secrets:
  🔐 STRIPE_API_KEY
  🔐 DATABASE_PASSWORD
Total: 2 secret(s)
Using Secrets in Your Function

1. Declare in .env file (leave value empty):

# .env
STRIPE_API_KEY=
DATABASE_PASSWORD=

2. Access in your code:

// Secrets are loaded automatically from keychain
const stripeKey = process.env.STRIPE_API_KEY;
const dbPassword = process.env.DATABASE_PASSWORD;

// They're available in your function
module.exports = {
  async ice(context, callbackData) {
    if (process.env.STRIPE_API_KEY) {
      // Process payment with Stripe
    }
  }
};
💡 Security Best Practice: Only secrets declared in .env (with empty values) are loaded from the keychain. This prevents accidental exposure of unintended secrets.

Local Development

Development Server with Hot Reload
Start Development Server
sinch functions dev

# Options:
--port 8080        # Custom port (default: 3000)
--debug            # Enable Node.js debugging
--tunnel           # Force create ngrok tunnel
--no-tunnel        # Disable tunnel
--no-watch         # Disable file watching
Features
  • 🔄 Hot Reload - Instant updates on save
  • 🌐 Ngrok Tunnel - Test with real calls
  • 📞 Auto Callback URL - Updates Sinch automatically
  • 🔐 Secrets Loading - From OS keychain
  • 🐛 F5 Debugging - Works in VS Code
  • 📝 Request Logging - See all activity
  • 🗄️ Local Storage - Emulated locally
  • Fast Startup - Ready in seconds
VS Code F5 Debugging
🎉 Zero Configuration! All Node.js templates include .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Sinch Function",
      "program": "${workspaceFolder}/host.js",
      "env": {
        "NODE_ENV": "development"
      }
    }
  ]
}

Just press F5! Secrets load automatically from OS keychain.

Testing Your Function
# Test ICE (Incoming Call Event)
curl -X POST http://localhost:3000/ice \
  -H "Content-Type: application/json" \
  -d '{
    "callid": "test-123",
    "cli": "+1234567890",
    "to": "+0987654321"
  }'

Deployment

Deploy to Production
Interactive Deployment
sinch functions deploy
CI/CD Deployment
# Non-interactive mode for automation
sinch functions deploy --non-interactive

# Deploy with custom Dockerfile
sinch functions deploy --dockerfile

# Specify deployment configuration
sinch functions deploy --configuration dockerfile
Deployment Process
  1. Package - Your code is bundled
  2. Upload - Secure transfer to backend
  3. Build - Container image creation
  4. Deploy - Azure Container Apps deployment
  5. Verify - Health checks and URL assignment
Post-Deployment
# Stream logs
sinch functions logs FUNCTION_ID --follow

# Check status
sinch functions status FUNCTION_ID

# List all functions
sinch functions list
🚀 Auto-Scaling: Your function automatically scales based on traffic, with health monitoring and HTTPS included.

Storage System

Built-in Key-Value Storage

Perfect for session management and state persistence:

Basic Usage
// Store data with TTL
await context.storage.set('session:abc123', {
  caller: '+1234567890',
  state: 'menu_main',
  authenticated: true
}, 3600); // 1 hour TTL

// Retrieve data
const session = await context.storage.get('session:abc123');

// Delete data
await context.storage.delete('session:abc123');

// Extend TTL on activity
await context.storage.extendTTL('session:abc123', 3600);
Number Masking Example
// Create masking session
const sessionKey = `mask:${fromNumber}:${toNumber}`;
await context.storage.set(sessionKey, {
  virtualNumber: '+15551234567',
  created: new Date(),
  lastActivity: new Date()
}, 14400); // 4 hours
Best Practices
  • Use descriptive key prefixes (session:, call:, user:)
  • Always set appropriate TTLs
  • Handle missing keys gracefully
  • Keep objects under 1MB
  • Clean up in DICE handler when possible

Available Templates

Browse Templates
# List all templates
sinch templates list

# Show template details
sinch templates show node/number-masking
Popular Templates
Node.js Templates
  • node/simple-voice-ivr - Basic IVR with menu system
  • node/number-masking - Anonymous communication
  • node/call-forwarding - Smart call routing
  • node/conference-call - Multi-party calls
  • node/voicemail - Complete voicemail system
  • node/call-recording - Record and manage calls
C# Templates
  • csharp/simple-voice-ivr - IVR in C#
  • csharp/call-forwarding - Call routing in C#
Python Templates
  • python/simple-voice-ivr - Coming soon
💡 Templates are Dynamic: Run sinch templates list for the latest options.

Troubleshooting

Common Issues
Secrets Not Loading
# Check if secret exists
sinch secrets get MY_SECRET

# Verify .env declaration
cat .env | grep MY_SECRET

# Re-add secret
sinch secrets add MY_SECRET new_value
Authentication Issues
# Check status
sinch auth status

# Re-authenticate
sinch auth logout
sinch auth login
Enable Debug Logging
# General debug
DEBUG=1 sinch functions dev

# HTTP request/response logging
DEBUG_HTTP=1 sinch functions deploy

# Combined
DEBUG=1 DEBUG_HTTP=1 sinch functions dev
Port Already in Use
# Use different port
sinch functions dev --port 8080

# Check what's using port 3000
netstat -an | grep 3000