VOICE / list-registered-sip-phone-numbers

Voice

List registered SIP phone numbers

Pull every Direct SIP (and Twilio-imported) phone number on your team when ops needs the phone_number_id for deletes, when a dashboard must show which E.164 lines route into Speech to Speech, or when you filter inventory by agent. Official Voice REST documents GET https://api.x.ai/v2/phone-numbers with Bearer API-key auth, optional limit / pagination_token / agent_id query parameters, and a JSON phone_numbers array. The SIP Phone Calls guide points at the same list when you must recover an id after create: match on the phone_number field, then use phone_number_id for delete.

What you need

An xAI inference API key for the team that registered the numbers, and at least one line already created with POST /v2/phone-numbers (usually origin: "byo_trunk" for a customer-owned E.164). Neighboring jobs include Handle SIP phone calls with Speech to Speech for register → webhook → WebSocket, Delete a registered SIP phone number for teardown, and Transfer a SIP call with refer once a live call_id exists. More voice jobs live on the Voice hub.

Call the list endpoint

Export the key outside of source control, then GET the collection. Default page size is 20; values above 100 clamp to 100.

export XAI_API_KEY="your_api_key"

curl -s "https://api.x.ai/v2/phone-numbers?limit=20" \
  -H "Authorization: Bearer ${XAI_API_KEY}"
import json
import os

import requests

headers = {"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"}
params = {"limit": 20}
response = requests.get(
    "https://api.x.ai/v2/phone-numbers",
    headers=headers,
    params=params,
)
response.raise_for_status()
payload = response.json()
for row in payload.get("phone_numbers", []):
    print(row["phone_number_id"], row.get("phone_number"), row.get("name"), row.get("origin"))

Expect objects with phone_number_id, E.164 phone_number, optional name, origin (byo_trunk or xai_provisioned), sip_host, optional agent_id / webhook_id, and timestamps. When another page exists, the response includes pagination_token — pass that exact value back as the pagination_token query parameter (it is the last phone_number_id from the prior page). To list only numbers routed to one agent, add agent_id=<id>.

Find an id for delete or ops

After listing, keep phone_number_id for Delete a registered SIP phone number. Matching on human-readable E.164 alone is fine for dashboards; the path parameter for delete is always the id. Digest passwords never appear on list or get — only auth_username and allowed_addresses show when SIP auth was configured at create time.

Pitfalls

Assuming create response alone is enough forever fails when the create payload was lost — list is the recovery path for phone_number_id. Ignoring pagination_token on large teams silently drops lines past the first page. Filtering by a wrong agent_id returns an empty array even though other numbers exist on the team. Treating list as a live call control API confuses inventory with call_id from realtime.call.incoming; transfers and hangups use the call id, not phone_number_id.