API

DIDs & Health API

Manage phone numbers, monitor health scores, and control DID lifecycle states.

DIDs (Direct Inward Dialing numbers) are the phone numbers in your pool. The hub continuously monitors their health and automatically manages lifecycle transitions to protect your caller reputation.

DID states

StateDescription
warmingNew DID ramping up call volume gradually
activeFully operational, in rotation for outbound calls
coolingTemporarily pulled from rotation to recover health
burnedFlagged as spam by carriers, removed from rotation
quarantineUnder review, not available for use

List DIDs

GET /dids

Returns all DIDs owned by the authenticated account.

curl "https://api.trunx.io/dids" \
  -H "Authorization: Bearer tk_live_..."
const res = await fetch("https://api.trunx.io/dids", {
  headers: { "Authorization": "Bearer tk_live_..." },
});
const data = await res.json();
import requests

res = requests.get(
    "https://api.trunx.io/dids",
    headers={"Authorization": "Bearer tk_live_..."},
)
data = res.json()

Search Available Numbers

GET /dids/search

Search for phone numbers available for purchase from the carrier pool.

Query parameters

ParameterTypeRequiredDescription
areaCodestringYes3-digit US area code
quantitynumberNoNumber of results to return (default: 10)
containsstringNoPattern to match (e.g. "555")
curl "https://api.trunx.io/dids/search?areaCode=949&quantity=5" \
  -H "Authorization: Bearer tk_live_..."
const res = await fetch("https://api.trunx.io/dids/search?areaCode=949&quantity=5", {
  headers: { "Authorization": "Bearer tk_live_..." },
});
const data = await res.json();

Response

{
  "available": [
    { "number": "+19495551234", "areaCode": "949", "city": "Irvine", "state": "CA", "cost": 1.50 }
  ]
}

Purchase Numbers

POST /dids/purchase

Purchase one or more phone numbers. Purchased DIDs enter the warming state automatically.

Request body

FieldTypeRequiredDescription
numbersstring[]YesPhone numbers in E.164 format
curl -X POST "https://api.trunx.io/dids/purchase" \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "numbers": ["+19495551234", "+19495555678"] }'
const res = await fetch("https://api.trunx.io/dids/purchase", {
  method: "POST",
  headers: {
    "Authorization": "Bearer tk_live_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ numbers: ["+19495551234", "+19495555678"] }),
});
const data = await res.json();

Response

{
  "purchased": ["+19495551234"],
  "failed": [],
  "totalCost": 1.50
}

Newly purchased DIDs start in the warming state and follow the warming schedule below before entering full rotation.


Release Number

DELETE /dids/{number}

Release a phone number back to the carrier.

curl -X DELETE "https://api.trunx.io/dids/+19495551234" \
  -H "Authorization: Bearer tk_live_..."

Response

{
  "released": true,
  "number": "+19495551234"
}

Releasing a number is permanent. The number will be returned to the carrier pool and may be reassigned to another customer. You cannot undo this action.


Configure Number

PATCH /dids/{number}

Update a DID's configuration including webhooks, state, and IVR assignment.

Request body

FieldTypeRequiredDescription
voiceUrlstringNoVoice webhook URL
smsUrlstringNoSMS webhook URL
statusCallbackUrlstringNoStatus callback URL
statestringNoDID state: active, cooling, or warming
ivrIdstring | nullNoIVR definition ID to assign (null to unassign)
curl -X PATCH "https://api.trunx.io/dids/+19495551234" \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "ivrId": "ivr_abc123" }'

Response

{
  "configured": true,
  "number": "+19495551234"
}

Get DID

GET /dids/:id

Returns DID details including current health score and state.


Health endpoints

All DIDs health

GET /dids/health

Returns all DIDs with their health scores, state, and call counts.

curl "https://api.trunx.io/dids/health" \
  -H "Authorization: Bearer tk_live_..."
const res = await fetch("https://api.trunx.io/dids/health", {
  headers: { "Authorization": "Bearer tk_live_..." },
});
const data = await res.json();
import requests

res = requests.get(
    "https://api.trunx.io/dids/health",
    headers={"Authorization": "Bearer tk_live_..."},
)
data = res.json()

Response

[
  {
    "number": "+19495551234",
    "state": "active",
    "health_score": 0.92,
    "total_calls": 487,
    "answer_rate": 0.68,
    "avg_duration": 34.2,
    "last_used": "2026-03-09T14:22:00.000Z"
  },
  {
    "number": "+17145559876",
    "state": "cooling",
    "health_score": 0.64,
    "total_calls": 312,
    "answer_rate": 0.41,
    "avg_duration": 12.8,
    "last_used": "2026-03-09T10:15:00.000Z"
  }
]

Pool health report

GET /dids/health/report

Returns an aggregate report across the entire DID pool.

{
  "total_dids": 54,
  "by_state": {
    "active": 42,
    "warming": 8,
    "cooling": 3,
    "burned": 1,
    "quarantine": 0
  },
  "avg_health": 0.88,
  "avg_answer_rate": 0.62,
  "dids_below_threshold": 4
}

Single DID health

GET /dids/:number/health

Returns detailed health data for a specific DID, including the breakdown of score components.


DID lifecycle actions

Cool down DID

POST /dids/:number/cooldown

Pull a DID from rotation temporarily. The DID enters cooling state and stops receiving outbound calls.

curl -X POST "https://api.trunx.io/dids/+19495551234/cooldown" \
  -H "Authorization: Bearer tk_live_..."
await fetch("https://api.trunx.io/dids/+19495551234/cooldown", {
  method: "POST",
  headers: { "Authorization": "Bearer tk_live_..." },
});
import requests

requests.post(
    "https://api.trunx.io/dids/+19495551234/cooldown",
    headers={"Authorization": "Bearer tk_live_..."},
)

Activate DID

POST /dids/:number/activate

Return a cooled-down DID to active rotation.

Burn DID

POST /dids/:number/burn

Permanently mark a DID as burned. Burned DIDs are removed from all campaign rotations and flagged for review.

Burning a DID is a significant action. Burned DIDs cannot be automatically reactivated and require manual review before returning to rotation.


Health score formula

The health score is computed over a sliding window of the last 50 calls for each DID.

ComponentWeightDescription
Answer rate30%Percentage of calls answered by a human
Avg call duration25%Longer calls indicate genuine conversations
Human engagement20%Calls where the human spoke back (not just answered)
No-answer trend15%Direction of the no-answer rate (improving or worsening)
Spam DB clean10%DID is not listed in known spam databases

Health thresholds

ScoreAction
>= 0.8Healthy — no action needed
0.7 – 0.8WARNING — monitor closely
0.5 – 0.7COOLDOWN — auto-pulled from rotation
< 0.5BURNED — flagged for review, removed from all campaigns

Warming schedule

New DIDs follow a gradual ramp-up to build carrier trust and avoid spam flags.

PeriodMax calls/day
Day 1–310
Day 4–750
Day 8–14200
Day 15+Full rotation (no limit)

The warming schedule is enforced automatically by the campaign engine. DIDs that exceed their warming limits are held until the next day.

On this page