Bring Your Own Carrier (BYOC)
Register your own SIP carrier with TryVox so calls egress through it instead of TryVox's default carriers.
Bring Your Own Carrier (BYOC)
By default, TryVox routes outbound calls through its own carrier mix. BYOC lets you register an external SIP carrier (your existing carrier contract, an upstream wholesaler, a regional operator) so calls placed by your account egress through it. You configure SIP credentials, dialing prefixes, codec preferences, and concurrency caps; TryVox's routing engine picks one of your carriers per call based on prefix match and priority.
You retain the carrier relationship and the per-minute commercials. TryVox handles SIP signalling, NAT traversal, and call control.
When to use BYOC
- You already have a carrier contract you want to keep using.
- You need to reach destinations TryVox's default carriers don't cover well.
- Compliance requires calls to traverse a specific operator (regulated markets, PSAP routing, government numbers).
- You want to A/B carrier quality without leaving the TryVox call control surface.
Concepts
| Term | Description |
|---|---|
| Carrier | Top-level record. Holds SIP host, credentials, capacity, codec list, status. |
| Carrier Route | A dialing rule attached to a carrier: prefix + priority + optional rate. The same destination prefix can exist on multiple carriers — routing picks by priority then weight. |
| Health Status | Health-checker pings the carrier's SIP host and updates health_status (healthy, degraded, unhealthy). Calls don't get routed to unhealthy carriers. |
| LCR | Least-Cost Routing. Internal lookup that picks a carrier for a destination by walking matching routes in priority order. |
Endpoints
All carrier management endpoints are scoped to your account. Both the account-scoped and ID-only forms are accepted; prefer the account-scoped form so resources stay attached to the right Auth ID.
| Method | Path | Purpose |
|---|---|---|
POST | /v1/account/{auth_id}/carriers | Create a carrier |
GET | /v1/account/{auth_id}/carriers | List carriers |
GET | /v1/account/{auth_id}/carriers/{id} | Get a carrier |
PUT | /v1/account/{auth_id}/carriers/{id} | Update a carrier |
DELETE | /v1/account/{auth_id}/carriers/{id} | Delete a carrier |
GET | /v1/account/{auth_id}/carriers/{id}/routes | List carrier routes |
POST | /v1/account/{auth_id}/carriers/{id}/routes | Add a route |
DELETE | /v1/account/{auth_id}/carriers/{carrier_id}/routes/{route_id} | Delete a route |
GET | /v1/account/{auth_id}/carriers/{id}/health | Get health log |
Create a carrier
POST /v1/account/{auth_id}/carriersRequest body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Display name. |
code | string | no | Short identifier you can use in routing rules (e.g. CC-IN). Defaults to a slug of name. |
carrier_type | string | no | inbound, outbound, or bidirectional. Default: outbound. |
sip_host | string | conditional | SIP host or FQDN. Required for outbound carriers. |
sip_port | integer | no | Default: 5060. |
transport | string | no | udp, tcp, or tls. Default: udp. |
auth_username | string | no | SIP digest username if the carrier requires auth. |
auth_password | string | no | SIP digest password. Stored encrypted. |
max_channels | integer | no | Concurrent call cap. Calls beyond this fall through to the next carrier. |
priority | integer | no | Higher wins. Default: 100. |
weight | integer | no | Round-robin weight among carriers with the same priority. Default: 1. |
health_check_url | string | no | URL to GET for health checks (instead of SIP OPTIONS ping). |
config | string | no | Free-form JSON for carrier-specific overrides. |
Example
curl -X POST https://api.tryvox.io/v1/account/$TRYVOX_AUTH_ID/carriers \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Telecom — IN",
"code": "ACME-IN",
"carrier_type": "outbound",
"sip_host": "sip.acmetel.example",
"sip_port": 5060,
"transport": "udp",
"auth_username": "tryvox-trunk-42",
"auth_password": "<sip-secret>",
"max_channels": 200,
"priority": 100
}'Response
201 Created — the full carrier record:
{
"id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
"name": "Acme Telecom — IN",
"code": "ACME-IN",
"carrier_type": "outbound",
"sip_host": "sip.acmetel.example",
"sip_port": 5060,
"transport": "udp",
"auth_username": "tryvox-trunk-42",
"max_channels": 200,
"active_channels": 0,
"priority": 100,
"weight": 1,
"status": "active",
"health_status": "unknown",
"codec_preferences": ["PCMU", "PCMA"],
"country_code": "IN",
"created_at": "2026-04-09T10:30:00Z"
}auth_password is never returned. To rotate, PUT a new value.
List carriers
GET /v1/account/{auth_id}/carrierscurl -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
https://api.tryvox.io/v1/account/$TRYVOX_AUTH_ID/carriersReturns 200 OK with an array of carrier records.
Get a carrier
GET /v1/account/{auth_id}/carriers/{id}Returns 200 OK with the same shape as Create. Returns 404 NOT_FOUND if the carrier doesn't exist or belongs to another account.
Update a carrier
PUT /v1/account/{auth_id}/carriers/{id}Pass any subset of the create fields; only the keys present are applied. Use this to rotate credentials, change priority, or flip status between active and disabled.
curl -X PUT https://api.tryvox.io/v1/account/$TRYVOX_AUTH_ID/carriers/$CARRIER_ID \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
-H "Content-Type: application/json" \
-d '{"priority": 50, "max_channels": 400}'Returns 200 OK with the updated carrier.
Delete a carrier
DELETE /v1/account/{auth_id}/carriers/{id}Returns 204 No Content. Routes attached to the carrier are removed at the same time. In-flight calls already routed through the carrier complete normally; no new calls match.
Carrier Routes
Routes attach to a single carrier and define which destinations the carrier handles.
List routes
GET /v1/account/{auth_id}/carriers/{id}/routes[
{
"id": "1b2c3d4e-5f60-7180-9a2b-3c4d5e6f7a8b",
"carrier_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
"prefix": "+91",
"priority": 100,
"rate": 0.0085,
"rate_currency": "USD",
"status": "active",
"created_at": "2026-04-09T10:31:00Z"
}
]Add a route
POST /v1/account/{auth_id}/carriers/{id}/routes| Field | Type | Required | Description |
|---|---|---|---|
prefix | string | yes | E.164 prefix to match (e.g. +91, +9198, +1415). Longer prefixes win over shorter ones. |
priority | integer | no | Within prefix matches across carriers, higher priority wins. Default: 100. |
rate | number | no | Per-minute rate. Used by LCR when picking among equal-priority carriers. |
rate_currency | string | no | ISO 4217 currency code. Default: USD. |
curl -X POST https://api.tryvox.io/v1/account/$TRYVOX_AUTH_ID/carriers/$CARRIER_ID/routes \
-u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
-H "Content-Type: application/json" \
-d '{"prefix": "+91", "priority": 100, "rate": 0.0085}'201 Created with the new route.
Delete a route
DELETE /v1/account/{auth_id}/carriers/{carrier_id}/routes/{route_id}Returns 204 No Content.
Health log
GET /v1/account/{auth_id}/carriers/{id}/healthReturns the most recent health probes (latest first):
[
{
"id": "...",
"carrier_id": "...",
"status": "healthy",
"response_time_ms": 42,
"created_at": "2026-04-09T10:34:00Z"
},
{
"id": "...",
"carrier_id": "...",
"status": "unhealthy",
"error_message": "SIP OPTIONS timeout",
"created_at": "2026-04-09T10:30:00Z"
}
]Health checks run every 30 seconds by default and update carriers.health_status automatically. Two consecutive failures flip the carrier to unhealthy and remove it from routing; one success flips it back.
Routing decision
When you place an outbound call:
- The destination
tonumber is normalised to E.164. - The router walks routes whose
prefixmatches the destination, longest-prefix first. - Among matches, carriers are ranked by
priority(descending), then byweight(round-robin), then byrate(ascending) for LCR. - Carriers with
status != active,health_status = unhealthy, oractive_channels >= max_channelsare skipped. - The first surviving carrier wins. If none survive, the call fails with
502 NO_CARRIER_AVAILABLE.
You can preview the decision with the internal LCR endpoint surfaced for support — contact us if you need API access for capacity planning.
Notes
- Credentials are write-only.
auth_passwordis never returned by GET. Rotate viaPUT. - Carriers are tenant-scoped. Other accounts on the platform can't see or use yours.
- Soft-disable instead of delete when iterating: set
status: "disabled"to remove from routing without losing the configuration. - Default carriers still exist — BYOC carriers are added to the routing pool, not as a replacement, unless you explicitly disable the defaults.