Skip to content
Last updated

Local Development

Starting the dev server

sinch functions dev

Node.js functions restart automatically when you save changes. C# functions use dotnet watch run.

Default port is 3000. Override with:

sinch functions dev --port 8080

Tunnel

The tunnel proxies requests from the Sinch platform to your local machine. Without it, Sinch callbacks cannot reach localhost.

On first run, the CLI asks for your tunnel preference. Your answer is saved in sinch.json under tunnel.preference.

sinch functions dev --tunnel      # Force tunnel on
sinch functions dev --no-tunnel   # Force tunnel off

When active, the tunnel registers a public endpoint and the platform automatically configures your Voice application's callback URL to point at it.

Debugging

Node.js

sinch functions dev --debug

Starts the Node.js inspector on port 9229. The CLI creates .vscode/launch.json automatically if it does not exist.

  • VS Code / Cursor — Press F5 to attach
  • WebStorm — Run > Attach to Node.js/Chrome > localhost:9229
  • Manual — connect to ws://localhost:9229

C#

sinch functions dev --debug

Creates .vscode/launch.json and .vscode/tasks.json. For Visual Studio: Debug > Attach to Process > dotnet.exe. For Rider: Run > Attach to Process.

Debug environment variables

VariableEffect
DEBUG=1Verbose debug logging in CLI and runtime
DEBUG_HTTP=1Log all HTTP request and response details

Testing endpoints

# ICE callback
curl -s -X POST http://localhost:3000/ice \
  -H "Content-Type: application/json" \
  -d '{
    "callid": "test-123",
    "cli": "+15551234567",
    "to": {"type": "number", "endpoint": "+15559876543"},
    "domain": "pstn",
    "originationType": "pstn"
  }'

# PIE callback (simulating DTMF press "1")
curl -s -X POST http://localhost:3000/pie \
  -H "Content-Type: application/json" \
  -d '{
    "callid": "test-123",
    "menuResult": {
      "menuId": "main",
      "value": "1",
      "inputMethod": "dtmf"
    }
  }'

Secrets

Secrets are sensitive values stored in your OS keychain and injected at runtime.

Pattern

  1. Declare the key in .env (Node.js) or appsettings.json (C#) with an empty value
  2. Store the actual value: sinch secrets add OPENAI_API_KEY sk-proj-PLACEHOLDER
  3. The runtime loads values from the keychain at startup

Use in code

const apiKey = process.env.OPENAI_API_KEY;

Manage secrets

sinch secrets list                         # List key names (values hidden)
sinch secrets get OPENAI_API_KEY           # Show metadata, --show for value
sinch secrets delete OPENAI_API_KEY        # Remove from keychain

C# secrets

sinch functions init runs dotnet user-secrets init automatically. To add manually:

dotnet user-secrets set OPENAI_API_KEY sk-proj-PLACEHOLDER

On deploy

The CLI reads your .env or appsettings.json. For keys with empty values, it looks up the actual value from the keychain. Secret variables are encrypted at rest and never appear in logs.

Credential injection

The dev server injects Sinch credentials as environment variables automatically:

VariableSource
SINCH_APPLICATION_KEYOS keychain (Voice application key)
SINCH_APPLICATION_SECRETOS keychain (Voice application secret)

What gets excluded from deployment

node_modules/, .env, .env.local, bin/, obj/, .git/, .vscode/, .idea/, .vs/, .cursor/, *.zip, *.user, *.suo