Appearance
Consumers
Generated from
DialerDigital/corecommit0fc18008b3c8— specopenapi/dialer-v1.yamlv0.134.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.
Debtor card by consumer_ref: debts, DNC / cease-and-desist, Reg F counter and next permitted window, derived from the append-only sources.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/consumers/{id} | Debtor card (debts, DNC / cease-and-desist, Reg F counter, next permitted window) |
Debtor card (debts, DNC / cease-and-desist, Reg F counter, next permitted window)
http
GET /v1/consumers/{id}The card of ONE debtor, keyed by consumer_ref — the string core already counts Reg F under ({tenant, consumer_ref, debt_key}). core has no consumers entity and this adds none: the path id is the consumer_ref the CMS sent on POST /v1/debts/import, so the card and the Reg F gate cannot disagree about who "the same debtor" is. "" is the absence of a consumer, never a card.
Everything is DERIVED at request time from the append-only sources (call_attempts, conversations, cease_and_desist, the DNC lists); no counter or cache is added. Each debt is the public projection of GET /v1/debts (masked phone, no account_number) plus the debtor's name (debtor_name, core#1529), its Reg F counter and its own next window. No phone number is published: DNC state is counts per list.
window / next_window answer "when is the next time a call to this debtor is permitted?", in UTC and in the destination's local time. They come from running the REAL gates listed in evaluated_gates over a read-only snapshot, so the instant given is one the dialer itself would permit. They do NOT cover not_evaluated_gates (consent, AI / artificial voice, campaign state, DNC provisioning proofs), which depend on the campaign or on the dial. The answer is fail-closed: permitted_now / scheduled only when a gate run positively permitted that instant; undecidable (with reason) when it cannot decide — unresolvable destination time zone, no contacts, too many numbers to check, a gate that failed, nothing permitted inside the 9-day horizon — and suppressed / not_dialable when the debtor must not be called.
A consumer who exists only in another tenant is 404, indistinguishable from one that does not exist.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | The debtor's consumer_ref (1 to 128 characters, not blank, without NUL bytes). |
Responses
200
The card.
| Field | Type | Required | Description |
|---|---|---|---|
consumer | object (ConsumerCard) | yes | |
consumer.id | string | yes | The consumer_ref. |
consumer.identity | consumer_ref | yes | Which key identifies the consumer. core has no consumers entity; this is the key Reg F counts under. |
consumer.generated_at | string (date-time) | yes | The compliance-clock instant every figure was evaluated at. |
consumer.debts | array of ConsumerDebt | yes | |
consumer.debts_truncated | boolean | yes | True when the consumer has as many debts as the page cap; the windows are then undecidable (debts_truncated). |
consumer.cease_and_desist | object | yes | |
consumer.cease_and_desist.on_file | boolean | yes | Any record for the consumer suppresses contact on every debt, as the consent gate reads it. |
consumer.cease_and_desist.records | array of object | yes | |
consumer.cease_and_desist.records[].scope | consumer · debt | yes | |
consumer.cease_and_desist.records[].debt_external_ref | string | yes | |
consumer.cease_and_desist.records[].received_at | string (date-time) | yes | |
consumer.dnc | object | yes | Counts of the consumer's distinct phone numbers on each list. No number is published. |
consumer.dnc.contacts_total | integer | yes | |
consumer.dnc.contacts_checked | integer | yes | |
consumer.dnc.contacts_listed | integer | yes | |
consumer.dnc.lists | object | yes | |
consumer.dnc.lists.federal | integer | yes | |
consumer.dnc.lists.state | integer | yes | |
consumer.dnc.lists.internal_tenant | integer | yes | |
consumer.dnc.lists.internal_global | integer | yes | |
consumer.dnc.truncated | boolean | yes | True when the consumer has more numbers than the card checks. |
consumer.next_window | object (ConsumerWindow) | yes | The next instant a call is permitted by the time-dependent gates (ConsumerCard.evaluated_gates), or why there is none. |
consumer.next_window.status | permitted_now · scheduled · suppressed · not_dialable · undecidable | yes | permitted_now: the gates permit a call at generated_at. scheduled: the earliest permitted instant is at. suppressed: a DNC listing or a cease-and-desist forbids contact. not_dialable: the debt's state is not dialable. undecidable: the card cannot decide and says why in reason; it is never read as permission. |
consumer.next_window.reason | string | null | yes | Null for permitted_now / scheduled. Otherwise a code such as dnc_listed, cease_and_desist, debt_state_closed, no_contacts, tz_unresolved, too_many_contacts, debts_truncated, none_within_horizon, or the rule_id of the gate that blocked. |
consumer.next_window.at | string (date-time) | null | yes | Earliest permitted instant (UTC); null when there is none. |
consumer.next_window.destination_timezone | string | null | yes | IANA zone the quiet-hours gate evaluated first at at. |
consumer.next_window.destination_local_time | string (date-time) | null | yes | at in destination_timezone, with its UTC offset. |
consumer.negotiation_bounds | NegotiationBounds | null | yes | Active negotiation policy for this tenant's AI agent, or null if none. |
consumer.promise_max_horizon_days | integer | yes | The tenant's promise_max_horizon_days (90 by default) — how many days ahead a promise-to-pay may be dated, counted from the current UTC day. Lets a client offer only dates the wrap-up will accept. |
consumer.evaluated_gates | array of string | yes | Rule ids window / next_window are derived from. |
consumer.not_evaluated_gates | array of string | yes | Gates window / next_window do NOT cover. |
400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
json
{
"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). A dashboard session (ddu_) that a newer login of the same person ended answers the code session_superseded instead (tenant flag single_session_enforced), so the screen can say why it was signed out; a logout, an expired or an unknown token stay unauthorized.
json
{
"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).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}429 — ApiKeyRateLimited
This API key is over its request quota, or the tenant's keys together are over the tenant ceiling (core#2503) (code rate_limited). The request was not processed. Wait Retry-After seconds and retry; a refusal is not counted against the budget, so that wait is always enough. Bounded per API key and, above the keys, per tenant (api_tenant_requests_per_minute): a sibling key is unaffected until the tenant's keys together reach that ceiling. The quota applies to every operation reachable with a dd_ key, so the operations that name a more specific 429 (call control, dispositions, SMS, …) can ALSO answer this one with its X-RateLimit-* headers.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}