Appearance
Callbacks
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.
Consumer-agreed redial appointments.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/callbacks | Callback queue view / due feed |
POST | /v1/callbacks | Schedule a consumer-agreed redial |
POST | /v1/callbacks/{id}/complete | pending → done |
POST | /v1/callbacks/{id}/cancel | pending → cancelled |
POST | /v1/callbacks/{id}/miss | pending → missed |
Callback queue view / due feed
http
GET /v1/callbacksdue=now (also true/1) is the runner-facing due feed (pending AND scheduled_at <= now, priority then time order); otherwise the queue view filtered by status (default pending, soonest first; done, cancelled and missed list the most recent appointment first). agent_id scopes to the callbacks that agent created. The queue view pages by keyset: pass the previous next_cursor as cursor (opaque; null on the last page). due=now is not paged.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
due | query | now · true · 1 | no | |
status | query | pending · done · cancelled · missed | no | |
campaign_id | query | string (uuid) | no | |
debt_id | query | string (uuid) | no | |
agent_id | query | string (uuid) | no | |
limit | query | integer | no | Page size (default 100, max 1000). |
cursor | query | string | no | Opaque keyset cursor from the previous page's next_cursor. |
Responses
200
Callbacks matching the view.
| Field | Type | Required | Description |
|---|---|---|---|
callbacks | array of Callback | yes | |
callbacks[].id | string (uuid) | no | |
callbacks[].tenant_id | string (uuid) | no | |
callbacks[].debt_id | string (uuid) | no | |
callbacks[].contact_phone | string | no | |
callbacks[].campaign_id | string (uuid) | null | no | |
callbacks[].agent_id | string (uuid) | null | no | |
callbacks[].scheduled_at | string (date-time) | no | |
callbacks[].note | string | null | no | |
callbacks[].priority | integer | no | |
callbacks[].status | pending · done · cancelled · missed | no | |
callbacks[].created_at | string (date-time) | no | |
callbacks[].updated_at | string (date-time) | no | |
next_cursor | string,null | no | Opaque cursor for the next page; null on the last page. |
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"
}
}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"
}
}Schedule a consumer-agreed redial
http
POST /v1/callbackscontact_phone must already be a contact of the debt (the gates need line/locale data) → 422 otherwise; less than the tenant's minimum notice (callback_min_notice_seconds, 10 minutes by default) → 422; the number is in R16 quarantine → 422 (the platform will not promise a call it cannot make); unknown debt → 404; bad timestamp → 400. campaign_id defaults to the ONE campaign whose population holds the debt — its own campaign_id, or the campaign of a list it is in. A debt in MORE than one campaign (its own and a list's, or two lists') has no default: omitting campaign_id, or sending it null, is 422 — the platform does not pick a campaign for the caller. The campaign runner dials due callbacks BEFORE fresh leads.
agent_id is the callback's CREATOR and is optional (a callback may have no agent). Who may name whom (ADR #133, ADR #134). The agent_id is bound by the PRINCIPAL, the same rule on every verb that reads one: a dd_ machine key names any agent of its tenant; a ddw_ only its own; a ddu_ login session linked to an agent seat acts as THAT seat — agent_id may be omitted (filled with the seat) or repeat it, and naming another agent is 403 forbidden; a ddu_ session with NO linked seat may name another agent only with users.role = account_admin — a member is 403 role_forbidden — once the tenant's catalog key ddu_author_role_enforced is on (born off: until then the seatless session keeps the dd_ contract on this verb).
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
debt_id | string (uuid) | yes | |
contact_phone | string | yes | E.164 of an existing contact of the debt. |
scheduled_at | string (date-time) | yes | RFC 3339, at least the tenant's callback_min_notice_seconds (10 minutes by default) in the future. |
campaign_id | string (uuid) | no | |
agent_id | string (uuid) | no | |
note | string | no | |
priority | integer | no |
json
{
"debt_id": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"contact_phone": "+13125551001",
"scheduled_at": "2026-07-06T16:30:00Z",
"note": "postman: consumer pidió el martes"
}Responses
201
Scheduled callback.
| Field | Type | Required | Description |
|---|---|---|---|
callback | object (Callback) | yes | |
callback.id | string (uuid) | no | |
callback.tenant_id | string (uuid) | no | |
callback.debt_id | string (uuid) | no | |
callback.contact_phone | string | no | |
callback.campaign_id | string (uuid) | null | no | |
callback.agent_id | string (uuid) | null | no | |
callback.scheduled_at | string (date-time) | no | |
callback.note | string | null | no | |
callback.priority | integer | no | |
callback.status | pending · done · cancelled · missed | no | |
callback.created_at | string (date-time) | no | |
callback.updated_at | string (date-time) | no |
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"
}
}403 — Forbidden
The tenant is suspended. A dashboard session (ddu_) of a tenant whose login policy (ADR 227) is in mode enforce answers 403 with the code login_policy_denied on a request from an address or at an hour the policy does not allow — the same body for both; the session is not revoked and a later request inside the policy goes through. A widget token (ddw_) of a seat is held to the same policy on every request (core#2406, flag widget_login_honors_policy). A synthetic (demo) tenant answers 403 with the code synthetic_tenant on every route that would reach a third party — manual dial, external transfer or conference leg, SMS send (core#2251, ADR #280 addendum). No payment changes it.
json
{
"error": {
"code": "forbidden",
"message": "tenant is suspended"
}
}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"
}
}422 — Unprocessable
Shape is fine, semantics are not (broken domain rule).
json
{
"error": {
"code": "unprocessable",
"message": "scheduled_at is closer than the minimum notice for a callback (10 minutes unless the tenant's callback_min_notice_seconds says otherwise)"
}
}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"
}
}pending → done
http
POST /v1/callbacks/{id}/completeStatus machine pending → done|cancelled|missed (terminal); 409 on re-transition.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The completed callback.
| Field | Type | Required | Description |
|---|---|---|---|
callback | object (Callback) | yes | |
callback.id | string (uuid) | no | |
callback.tenant_id | string (uuid) | no | |
callback.debt_id | string (uuid) | no | |
callback.contact_phone | string | no | |
callback.campaign_id | string (uuid) | null | no | |
callback.agent_id | string (uuid) | null | no | |
callback.scheduled_at | string (date-time) | no | |
callback.note | string | null | no | |
callback.priority | integer | no | |
callback.status | pending · done · cancelled · missed | no | |
callback.created_at | string (date-time) | no | |
callback.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). 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"
}
}409 — Conflict
Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.
json
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}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"
}
}pending → cancelled
http
POST /v1/callbacks/{id}/cancelParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The cancelled callback.
| Field | Type | Required | Description |
|---|---|---|---|
callback | object (Callback) | yes | |
callback.id | string (uuid) | no | |
callback.tenant_id | string (uuid) | no | |
callback.debt_id | string (uuid) | no | |
callback.contact_phone | string | no | |
callback.campaign_id | string (uuid) | null | no | |
callback.agent_id | string (uuid) | null | no | |
callback.scheduled_at | string (date-time) | no | |
callback.note | string | null | no | |
callback.priority | integer | no | |
callback.status | pending · done · cancelled · missed | no | |
callback.created_at | string (date-time) | no | |
callback.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). 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"
}
}409 — Conflict
Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.
json
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}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"
}
}pending → missed
http
POST /v1/callbacks/{id}/missParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The missed callback.
| Field | Type | Required | Description |
|---|---|---|---|
callback | object (Callback) | yes | |
callback.id | string (uuid) | no | |
callback.tenant_id | string (uuid) | no | |
callback.debt_id | string (uuid) | no | |
callback.contact_phone | string | no | |
callback.campaign_id | string (uuid) | null | no | |
callback.agent_id | string (uuid) | null | no | |
callback.scheduled_at | string (date-time) | no | |
callback.note | string | null | no | |
callback.priority | integer | no | |
callback.status | pending · done · cancelled · missed | no | |
callback.created_at | string (date-time) | no | |
callback.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). 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"
}
}409 — Conflict
Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.
json
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}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"
}
}