sip_trunk.invalid
The SIP trunk request failed validation for the given auth_mode.
sip_trunk.invalid means PUT /v1/sip-trunk was refused before anything was saved: some field in the request body does not fit the shape required for the trunk's auth_mode. The error message names the specific field that failed.
Validation runs the same way regardless of whether this is a first-time connection or an edit to an existing trunk, and checks these rules in order:
Always, for both modes:
auth_mode must be exactly "registration" or "ip_allowlist".username must be non-empty.proxy must be a bare hostname or host:port — letters, digits, ., _, -, and an optional : followed by 1-5 digits. No scheme, no path, no whitespace.realm, if supplied at all, is held to the same host/host:port shape as proxy.transport must be udp, tcp or tls (it defaults to udp when omitted).registration mode only:
password is required the first time a trunk is connected. On a later edit you can omit it to keep the password already on file — but a registration trunk that has never had one still has nothing to keep, so it fails the same way.ip_allowlist mode only:
country_code must be E.164 with a leading + (e.g. +254) — 1 to 3 digits, no leading zero.signaling_ips must contain at least one entry, and every entry must parse as either a bare IP address or a CIDR block.media_ips must contain at least one entry, and every entry must parse as either a bare IP address or a CIDR block. This is a separate field from signaling_ips — your carrier's call-setup address and its audio address are not assumed to be the same, so both are required even when they happen to be identical. Omitting media_ips is rejected here rather than accepted and left to produce a trunk with no audio.Match the request to the rule the message names. A minimal valid registration trunk:
curl -X PUT "https://api.sautikit.com/v1/sip-trunk" \
-H "Authorization: Bearer $SAUTIKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Head office trunk",
"auth_mode": "registration",
"proxy": "sip.example-carrier.com",
"transport": "udp",
"username": "sautikit_100",
"password": "…"
}'A minimal valid ip_allowlist trunk:
curl -X PUT "https://api.sautikit.com/v1/sip-trunk" \
-H "Authorization: Bearer $SAUTIKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Head office trunk",
"auth_mode": "ip_allowlist",
"proxy": "sip.example-carrier.com",
"transport": "udp",
"username": "sautikit_100",
"country_code": "+254",
"signaling_ips": ["203.0.113.10", "203.0.113.0/28"],
"media_ips": ["203.0.113.10", "203.0.113.0/28"]
}'{
"error": {
"code": "sip_trunk.invalid",
"message": "proxy must be a host or host:port",
"request_id": "req_01900000abc"
}
}sip_trunk.not_found — a different PUT /v1/sip-trunk error, unrelated to the request body's shapeworkspace.locked_to_platform_numbers — a valid trunk body can still be refused if the workspace already buys numbers from Sautikit