Release a tenant number
Marks the number released, returns the DID to the available pool,
and emits a number.released event. Idempotent —
re-releasing a released number returns 204 with no event.
Authorization
bearerAuth Long-lived ES256 JWT minted from the dashboard (https://app.sautikit.com/developers/api-keys). Signed by the
platform keyring. Carries workspace_id and scopes claims;
revoked via the platform deny-list.
In: header
Path Parameters
uuidResponse Body
application/json
curl -X DELETE "https://example.com/v1/numbers/497f6eca-6276-4993-bfeb-53cbbbba6f08"{ "error": { "code": "validation.bad_request", "message": "string", "request_id": "string", "details": [ "string" ] }}Get a single tenant number by id GET
Previous Page
Update a tenant number's routing config PUT
Patches `voice_callback_url`, `events_url`, and/or `inbound_agent` on a number's routing config. `voice_callback_url`/`events_url` accept http or https; empty string clears either field; omitted fields are left untouched. The `Idempotency-Key` header is honoured for replay safety. ## Assign an AI agent to this number Send an `inbound_agent` object to make one of your AI agents answer inbound calls to this number instead of POSTing to `voice_callback_url`: ```json { "inbound_agent": { "enabled": true, "agent_id": "9d2b1f53-8c0e-4f1d-9a6b-5d3a8c47e9f0", "mode": "always", "handover_callback_url": "https://example.com/sautikit/voice" } } ``` - `agent_id` — an agent in this workspace that has at least one PUBLISHED REVISION. An agent you are currently editing still qualifies: its live published revision keeps answering while the new draft is unpublished. - `mode` — `always` (answer every inbound call) or `after_hours` (answer only outside the `schedule` windows; see `InboundAgentConfig`). - `handover_callback_url` — REQUIRED while `enabled` unless you set `handover_forward` or `handover_voicemail` (either one answers the handover itself); defaults to this number's `voice_callback_url` when omitted. Sautikit POSTs the `CallHandover` event here when the agent transfers the call (e.g. to a human); you respond with voice actions (`dial`, `say`, …). See the `CallHandoverCallback` schema. To STOP an AI agent answering, send `inbound_agent: null` (clears the binding). To pause without clearing, send the object with `enabled: false`. `inbound_agent` uses TRI-STATE semantics distinct from the two URL fields above (which only distinguish set-non-empty vs clear-via-empty-string): - **omitted from the request body** — leave the current binding untouched. - **JSON `null`** — clear the binding (no AI agent answers this number; routing falls through to `voice_callback_url` / legacy voice-actions). - **a JSON object** — validate (see `InboundAgentConfig`) and set. ## Forward a number Send a `forward` object to ring one or more destinations when this number is called directly (the same shape also appears under `InboundAgentConfig.handover_forward` for AI-agent handover): ```json { "forward": { "destinations": ["+254700000001", "+254700000002"], "sequential": false, "first_answer_wins": true, "ring_timeout": 20 } } ``` `forward` uses the SAME tri-state semantics as `inbound_agent`: omit to keep the current target, send `null` to clear it, or send a `ForwardTarget` object to validate and set it (`numbers.invalid_forward` on failure). ## Queue the call Send a `queue` object to hold callers in an ordered line, announce their position, and offer them to a pool one caller at a time: ```json { "queue": { "enabled": true, "greeting_text": "All of our team are busy. Please hold.", "agents": { "destinations": ["1001", "1002"], "first_answer_wins": true, "ring_timeout": 20 }, "announce_every_seconds": 90, "on_timeout": "voicemail", "voicemail": { "greeting_text": "Leave a message." } } } ``` A four-digit destination is an internal extension and rings the device registered to it. `queue` uses the same tri-state semantics as `inbound_agent`, and OUTRANKS `forward` and `voicemail` when enabled — so a number may keep a forward configured as the fallback it reverts to when the queue is switched off. Hold time is bounded by the PBX rather than by this config: the box allows 50 actions per call, so a caller can hold for roughly ten minutes at the default cadence. The queue takes its `on_timeout` exit before that runs out, so the caller is offered voicemail rather than cut off. ## Send to voicemail Send a `voicemail` object to configure a reusable voicemail fallback (a text-to-speech greeting or a pre-recorded greeting URL, plus recording limits): ```json { "voicemail": { "greeting_text": "Sorry we missed your call. Leave a message after the tone.", "max_length": 120, "beep": true } } ``` `voicemail` is also tri-state: omit to keep, `null` to clear, an object to validate and set (`numbers.invalid_voicemail` on failure). `beep` is accepted and stored but not yet rendered on the live call (reserved for a future release). ## Outbound routing mode Set `outbound_mode` to control how calls PLACED FROM this number route on the outbound edge (it has no effect on inbound): - `server` (default; also the value when unset) — forward to `voice_callback_url` when set, else auto-bridge the requested destination. - `connect` — auto-bridge the requested destination directly with no webhook round trip, IGNORING `voice_callback_url` on the outbound leg (that URL still serves the inbound "your server" mode). `outbound_mode` is a string field: omit to keep the current value, send an empty string to reset to `server`, or send `connect` (`numbers.invalid_outbound_mode` on any other value).