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
| State | Description |
|---|---|
warming | New DID ramping up call volume gradually |
active | Fully operational, in rotation for outbound calls |
cooling | Temporarily pulled from rotation to recover health |
burned | Flagged as spam by carriers, removed from rotation |
quarantine | Under 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
| Parameter | Type | Required | Description |
|---|---|---|---|
areaCode | string | Yes | 3-digit US area code |
quantity | number | No | Number of results to return (default: 10) |
contains | string | No | Pattern 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
| Field | Type | Required | Description |
|---|---|---|---|
numbers | string[] | Yes | Phone 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
| Field | Type | Required | Description |
|---|---|---|---|
voiceUrl | string | No | Voice webhook URL |
smsUrl | string | No | SMS webhook URL |
statusCallbackUrl | string | No | Status callback URL |
state | string | No | DID state: active, cooling, or warming |
ivrId | string | null | No | IVR 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.
| Component | Weight | Description |
|---|---|---|
| Answer rate | 30% | Percentage of calls answered by a human |
| Avg call duration | 25% | Longer calls indicate genuine conversations |
| Human engagement | 20% | Calls where the human spoke back (not just answered) |
| No-answer trend | 15% | Direction of the no-answer rate (improving or worsening) |
| Spam DB clean | 10% | DID is not listed in known spam databases |
Health thresholds
| Score | Action |
|---|---|
| >= 0.8 | Healthy — no action needed |
| 0.7 – 0.8 | WARNING — monitor closely |
| 0.5 – 0.7 | COOLDOWN — auto-pulled from rotation |
| < 0.5 | BURNED — flagged for review, removed from all campaigns |
Warming schedule
New DIDs follow a gradual ramp-up to build carrier trust and avoid spam flags.
| Period | Max calls/day |
|---|---|
| Day 1–3 | 10 |
| Day 4–7 | 50 |
| Day 8–14 | 200 |
| 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.