DIDs (caller IDs)
Generated from
DialerDigital/corecommit6e9f026f0a72— specopenapi/dialer-v1.yamlv0.36.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.
DID registry + CDR-computed health.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/dids | DID registry |
POST | /v1/dids | Register a tenant-owned number |
GET | /v1/dids/{id} | Fetch one DID |
PATCH | /v1/dids/{id} | Update metadata/status (e164 immutable) |
DELETE | /v1/dids/{id} | Retire a DID (rows never delete) |
GET | /v1/dids/{id}/health | CDR-computed DID health |
DID registry
GET /v1/didsParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
status | query | active · quarantine · retired | no |
Responses
200
Registry rows ordered by e164.
| Field | Type | Required | Description |
|---|---|---|---|
dids | array of DID | yes | |
dids[].id | string (uuid) | no | |
dids[].tenant_id | string (uuid) | no | |
dids[].e164 | string | no | Immutable after creation. |
dids[].npa | string | null | no | |
dids[].us_state | string | null | no | |
dids[].attestation | A · B · C · unknown | no | STIR/SHAKEN level the carrier signs. |
dids[].status | active · quarantine · retired | no | |
dids[].origin | house · customer | no | house rows are admin-minted platform inventory; the tenant surface only creates customer. |
dids[].labels | array of string | no | |
dids[].notes | string | null | no | |
dids[].created_at | string (date-time) | no | |
dids[].updated_at | string (date-time) | no |
400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}Register a tenant-owned number
POST /v1/didse164 unique per tenant → 409 conflict on duplicates; npa is derived from +1 numbers when omitted. The tenant surface can only ever create origin: customer rows — house inventory is admin-minted (POST /v1/admin/tenants/{id}/dids).
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
e164 | string | yes | E.164 (immutable after creation). |
npa | string | no | |
us_state | string | no | |
attestation | A · B · C · unknown | no | |
status | active · quarantine · retired | no | |
labels | array of string | no | |
notes | string | no | |
origin | house · customer | no | Accepted and IGNORED FOR SAFETY: a tenant can never mint origin: house, so any value here is overridden with customer. The enum mirrors the response schema because a GET of a house DID returns house — sending that value back does not fail, it has no effect. Declared so that THIS key does not become a 400 now that unknown keys are. It does NOT make the whole rendered object round-trip: id, tenant_id, created_at and updated_at are not accepted and DO get the 400. |
{
"e164": "+13125550142",
"us_state": "IL"
}Responses
201
Registered DID.
| Field | Type | Required | Description |
|---|---|---|---|
did | object (DID) | yes | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Immutable after creation. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | STIR/SHAKEN level the carrier signs. |
did.status | active · quarantine · retired | no | |
did.origin | house · customer | no | house rows are admin-minted platform inventory; the tenant surface only creates customer. |
did.labels | array of string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.updated_at | string (date-time) | no |
400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}409 — Conflict
Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}Fetch one DID
GET /v1/dids/{id}Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The DID.
| Field | Type | Required | Description |
|---|---|---|---|
did | object (DID) | yes | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Immutable after creation. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | STIR/SHAKEN level the carrier signs. |
did.status | active · quarantine · retired | no | |
did.origin | house · customer | no | house rows are admin-minted platform inventory; the tenant surface only creates customer. |
did.labels | array of string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.updated_at | string (date-time) | no |
401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}Update metadata/status (e164 immutable)
PATCH /v1/dids/{id}A different number is a different DID; CDR history is never re-attributed.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
npa | string | no | |
us_state | string | no | |
attestation | A · B · C · unknown | no | |
status | active · quarantine · retired | no | |
labels | array of string | no | |
notes | string | no | |
origin | house · customer | no | Accepted and IGNORED FOR SAFETY, same as on POST /v1/dids: origin is immutable and never cast, so any value here has no effect. Sending back the value a GET returned does not fail; the rest of the rendered object still does (id, tenant_id, e164, created_at, updated_at are a 400). |
{
"attestation": "A",
"labels": [
"postman"
],
"notes": "postman smoke"
}Responses
200
Updated DID.
| Field | Type | Required | Description |
|---|---|---|---|
did | object (DID) | yes | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Immutable after creation. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | STIR/SHAKEN level the carrier signs. |
did.status | active · quarantine · retired | no | |
did.origin | house · customer | no | house rows are admin-minted platform inventory; the tenant surface only creates customer. |
did.labels | array of string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.updated_at | string (date-time) | no |
400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}Retire a DID (rows never delete)
DELETE /v1/dids/{id}Sets status retired, idempotent. Rows never leave the registry (DELETE is revoked in Postgres): CDR from_number provenance must keep resolving for the Defense Packet.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The retired DID.
| Field | Type | Required | Description |
|---|---|---|---|
did | object (DID) | yes | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Immutable after creation. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | STIR/SHAKEN level the carrier signs. |
did.status | active · quarantine · retired | no | |
did.origin | house · customer | no | house rows are admin-minted platform inventory; the tenant surface only creates customer. |
did.labels | array of string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.updated_at | string (date-time) | no |
401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}CDR-computed DID health
GET /v1/dids/{id}/healthHealth is COMPUTED from the append-only CDR at read time — every number is a row count, never a cached score. short_call_rate (answered calls ended in under 15 s / answered) is the strongest CDR-side "spam likely" signal. Rates are null when the denominator is zero. reputation.hiya/reputation.tns are explicit nulls until an external feed is contracted. A retired DID still serves health (provenance outlives rotation).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
from | query | string (date-time) | no | RFC 3339 lower bound (endpoint-specific field; default trailing 30 UTC days where noted). |
to | query | string (date-time) | no | RFC 3339 upper bound. |
Responses
200
Computed health for the period (default trailing 30 UTC days).
| Field | Type | Required | Description |
|---|---|---|---|
did_id | string (uuid) | no | |
e164 | string | no | |
status | active · quarantine · retired | no | |
period | object | no | |
period.from | string (date-time) | no | |
period.to | string (date-time) | no | |
dials | integer | no | |
answered | integer | no | |
answer_rate | number | null | no | |
short_calls | integer | no | |
short_call_rate | number | null | no | |
short_call_seconds | integer | no | |
daily | array of object | no | |
daily[].date | string (date) | no | |
daily[].dials | integer | no | |
daily[].answered | integer | no | |
daily[].short_calls | integer | no | |
reputation | object | no | Explicit nulls until an external feed is contracted — render as pending, not zero. |
reputation.hiya | number | null | no | |
reputation.tns | number | null | no | |
reputation.note | string | no |
{
"did_id": "4e3d2c1b-0a9f-4e8d-7c6b-5a4f3e2d1c0b",
"e164": "+13125550184",
"status": "active",
"period": {
"from": "2026-06-05T00:00:00Z",
"to": "2026-07-05T00:00:00Z"
},
"dials": 412,
"answered": 67,
"answer_rate": 0.1626,
"short_calls": 24,
"short_call_rate": 0.3582,
"short_call_seconds": 15,
"daily": [
{
"date": "2026-06-01",
"dials": 80,
"answered": 14,
"short_calls": 5
}
],
"reputation": {
"hiya": null,
"tns": null,
"note": "external reputation feeds not integrated yet"
}
}400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}