Skip to content

Exception resolve — external contract

Partner / integrator-facing contract for exception resolution on the reconciliation exception service.

Scope

This page is the external contract only. Detailed engineering design (SQL, concurrency, table layouts) lives on the internal documentation site and is not published here.

Transport

Path Role
Pub/Sub pull (subscription configured per environment) Primary production trigger where the service is deployed with the resolution-request pull loop enabled
POST /v1/exceptions/resolve Manual / local / fallback HTTP path — still implemented; suitable for testing and operators when messaging is unavailable

resolution_request_id is mandatory on the Pub/Sub path (missing id is rejected rather than inventing a UUID). On HTTP it is optional at the model level; the route may mint a fallback UUID — prefer sending your own stable id for safe retries.

Purpose

Apply an operator decision to exception clusters in scope (partner_id + tenant_id + domain derived from customer_type/service + cluster_type), optionally narrowed by cluster_ids.

Decisions

decision Meaning (external)
approved Status decision on existing data
rejected Reject in scope
escalated Escalate in scope
reopened Reopen previously resolved rows (selects non-pending band)
reconcile Take new information (e.g. file URLs) and perform ingest + re-match for not_found_* paths

Request shape (summary)

Required (typical): partner_id, tenant_id, decision, customer_type, cluster_type.

service is required when customer_type is commercial. It may be sent top-level or backfilled from template.service when the top-level field is omitted.

Common optional fields:

Field Role
resolution_request_id Idempotency key — required on Pub/Sub; optional on HTTP (prefer caller-supplied)
template Optional loose reconciliation template object; used at least as a fallback source for service
is_recurring Boolean (default false). When true and decision is approved, marks the resolution as a recurring pattern for intelligence learning on supported cluster_types; ignored otherwise
cluster_ids Narrow bulk scope; not supported with decision=reconcile + not_found_gl/not_found_bank (422)
note, metadata Free-form operator context
gl_file_url, bank_file_url New source documents for reconcile / not_found flows
mappings, others Optional column mapping (consumed on banking ingest path)
branch_id Optional explicit branch for not_found reconcile
matching_method, tolerances / search windows Banking matcher overrides

Prefer live OpenAPI on the exception service for full schemas.

State transitions (external)

Clusters carry a decision_status band. Resolve selects pending rows for most decisions, and the opposite band for reopened. Exact status vocabulary and audit fields are environment/internal documentation.

Idempotency

  • Pub/Sub path: resolution_request_id required; claim/inspect bookkeeping in the exception service.
  • HTTP path: may mint a fallback id — prefer sending your own stable id for safe retries.

Observable errors (typical)

Condition Likely signal
Invalid enum / failed validators HTTP 422
Unsupported domain / unwired vertical Service error
Targeted cluster_ids + reconcile not_found 422 with explicit message
Missing resolution_request_id on Pub/Sub Message rejected / not processed as a resolve

Inventory snapshot: Reconciliation OpenAPI.

Cluster types (union across verticals)

Includes (non-exhaustive of future rules): amount_mismatch, date_difference, possible_bank_fee, fuzzy_narration_match, split_transaction, debit_standalone, extraction_issue, possible_duplicate, needs_review, not_found_gl, not_found_bank, missing_identifier, incomplete_identifier.