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_idrequired; 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.