---
title: sip_trunk.invalid
description: The SIP trunk request failed validation for the given auth_mode.
summary: >-
  Returned by PUT /v1/sip-trunk when a required field is missing or malformed
  for the submitted auth_mode. Fix the field named in the message and re-submit.
date: 2026-08-06T00:00:00.000Z
type: error
---


## Summary

`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.

## Cause

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.

## Resolution

Match the request to the rule the message names. A minimal valid `registration` trunk:

```bash
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:

```bash
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"]
  }'
```

## Example response

```json
{
  "error": {
    "code": "sip_trunk.invalid",
    "message": "proxy must be a host or host:port",
    "request_id": "req_01900000abc"
  }
}
```

## Next steps

- [Numbers concepts — bring your own SIP trunk](/developers/concepts/numbers#bring-your-own-sip-trunk)
- [`sip_trunk.not_found`](/developers/errors/sip_trunk.not_found) — a different `PUT /v1/sip-trunk` error, unrelated to the request body's shape
- [`workspace.locked_to_platform_numbers`](/developers/errors/workspace.locked_to_platform_numbers) — a valid trunk body can still be refused if the workspace already buys numbers from Sautikit
