Docs

RingTrunk REST API reference

The RingTrunk developer API. Authenticate with an API key, create and manage SIP trunks, attach Indian phone numbers, set origination URIs, rotate credentials, and read call records. One JSON envelope, cursor pagination, snake_case fields.

Updated 6 September 2026

In short: The RingTrunk REST API at https://ringtrunk.com/api/v1 creates trunks, attaches Indian numbers, sets where inbound calls go, rotates credentials and reads call records, with one JSON envelope and an X-API-Key header.

Everything in the portal is available programmatically. The base URL is https://ringtrunk.com/api/v1. Field names are snake_case. If you have used Twilio's SIP trunking API, the shapes will feel familiar.

Authentication

Create a key under API keys in the portal and send it in the X-API-Key header. Keys are scoped to what they need and are shown once.

bash
curl https://ringtrunk.com/api/v1/trunks \
  -H "X-API-Key: cw_live_your_key_here"

Response envelope

Every response uses one envelope.

Success
{ "success": true, "data": { } }
List
{ "success": true, "data": [ ],
  "pagination": { "limit": 50, "has_more": true, "next_cursor": "…" } }
Error
{ "success": false,
  "error": { "code": "TRUNK_NOT_FOUND", "message": "…", "details": { } } }

Lists use cursor pagination: pass next_cursor back as cursor. There is no total and no offset. Status codes are 200, 201, 400, 401, 403, 404, 409, 429, 500 and 503.

Endpoints

MethodPathPurpose
POST/trunksCreate a trunk. The SIP password is returned once, in this response.
GET/trunksList your trunks.
GET/trunks/{sid}Read one trunk. Never includes the password.
PATCH/trunks/{sid}Update friendly_name, status (active or suspended) or cps_limit.
DELETE/trunks/{sid}Delete a trunk. Add ?detach_numbers=true to release its numbers first.
POST/trunks/{sid}/credentials/rotateIssue a new SIP password, returned once.
GET/trunks/{sid}/origination-urisRead where inbound calls are delivered.
PUT/trunks/{sid}/origination-urisReplace the list. Whole-list write, ordered by priority.
GET/trunks/{sid}/numbersNumbers attached to the trunk.
POST/trunks/{sid}/numbersAttach a number: { "did": "9XXXXXXXXX" }.
PATCH/trunks/{sid}/numbers/{did}Set or clear forward_number for callback forwarding.
DELETE/trunks/{sid}/numbers/{did}Detach a number.
GET/numbersEvery number on your account with its attachment state.
GET/callsCall records, newest first. Filters: trunk_sid, from, to, limit, cursor.

Create a trunk

bash
curl -X POST https://ringtrunk.com/api/v1/trunks \
  -H "X-API-Key: cw_live_your_key_here" \
  -H "content-type: application/json" \
  -d '{"friendly_name": "production"}'

Optional fields: origination_uris, ip_acl and cps_limit. Numbers cannot be attached at creation time; create the trunk, then attach each number so the number and its inbound route are written together. A new trunk is always active.

The 201 response carries the trunk and its SIP password. The password is stored encrypted and there is no read-back path anywhere in the API. Losing it means rotating.

Trunk object

FieldMeaning
trunk_sidThe trunk id and SIP username. TR followed by 16 lowercase characters.
friendly_nameYour label.
statusactive or suspended.
channel_limitConcurrent calls, derived from the channels bought with the attached numbers. Read only.
cps_limitCalls per second.
numbersNumbers attached to the trunk; the caller IDs it may present.
origination_urisWhere inbound calls are delivered: uri, priority, enabled, and optionally user — the ID before the @ for platforms that route on it (see inbound calls).
termination.has_password, termination.ip_aclWhether a password is set, and the optional address allow-list for outbound calls.
created_at, updated_atTimestamps.

Origination URIs

bash
curl -X PUT https://ringtrunk.com/api/v1/trunks/TRxxxxxxxxxxxxxxxx/origination-uris \
  -H "X-API-Key: cw_live_your_key_here" \
  -H "content-type: application/json" \
  -d '{"origination_uris": [
        {"uri": "your-project.sip.livekit.cloud:5060;transport=tcp", "priority": 10, "enabled": true},
        {"uri": "backup.example.com:5060;transport=tcp", "priority": 20, "enabled": true}
      ]}'

Entries are tried in ascending priority order until one answers. Each URI is validated at write time and rejected with the specific reason (a path, an IPv6 literal, a sips: scheme, a trailing space, a malformed user part) rather than accepted into a configuration that cannot work. A user — the ID before the @ — is accepted as its own field or embedded in uri ([email protected]:5061;transport=tls); transport=tls destinations are delivered over TLS with SRTP media.

Rotate credentials

bash
curl -X POST https://ringtrunk.com/api/v1/trunks/TRxxxxxxxxxxxxxxxx/credentials/rotate \
  -H "X-API-Key: cw_live_your_key_here"

The new password is returned once. It becomes active within 60 seconds, the previous password keeps working until then, and existing registrations are not dropped. To cut a compromised trunk off immediately, suspend it first with PATCH {"status": "suspended"} and rotate afterwards.

Call records

bash
curl "https://ringtrunk.com/api/v1/calls?limit=25" \
  -H "X-API-Key: cw_live_your_key_here"

Each record carries direction, trunk_sid, did, destination, status, hangup_cause, duration_seconds, created_at and ended_at. Records are scoped to your account.

Portal sessions

Portal routes use Authorization: Bearer <ID token> from the signed-in session. Developer integrations should use API keys.