Skip to content

Segment filters ​

Generated from DialerDigital/core commit 0fc18008b3c8 — spec openapi/dialer-v1.yaml v0.134.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.

Español

Saved segmentation filters (the criteria of GET /v1/debts with a name), versioned append-only per tenant. Behind the debt_segmentation_enabled flag (ADR #221).

Endpoints ​

MethodPathSummary
GET/v1/segment-filtersThe tenant's saved segmentation filters, each with its current version
POST/v1/segment-filtersCreate a saved filter (version 1)
GET/v1/segment-filters/{id}One saved filter, at its current version
PATCH/v1/segment-filters/{id}Rename a filter, or edit its criteria into a NEW version
DELETE/v1/segment-filters/{id}Archive a saved filter
POST/v1/segment-filters/{id}/to-listFreeze what a saved filter selects NOW into a list
POST/v1/segment-filters/to-listFreeze what inline criteria select NOW into a list

The tenant's saved segmentation filters, each with its current version ​

http
GET /v1/segment-filters

Behind the debt_segmentation_enabled flag: with it off (the default) every /v1/segment-filters route answers 404, whatever the caller. By name, the live ones; ?include_archived=true adds the archived. Each filter comes with its CURRENT version. Capped at 2 000.

Parameters

NameInTypeRequiredDescription
include_archivedquerybooleanno

Responses

200 ​

The filters.

FieldTypeRequiredDescription
segment_filtersarray of SegmentFilteryes
segment_filters[].idstring (uuid)yes
segment_filters[].tenant_idstring (uuid)no
segment_filters[].namestringyes
segment_filters[].archivedbooleanyes
segment_filters[].versionintegeryesThe current version.
segment_filters[].criteriaanyyesThe criteria of the current version, in canonical form (lists sorted, without repeats).
segment_filters[].version_created_atstring (date-time)no
segment_filters[].created_atstring (date-time)no
segment_filters[].updated_atstring (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"
  }
}

Create a saved filter (version 1) ​

http
POST /v1/segment-filters

name is trimmed, not blank, at most 200 characters and unique among the tenant's LIVE filters (409). criteria goes through Dialer.Debts.Segment (ADR #221): a closed vocabulary, a value outside it is a 400, and phone, consumer_ref, external_ref and debtor_name are refused by name. The server stores the canonical form (lists sorted, without repeats). An empty object is valid: the whole portfolio. A tenant holds at most 500 live filters (422). Needs the tenant scope (403 for an agent token). With the flag off, 404.

Request body (JSON, required)

FieldTypeRequiredDescription
namestringyes
criteriaobject (SegmentCriteria)yesCriteria accepted by the segment-filter writes and to-list routes (Dialer.Debts.Segment, ADR #221). A closed vocabulary, combined with AND; an empty object is the whole portfolio. state, debt_type, us_state and regf_status take one value or a list (they are always returned as a sorted list without repeats). phone, consumer_ref, external_ref and debtor_name are refused by name.
criteria.campaign_idstring (uuid)no
criteria.stateopen · in_collection · promise_to_pay · paid · settled · disputed · closed | array of open · in_collection · promise_to_pay · paid · settled · disputed · closedno
criteria.debt_typeother · student_loan | array of other · student_loanno
criteria.us_statestring | array of stringno
criteria.regf_statusok · blocked_7in7 · blocked_post_contact · undecidable | array of ok · blocked_7in7 · blocked_post_contact · undecidablenoADR #221 criterion: current Reg F eligibility derived by the server.
criteria.min_amount_centsintegerno
criteria.max_amount_centsintegerno
criteria.min_age_daysintegernoADR #221 criterion: delinquent for at least this many days (debts.delinquent_since against today); a debt with no delinquent_since never matches.
criteria.max_age_daysintegernoADR #221 criterion: delinquent for at most this many days (debts.delinquent_since against today); a debt with no delinquent_since never matches. A min_age_days above max_age_days is refused.
json
{
  "name": "Texas student loans over 500 USD",
  "criteria": {
    "debt_type": [
      "student_loan"
    ],
    "us_state": [
      "TX"
    ],
    "min_amount_cents": 50000
  }
}

Responses

201 ​

The filter, at version 1.

FieldTypeRequiredDescription
segment_filterobject (SegmentFilter)yesA saved filter: its header and its CURRENT version.
segment_filter.idstring (uuid)yes
segment_filter.tenant_idstring (uuid)no
segment_filter.namestringyes
segment_filter.archivedbooleanyes
segment_filter.versionintegeryesThe current version.
segment_filter.criteriaanyyesThe criteria of the current version, in canonical form (lists sorted, without repeats).
segment_filter.version_created_atstring (date-time)no
segment_filter.created_atstring (date-time)no
segment_filter.updated_atstring (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"
  }
}

409 — Conflict ​

Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.

json
{
  "error": {
    "code": "conflict",
    "message": "invalid state transition"
  }
}

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)"
  }
}

One saved filter, at its current version ​

http
GET /v1/segment-filters/{id}

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Responses

200 ​

The filter (archived ones too, flagged archived).

FieldTypeRequiredDescription
segment_filterobject (SegmentFilter)yesA saved filter: its header and its CURRENT version.
segment_filter.idstring (uuid)yes
segment_filter.tenant_idstring (uuid)no
segment_filter.namestringyes
segment_filter.archivedbooleanyes
segment_filter.versionintegeryesThe current version.
segment_filter.criteriaanyyesThe criteria of the current version, in canonical form (lists sorted, without repeats).
segment_filter.version_created_atstring (date-time)no
segment_filter.created_atstring (date-time)no
segment_filter.updated_atstring (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"
  }
}

Rename a filter, or edit its criteria into a NEW version ​

http
PATCH /v1/segment-filters/{id}

Send at least one of name, criteria. A rename changes the header only. Changing criteria appends version n+1 and leaves version n exactly as it was: a list materialised from it may have used it. criteria REPLACES the current ones, it is not merged. An edit that changes nothing writes no version. base_version is optional and, when sent, must be the current version, otherwise 409 and nothing is written, so two people editing the same filter do not overwrite each other unnoticed. An archived filter cannot be edited (409); a filter holds at most 1 000 versions (422). Needs the tenant scope. With the flag off, 404.

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Request body (JSON, required)

FieldTypeRequiredDescription
namestringno
criteriaobject (SegmentCriteria)noCriteria accepted by the segment-filter writes and to-list routes (Dialer.Debts.Segment, ADR #221). A closed vocabulary, combined with AND; an empty object is the whole portfolio. state, debt_type, us_state and regf_status take one value or a list (they are always returned as a sorted list without repeats). phone, consumer_ref, external_ref and debtor_name are refused by name.
criteria.campaign_idstring (uuid)no
criteria.stateopen · in_collection · promise_to_pay · paid · settled · disputed · closed | array of open · in_collection · promise_to_pay · paid · settled · disputed · closedno
criteria.debt_typeother · student_loan | array of other · student_loanno
criteria.us_statestring | array of stringno
criteria.regf_statusok · blocked_7in7 · blocked_post_contact · undecidable | array of ok · blocked_7in7 · blocked_post_contact · undecidablenoADR #221 criterion: current Reg F eligibility derived by the server.
criteria.min_amount_centsintegerno
criteria.max_amount_centsintegerno
criteria.min_age_daysintegernoADR #221 criterion: delinquent for at least this many days (debts.delinquent_since against today); a debt with no delinquent_since never matches.
criteria.max_age_daysintegernoADR #221 criterion: delinquent for at most this many days (debts.delinquent_since against today); a debt with no delinquent_since never matches. A min_age_days above max_age_days is refused.
base_versionintegerno
json
{
  "base_version": 1,
  "criteria": {
    "us_state": [
      "TX",
      "NY"
    ]
  }
}

Responses

200 ​

The filter, at its current version after the edit.

FieldTypeRequiredDescription
segment_filterobject (SegmentFilter)yesA saved filter: its header and its CURRENT version.
segment_filter.idstring (uuid)yes
segment_filter.tenant_idstring (uuid)no
segment_filter.namestringyes
segment_filter.archivedbooleanyes
segment_filter.versionintegeryesThe current version.
segment_filter.criteriaanyyesThe criteria of the current version, in canonical form (lists sorted, without repeats).
segment_filter.version_created_atstring (date-time)no
segment_filter.created_atstring (date-time)no
segment_filter.updated_atstring (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"
  }
}

409 — Conflict ​

Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.

json
{
  "error": {
    "code": "conflict",
    "message": "invalid state transition"
  }
}

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)"
  }
}

Archive a saved filter ​

http
DELETE /v1/segment-filters/{id}

Filters are never deleted: a version a list was materialised from is evidence. Archiving frees the name for a new filter and takes the filter out of the default list; it can no longer be edited. Idempotent. Needs the tenant scope. With the flag off, 404.

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Responses

204 ​

The filter is archived.

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"
  }
}

Freeze what a saved filter selects NOW into a list ​

http
POST /v1/segment-filters/{id}/to-list

A PHOTO (ADR #221, core#1687): the debts the filter's LATEST version selects at this moment are put in the list, and the list does not follow the filter afterwards. Only the tenant's debts enter; the Reg F criteria use the real Reg F logic. Idempotent by (list_id, debt_id): repeating the request adds nothing (added: 0) and still records its own evidence row.

The target is EXACTLY ONE of list_id (an existing list of the tenant: 200) or new_list_name (a list created in the same request, unique name: 201); none or both is a 400.

The tenant's catalog cap debt_segment_max_rows (default 10 000, never above the Reg F candidate ceiling) bounds how many debts are written; reaching it is truncated: true in the answer, never silent, and the photo then covers only the most recent candidates. A cap of 0 or less is 422 and writes nothing. An archived filter, or an archived list_id list, is 409. A list_id or filter that is not the tenant's, or not a UUID, is 404. A request that fails leaves no empty list behind. Needs the tenant scope (403 for an agent token). Behind the debt_segmentation_enabled flag: off, 404 and nothing is read or written.

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Request body (JSON, required)

FieldTypeRequiredDescription
list_idstring (uuid)no
new_list_namestringno
json
{
  "new_list_name": "Texas student loans",
  "July photo": null
}

Responses

200 ​

The photo was written into the existing list.

FieldTypeRequiredDescription
segment_materializationobject (SegmentMaterialization)yesThe evidence row of one photo (append-only). matched debts were selected (at most max_rows), added of them were NEW in the list and truncated says the catalog cap cut the result.
segment_materialization.idstring (uuid)yes
segment_materialization.tenant_idstring (uuid)no
segment_materialization.list_idstring (uuid)yes
segment_materialization.filter_idstring (uuid) | nullyesThe saved filter, or null when the criteria came inline.
segment_materialization.filter_versioninteger | nullyesThe version of the filter that was used, or null when inline.
segment_materialization.criteriaanyyesThe criteria that were evaluated, in canonical form.
segment_materialization.max_rowsintegeryesThe cap in force for this photo.
segment_materialization.matchedintegeryes
segment_materialization.addedintegeryes
segment_materialization.truncatedbooleanyes
segment_materialization.requested_atstring (date-time)no
debt_listanyyesThe target list, its size counted after the photo.

201 ​

The list was created and the photo written into it.

FieldTypeRequiredDescription
segment_materializationobject (SegmentMaterialization)yesThe evidence row of one photo (append-only). matched debts were selected (at most max_rows), added of them were NEW in the list and truncated says the catalog cap cut the result.
segment_materialization.idstring (uuid)yes
segment_materialization.tenant_idstring (uuid)no
segment_materialization.list_idstring (uuid)yes
segment_materialization.filter_idstring (uuid) | nullyesThe saved filter, or null when the criteria came inline.
segment_materialization.filter_versioninteger | nullyesThe version of the filter that was used, or null when inline.
segment_materialization.criteriaanyyesThe criteria that were evaluated, in canonical form.
segment_materialization.max_rowsintegeryesThe cap in force for this photo.
segment_materialization.matchedintegeryes
segment_materialization.addedintegeryes
segment_materialization.truncatedbooleanyes
segment_materialization.requested_atstring (date-time)no
debt_listanyyesThe target list, its size counted after the photo.

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"
  }
}

409 — Conflict ​

Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.

json
{
  "error": {
    "code": "conflict",
    "message": "invalid state transition"
  }
}

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)"
  }
}

Freeze what inline criteria select NOW into a list ​

http
POST /v1/segment-filters/to-list

The same photo as POST /v1/segment-filters/{id}/to-list, with the criteria in the body instead of a saved filter (the evidence row then has no filter_id). criteria goes through Dialer.Debts.Segment: a value outside the closed vocabulary, a PII key or a non-object is a 400, and nothing is written. An empty object is the whole portfolio, still bounded by the cap. Target, cap, scope and flag as in the saved-filter form.

Request body (JSON, required)

FieldTypeRequiredDescription
criteriaobject (SegmentCriteria)yesCriteria accepted by the segment-filter writes and to-list routes (Dialer.Debts.Segment, ADR #221). A closed vocabulary, combined with AND; an empty object is the whole portfolio. state, debt_type, us_state and regf_status take one value or a list (they are always returned as a sorted list without repeats). phone, consumer_ref, external_ref and debtor_name are refused by name.
criteria.campaign_idstring (uuid)no
criteria.stateopen · in_collection · promise_to_pay · paid · settled · disputed · closed | array of open · in_collection · promise_to_pay · paid · settled · disputed · closedno
criteria.debt_typeother · student_loan | array of other · student_loanno
criteria.us_statestring | array of stringno
criteria.regf_statusok · blocked_7in7 · blocked_post_contact · undecidable | array of ok · blocked_7in7 · blocked_post_contact · undecidablenoADR #221 criterion: current Reg F eligibility derived by the server.
criteria.min_amount_centsintegerno
criteria.max_amount_centsintegerno
criteria.min_age_daysintegernoADR #221 criterion: delinquent for at least this many days (debts.delinquent_since against today); a debt with no delinquent_since never matches.
criteria.max_age_daysintegernoADR #221 criterion: delinquent for at most this many days (debts.delinquent_since against today); a debt with no delinquent_since never matches. A min_age_days above max_age_days is refused.
list_idstring (uuid)no
new_list_namestringno
json
{
  "criteria": {
    "debt_type": [
      "student_loan"
    ],
    "us_state": [
      "TX"
    ]
  },
  "list_id": "6f1c2a52-3b52-4b3d-9d57-0e5c6a8f1a10"
}

Responses

200 ​

The photo was written into the existing list.

FieldTypeRequiredDescription
segment_materializationobject (SegmentMaterialization)yesThe evidence row of one photo (append-only). matched debts were selected (at most max_rows), added of them were NEW in the list and truncated says the catalog cap cut the result.
segment_materialization.idstring (uuid)yes
segment_materialization.tenant_idstring (uuid)no
segment_materialization.list_idstring (uuid)yes
segment_materialization.filter_idstring (uuid) | nullyesThe saved filter, or null when the criteria came inline.
segment_materialization.filter_versioninteger | nullyesThe version of the filter that was used, or null when inline.
segment_materialization.criteriaanyyesThe criteria that were evaluated, in canonical form.
segment_materialization.max_rowsintegeryesThe cap in force for this photo.
segment_materialization.matchedintegeryes
segment_materialization.addedintegeryes
segment_materialization.truncatedbooleanyes
segment_materialization.requested_atstring (date-time)no
debt_listanyyesThe target list, its size counted after the photo.

201 ​

The list was created and the photo written into it.

FieldTypeRequiredDescription
segment_materializationobject (SegmentMaterialization)yesThe evidence row of one photo (append-only). matched debts were selected (at most max_rows), added of them were NEW in the list and truncated says the catalog cap cut the result.
segment_materialization.idstring (uuid)yes
segment_materialization.tenant_idstring (uuid)no
segment_materialization.list_idstring (uuid)yes
segment_materialization.filter_idstring (uuid) | nullyesThe saved filter, or null when the criteria came inline.
segment_materialization.filter_versioninteger | nullyesThe version of the filter that was used, or null when inline.
segment_materialization.criteriaanyyesThe criteria that were evaluated, in canonical form.
segment_materialization.max_rowsintegeryesThe cap in force for this photo.
segment_materialization.matchedintegeryes
segment_materialization.addedintegeryes
segment_materialization.truncatedbooleanyes
segment_materialization.requested_atstring (date-time)no
debt_listanyyesThe target list, its size counted after the photo.

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"
  }
}

409 — Conflict ​

Invalid state transition, uniqueness conflict, or a seat that is busy/reserved.

json
{
  "error": {
    "code": "conflict",
    "message": "invalid state transition"
  }
}

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)"
  }
}

Nothing in these docs is legal advice — always confirm compliance posture with your own counsel.