Skip to content

Debt segmentation: saved filters and list snapshots ​

Español: Segmentación de deuda.

Saved segmentation filters give a tenant a named, reusable set of debt criteria. They are useful when an integration needs to repeat the same portfolio selection without sending the criteria again or putting person-identifying search values in a saved object.

This guide separates the API that is in the latest published core release from the list-snapshot operations that are currently present only in core@main.

Contract used by this guide

The available API below comes from the OpenAPI document in core v0.94.0, the latest published release when this page was written. The list-snapshot section is marked separately because those operations are not in that release.

Before you start ​

All requests use the normal bearer authentication described in Authentication. The feature is tenant-scoped and is behind debt_segmentation_enabled, which is off by default.

When the flag is off, every /v1/segment-filters route returns 404 not_found, regardless of the caller. This is intentional: the disabled surface behaves as if it does not exist and does not read or write saved filters.

Reads are available to an authenticated caller in the tenant. Creating, editing, archiving, and materializing require tenant scope; an agent token receives 403 forbidden. An id that is malformed, missing, or belongs to another tenant returns the same 404 not_found, so the API does not disclose whether another tenant owns it.

Criteria ​

criteria is an object with a closed vocabulary. The fields are combined with AND; array values within one field act as alternatives. An empty object selects the whole portfolio.

FieldShapeRules
campaign_idUUID stringRestricts the selection to one campaign.
statestring or arrayopen, in_collection, promise_to_pay, paid, settled, disputed, or closed. Arrays contain 1–100 values.
debt_typestring or arrayother or student_loan. Arrays contain 1–100 values.
us_statestring or arrayTwo uppercase letters. Arrays contain 1–100 values.
min_amount_centsintegerInclusive lower bound; zero or greater.
max_amount_centsintegerInclusive upper bound; zero or greater.

Unknown fields and values outside the allowed shape return 400 bad_request. The keys phone, consumer_ref, external_ref, and debtor_name are explicitly refused. A saved segment describes a group by attributes; it is not a stored person lookup.

The server stores criteria in canonical form: array values are sorted and duplicates are removed.

Create a saved filter ​

POST /v1/segment-filters accepts name and criteria:

bash
curl -X POST "$DIALER_BASE_URL/v1/segment-filters" \
  -H "Authorization: Bearer $DIALER_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Texas student loans over 500 USD",
    "criteria": {
      "debt_type": ["student_loan"],
      "us_state": ["TX"],
      "min_amount_cents": 50000
    }
  }'

A successful response is 201 with a segment_filter object. A newly created filter starts at version 1.

name is trimmed, cannot be blank, and has a maximum length of 200 characters. It must be unique among the tenant's non-archived filters. The tenant can hold up to 500 non-archived filters.

Read filters ​

Use GET /v1/segment-filters to list non-archived filters by name. Add ?include_archived=true to include archived filters. Each result contains its current version, and the response is capped at 2,000 filters.

Use GET /v1/segment-filters/{id} for one filter. This route can return an archived filter, with archived: true.

A segment_filter contains:

FieldMeaning
idFilter UUID.
tenant_idOwning tenant UUID.
nameSaved name.
archivedWhether the filter has been archived.
versionCurrent version number.
criteriaCurrent criteria in canonical form.
version_created_atCreation time of the current version.
created_atFilter creation time.
updated_atLast header or version change.

Update without overwriting another editor ​

PATCH /v1/segment-filters/{id} accepts at least one of name or criteria. When changing criteria, send the version you read as base_version:

bash
curl -X PATCH "$DIALER_BASE_URL/v1/segment-filters/$FILTER_ID" \
  -H "Authorization: Bearer $DIALER_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "base_version": 1,
    "criteria": {"us_state": ["NY", "TX"]}
  }'

criteria replaces the current object; it is not merged with it. Changing criteria appends the next version and preserves earlier versions. Renaming changes only the filter header. An edit that changes nothing does not append a version.

If base_version is not current, the server returns 409 conflict and writes nothing. An archived filter also returns 409 conflict. A filter can hold up to 1,000 versions; reaching that limit returns 422 unprocessable.

Archive a filter ​

DELETE /v1/segment-filters/{id} returns 204 and archives the filter. It does not physically delete its versions. Archiving is idempotent, removes the filter from the default list, prevents later edits, and makes its former name available for a new filter.

Error handling ​

Errors use the standard envelope:

json
{
  "error": {
    "code": "bad_request",
    "message": "..."
  }
}

Branch on error.code, not on the human-readable message.

Status and codeWhen to expect it
400 bad_requestInvalid body, unknown criterion, refused person lookup, or a value outside the criterion vocabulary.
401 unauthorizedMissing, unknown, or revoked credential.
403 forbiddenA write without tenant scope, or a suspended tenant.
404 not_foundFeature flag off; unknown or malformed id; or an id hidden by tenant isolation.
409 conflictDuplicate live name, stale base_version, or an attempt to edit an archived filter.
422 unprocessableThe live-filter or per-filter version limit has been reached.

These failures are fail-closed: invalid criteria do not become an empty filter, a broader query, or a partial write.

Materialize a segment into a debt list ​

Available in the next version

The operations in this section are present in the OpenAPI document on core@main (0.95.0) but are absent from the latest published release, v0.94.0. Do not call them against the published release yet.

Materialization creates a snapshot: it adds the debts that match now to a normal debt list. The list does not follow later changes to the filter or portfolio. Membership in the list does not bypass dialing compliance checks.

Two operations are planned by the current core@main contract:

MethodPathSource
POST/v1/segment-filters/{id}/to-listLatest version of a saved filter.
POST/v1/segment-filters/to-listInline criteria in the request body.

Choose exactly one target:

  • list_id: add matches to an existing tenant list; success returns 200.
  • new_list_name: create a list and add matches in the same request; success returns 201.

For the inline operation, also send criteria. Sending neither target or both targets returns 400 bad_request.

The response contains segment_materialization and debt_list. segment_materialization includes id, tenant_id, list_id, filter_id, filter_version, criteria, max_rows, matched, added, truncated, and requested_at. Inline criteria produce null for filter_id and filter_version.

The operation is idempotent for an existing (list_id, debt_id) membership: repeating it adds no duplicate member, while recording a separate evidence row. The tenant catalog cap limits the number written. When the cap cuts the result, the response reports truncated: true; it does not silently claim that the snapshot contains every match. A non-positive cap returns 422 unprocessable and writes nothing. A failing request does not leave an empty newly-created list.

The snapshot endpoints use the same 400, 401, 403, 404, 409, and 422 codes described above. In addition, an archived saved filter returns 409 conflict.

Operational checklist ​

  1. Confirm that debt_segmentation_enabled is enabled for the tenant.
  2. Create the filter and retain its id and version.
  3. Use base_version on edits to avoid unnoticed overwrites.
  4. Treat 404 as intentionally ambiguous; do not use it to infer another tenant's data or whether the feature is enabled.
  5. Once the snapshot operations appear in a published release, inspect truncated before treating a materialized list as the intended selection.

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