---
title: "Create an outbound SIP trunk (REGISTER or static peering)"
method: POST
path: "/sip/trunks"
tags: ["SIP Trunks"]
---

# Create an outbound SIP trunk (REGISTER or static peering)

`POST /sip/trunks`

Creates a typed SIP trunk. For `type: "sip_register"`, VoiceBlender begins REGISTERing to the supplied registrar URI with digest auth, refreshes before expiry, and routes inbound INVITEs that arrive on that peer's socket plus outbound INVITEs whose `from` matches the AOR through the trunk. For `type: "ip_ip"`, returns 501 (reserved, not yet implemented).

## Request body

- CreateTrunkRequest
  - `type` 'sip_register' | 'ip_ip', required — Trunk type discriminator. Only `sip_register` is implemented today; `ip_ip` is reserved and returns 501.
  - `app_id` string — Application identifier carried through to every event emitted by this trunk.
  - `sip_register` SIPRegisterTrunkSpec
    - `registrar_uri` string, required — Upstream registrar SIP URI (e.g. "sip:pbx.example.com:5060" or "sips:pbx.example.com:5061;transport=tls").
    - `aor` string, required — Address-of-record this trunk REGISTERs (e.g. "sip:alice@pbx.example.com"). Becomes the From URI on outbound REGISTER, and the From / P-Asserted-Identity host on outbound INVITEs placed `from` this AOR.
    - `username` string — Digest auth username. Defaults to the AOR user-part when empty.
    - `password` string, required — Digest auth password. Required. Never returned in any response.
    - `contact_user` string — Override the user-part of the Contact header sent in REGISTER. Defaults to the AOR user-part.
    - `expires_seconds` integer — Requested registration lifetime in seconds. Clamped to [SIP_OUTBOUND_REGISTRATION_MIN_EXPIRES_SECONDS, SIP_OUTBOUND_REGISTRATION_MAX_EXPIRES_SECONDS]. Default: SIP_OUTBOUND_REGISTRATION_DEFAULT_EXPIRES_SECONDS (3600).
  - `ip_ip` IPIPTrunkSpec
    - `peer_uri` string — Static peer SIP URI for IP-IP peering. Reserved; not yet implemented.

## Response `202`

Trunk accepted; REGISTER runs asynchronously

- CreateTrunkResponse
  - `id` string, required
  - `type` string, required
  - `status` string, required

## Other responses

- `400` — Invalid JSON, missing required field, or unknown type
- `501` — Trunk type reserved but not yet implemented (e.g. ip_ip)

---

[API](https://skmtc.net/voiceblender/apis/voiceblender-api.md) · [All operations](https://skmtc.net/voiceblender/apis/voiceblender-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/voiceblender/voiceblender-api/revisions/ad30827d3b57/schema)
