Appearance
Disclosure scripts
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.
Collection-notice script library (ADR #219): immutable versions per tenant, approved by a sealed event.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/disclosure-scripts | The tenant's collection-notice script versions, with their status |
POST | /v1/disclosure-scripts | Write a DRAFT version of a collection-notice script |
POST | /v1/disclosure-scripts/{id}/approve | Approve a draft version (sealed in the compliance chain) |
POST | /v1/disclosure-scripts/{id}/retire | Retire an approved version (sealed in the compliance chain) |
The tenant's collection-notice script versions, with their status
http
GET /v1/disclosure-scriptsEvery version of every selector, ordered by jurisdiction, debt_type and then the newest version first. The status comes from the sealed events, never from the version row: a version with no approved event is a draft and never reads as approved. jurisdiction, debt_type and status filter. Readable by any tenant-scope token (a dd_ key or a dashboard login).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
jurisdiction | query | string | no | |
debt_type | query | string | no | |
status | query | draft · approved · retired | no |
Responses
200
The versions.
| Field | Type | Required | Description |
|---|---|---|---|
scripts | array of DisclosureScript | yes | |
scripts[].id | string (uuid) | yes | |
scripts[].tenant_id | string (uuid) | yes | |
scripts[].kind | collection_notice | yes | |
scripts[].jurisdiction | string | yes | |
scripts[].debt_type | string | yes | |
scripts[].version | integer | yes | Per tenant and selector. |
scripts[].text | string | yes | |
scripts[].text_sha256 | string | yes | SHA-256 (lower hex) of text, derived by core. |
scripts[].legal_ref | string | yes | |
scripts[].authored_by | string | yes | |
scripts[].status | draft · approved · retired | yes | Read from the sealed events; no approved event means draft. |
scripts[].approval | DisclosureScriptEvent | null | no | |
scripts[].retirement | DisclosureScriptEvent | null | no | |
scripts[].created_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"
}
}Write a DRAFT version of a collection-notice script
http
POST /v1/disclosure-scriptsCreates an immutable draft for the selector (jurisdiction, debt_type); the version number is assigned by core (max + 1 per tenant and selector). A draft is NOT an approved script: it needs POST .../approve. text is at most 10 000 bytes; text_sha256 is derived by core from the text and is never accepted from the client. legal_ref (the citation of the rule or opinion the text rests on) is required and not blank. jurisdiction is a USPS state code or *; debt_type is other, student_loan or *. Unknown fields are 400. The platform does not judge the legal content of the text. Needs a dd_ key or a dashboard login with the account_admin role.
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
kind | collection_notice | no | |
jurisdiction | string | yes | A USPS state code (upper case) or * for any. |
debt_type | other · student_loan · * | yes | * for any. |
text | string | yes | At most 10 000 BYTES; not blank. |
legal_ref | string | yes | The citation of the rule or opinion the text rests on; not blank. |
json
{
"jurisdiction": "*",
"debt_type": "*",
"text": "Texto del aviso redactado y revisado por el despacho del tenant.",
"legal_ref": "Dictamen interno 2026-10 del despacho"
}Responses
201
The draft.
| Field | Type | Required | Description |
|---|---|---|---|
script | object (DisclosureScript) | yes | One immutable version of a collection-notice script and its status. |
script.id | string (uuid) | yes | |
script.tenant_id | string (uuid) | yes | |
script.kind | collection_notice | yes | |
script.jurisdiction | string | yes | |
script.debt_type | string | yes | |
script.version | integer | yes | Per tenant and selector. |
script.text | string | yes | |
script.text_sha256 | string | yes | SHA-256 (lower hex) of text, derived by core. |
script.legal_ref | string | yes | |
script.authored_by | string | yes | |
script.status | draft · approved · retired | yes | Read from the sealed events; no approved event means draft. |
script.approval | DisclosureScriptEvent | null | no | |
script.retirement | DisclosureScriptEvent | null | no | |
script.created_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 — DisclosureScriptWriteForbidden
A script write was refused. code role_forbidden: the caller is a member login (the route takes a dd_ key or an account_admin login). code forbidden: the tenant is suspended or the token is a widget token.
json
{
"error": {
"code": "role_forbidden",
"message": "approving a disclosure script takes a dd_ key or a dashboard login with the account_admin role"
}
}Approve a draft version (sealed in the compliance chain)
http
POST /v1/disclosure-scripts/{id}/approveWrites an append-only approved event and seals it in the tenant's compliance chain in the SAME transaction: if the seal fails nothing is written and the version stays a draft. reviewed_by (the person or firm that reviewed the text) is required. A version that is already approved or retired is 409. Another tenant's version, or a non-UUID id, is 404. Needs a dd_ key or an account_admin login.
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 |
|---|---|---|---|
reviewed_by | string | yes |
json
{
"reviewed_by": "Despacho de ejemplo"
}Responses
200
The version, now approved.
| Field | Type | Required | Description |
|---|---|---|---|
script | object (DisclosureScript) | yes | One immutable version of a collection-notice script and its status. |
script.id | string (uuid) | yes | |
script.tenant_id | string (uuid) | yes | |
script.kind | collection_notice | yes | |
script.jurisdiction | string | yes | |
script.debt_type | string | yes | |
script.version | integer | yes | Per tenant and selector. |
script.text | string | yes | |
script.text_sha256 | string | yes | SHA-256 (lower hex) of text, derived by core. |
script.legal_ref | string | yes | |
script.authored_by | string | yes | |
script.status | draft · approved · retired | yes | Read from the sealed events; no approved event means draft. |
script.approval | DisclosureScriptEvent | null | no | |
script.retirement | DisclosureScriptEvent | null | no | |
script.created_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 — DisclosureScriptWriteForbidden
A script write was refused. code role_forbidden: the caller is a member login (the route takes a dd_ key or an account_admin login). code forbidden: the tenant is suspended or the token is a widget token.
json
{
"error": {
"code": "role_forbidden",
"message": "approving a disclosure script takes a dd_ key or a dashboard login with the account_admin role"
}
}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"
}
}Retire an approved version (sealed in the compliance chain)
http
POST /v1/disclosure-scripts/{id}/retireWrites an append-only retired event and seals it, like approval. Only an approved version is retired: a draft is 409 (it was never approved) and so is one already retired. reviewed_by is optional here. Another tenant's version, or a non-UUID id, is 404. Needs a dd_ key or an account_admin login.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
reviewed_by | string | no |
Responses
200
The version, now retired.
| Field | Type | Required | Description |
|---|---|---|---|
script | object (DisclosureScript) | yes | One immutable version of a collection-notice script and its status. |
script.id | string (uuid) | yes | |
script.tenant_id | string (uuid) | yes | |
script.kind | collection_notice | yes | |
script.jurisdiction | string | yes | |
script.debt_type | string | yes | |
script.version | integer | yes | Per tenant and selector. |
script.text | string | yes | |
script.text_sha256 | string | yes | SHA-256 (lower hex) of text, derived by core. |
script.legal_ref | string | yes | |
script.authored_by | string | yes | |
script.status | draft · approved · retired | yes | Read from the sealed events; no approved event means draft. |
script.approval | DisclosureScriptEvent | null | no | |
script.retirement | DisclosureScriptEvent | null | no | |
script.created_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 — DisclosureScriptWriteForbidden
A script write was refused. code role_forbidden: the caller is a member login (the route takes a dd_ key or an account_admin login). code forbidden: the tenant is suspended or the token is a widget token.
json
{
"error": {
"code": "role_forbidden",
"message": "approving a disclosure script takes a dd_ key or a dashboard login with the account_admin role"
}
}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"
}
}