{
  "openapi": "3.1.0",
  "info": {
    "title": "MasteryHive Reconciliation \u2014 Exceptions (Partner entry)",
    "version": "0.1.0",
    "description": "Detect + resolve partner entry points. root_path /v1. Local servers only."
  },
  "servers": [
    {
      "url": "http://localhost:8000/v1",
      "description": "Local mesh placeholder \u2014 replace host; keep /v1 prefix. Cloud bases require owner decision."
    }
  ],
  "paths": {
    "/": {
      "get": {
        "summary": "Home",
        "operationId": "home__get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Health",
        "operationId": "health_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/exceptions/resolve": {
      "post": {
        "tags": [
          "Exceptions"
        ],
        "summary": "Resolve Exceptions",
        "operationId": "resolve_exceptions_exceptions_resolve_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolveResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/exceptions/banking/detect": {
      "post": {
        "tags": [
          "Exceptions"
        ],
        "summary": "Detect Banking Exceptions",
        "operationId": "detect_banking_exceptions_exceptions_banking_detect_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BankingDetectRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DetectResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/exceptions/commercial/detect": {
      "post": {
        "tags": [
          "Exceptions"
        ],
        "summary": "Detect Commercial Exceptions",
        "operationId": "detect_commercial_exceptions_exceptions_commercial_detect_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommercialDetectRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DetectResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BankingDetectRequest": {
        "properties": {
          "session_id": {
            "type": "string",
            "title": "Session Id"
          },
          "partner_id": {
            "type": "string",
            "title": "Partner Id"
          },
          "tenant_id": {
            "type": "string",
            "title": "Tenant Id"
          },
          "branch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Id"
          },
          "dataset_id": {
            "type": "string",
            "title": "Dataset Id"
          },
          "exception_analysis_enabled": {
            "type": "boolean",
            "title": "Exception Analysis Enabled",
            "default": true
          },
          "matching_method": {
            "type": "string",
            "title": "Matching Method",
            "default": "line_by_line"
          },
          "exclude_debits_from_rate": {
            "type": "boolean",
            "title": "Exclude Debits From Rate",
            "default": true
          },
          "gl_gcs_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gl Gcs Url"
          },
          "bank_gcs_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bank Gcs Url"
          }
        },
        "type": "object",
        "required": [
          "session_id",
          "partner_id",
          "tenant_id",
          "dataset_id"
        ],
        "title": "BankingDetectRequest"
      },
      "ClusterResolutionResult": {
        "properties": {
          "cluster_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cluster Id"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id"
          },
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "new_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "New Status"
          },
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message"
          },
          "auto_resolved": {
            "type": "boolean",
            "title": "Auto Resolved",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "success"
        ],
        "title": "ClusterResolutionResult"
      },
      "ClusterType": {
        "type": "string",
        "enum": [
          "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"
        ],
        "title": "ClusterType",
        "description": "Every cluster_type any rule engine (banking or commercial) actually\nproduces today \u2014 grepped directly from banking/rules/*.py and\ncommercial/rules/*.py's CLUSTER_TYPE/CLUSTER_TYPE_BY_SIDE constants, not\nhand-guessed. Deliberately the UNION across both verticals rather than a\nper-domain subset: this only guards against typos/garbage, not against\nrequesting a type that happens to belong to the other domain (the\n(domain, cluster_type) OUTCOME_HANDLERS/table lookups already handle that\ncorrectly on their own \u2014 see service.py)."
      },
      "ColumnMapping": {
        "properties": {
          "system": {
            "type": "string",
            "title": "System"
          },
          "gl_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gl Title"
          },
          "statement_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Statement Title"
          },
          "secondary_mappings": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/SecondaryMapping"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Secondary Mappings"
          }
        },
        "type": "object",
        "required": [
          "system"
        ],
        "title": "ColumnMapping"
      },
      "CommercialDetectRequest": {
        "properties": {
          "session_id": {
            "type": "string",
            "title": "Session Id"
          },
          "partner_id": {
            "type": "string",
            "title": "Partner Id"
          },
          "tenant_id": {
            "type": "string",
            "title": "Tenant Id"
          },
          "branch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Id"
          },
          "dataset_id": {
            "type": "string",
            "title": "Dataset Id"
          },
          "domain": {
            "type": "string",
            "title": "Domain",
            "default": "nip"
          },
          "exception_analysis_enabled": {
            "type": "boolean",
            "title": "Exception Analysis Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "session_id",
          "partner_id",
          "tenant_id",
          "dataset_id"
        ],
        "title": "CommercialDetectRequest"
      },
      "DecisionType": {
        "type": "string",
        "enum": [
          "approved",
          "rejected",
          "escalated",
          "reopened",
          "reconcile"
        ],
        "title": "DecisionType",
        "description": "\"reconcile\" is distinct from \"approved\": anything that requires\ntaking NEW information (a freshly supplied gl_file_url/bank_file_url)\nand PERFORMING AN ACTION (ingest + re-match) is \"reconcile\" \u2014\nnot_found_gl/not_found_bank's own pipeline (outcomes/not_found/\nhandler.py). \"approved\" remains a plain status decision on existing\ndata \u2014 for not_found that's now a simple bulk status-flip override, no\nre-matching (see _bulk_status_flip)."
      },
      "DetectResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          }
        },
        "type": "object",
        "required": [
          "success"
        ],
        "title": "DetectResponse"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "MatchingMethod": {
        "type": "string",
        "enum": [
          "line_by_line",
          "bulk",
          "lump_sum",
          "line_by_line_and_lump_sum"
        ],
        "title": "MatchingMethod",
        "description": "Matching methods for reconciliation"
      },
      "OthersMapping": {
        "properties": {
          "gl": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gl"
          },
          "statement": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Statement"
          }
        },
        "type": "object",
        "title": "OthersMapping"
      },
      "ReconciliationCustomerTypeEnum": {
        "type": "string",
        "enum": [
          "mfb",
          "commercial_bank",
          "payment_provider",
          "lender",
          "fund_management"
        ],
        "title": "ReconciliationCustomerTypeEnum"
      },
      "ResolveRequest": {
        "properties": {
          "resolution_request_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resolution Request Id"
          },
          "partner_id": {
            "type": "string",
            "title": "Partner Id"
          },
          "tenant_id": {
            "type": "string",
            "title": "Tenant Id"
          },
          "decision": {
            "$ref": "#/components/schemas/DecisionType"
          },
          "customer_type": {
            "$ref": "#/components/schemas/ReconciliationCustomerTypeEnum"
          },
          "service": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ServiceType"
              },
              {
                "type": "null"
              }
            ]
          },
          "template": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Template"
          },
          "cluster_type": {
            "$ref": "#/components/schemas/ClusterType"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Note"
          },
          "metadata": {
            "additionalProperties": true,
            "type": "object",
            "title": "Metadata",
            "default": {}
          },
          "is_recurring": {
            "type": "boolean",
            "title": "Is Recurring",
            "default": false
          },
          "gl_file_url": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Gl File Url",
            "default": []
          },
          "bank_file_url": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Bank File Url",
            "default": []
          },
          "mappings": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ColumnMapping"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mappings"
          },
          "others": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OthersMapping"
              },
              {
                "type": "null"
              }
            ]
          },
          "branch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Id"
          },
          "cluster_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cluster Ids"
          },
          "matching_method": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MatchingMethod"
              },
              {
                "type": "null"
              }
            ]
          },
          "amount_tolerance": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Tolerance"
          },
          "recon_time_search_forward": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recon Time Search Forward"
          },
          "recon_time_search_backward": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recon Time Search Backward"
          }
        },
        "type": "object",
        "required": [
          "partner_id",
          "tenant_id",
          "decision",
          "customer_type",
          "cluster_type"
        ],
        "title": "ResolveRequest",
        "description": "A resolve call is a BULK action, not a per-cluster one by default: it\napplies `decision` to every cluster matching this exact\npartner_id/tenant_id/domain/cluster_type scope (and the right\ndecision_status \u2014 pending, or non-pending for `decision=\"reopened\"`).\n`cluster_ids` (optional) narrows that same scope to a specific set of\nclusters \u2014 for single-unit or small-batch resolution where a decision\nwas reached per-cluster (e.g. after some intelligence-gathering step),\nnot \"reject every pending X\". Omitting it preserves the original\nbulk-by-cluster_type behavior exactly. session_id is deliberately absent\ntoo: resolution scope is partner-wide, and not_found's own re-match\nlogic never scopes or requires one."
      },
      "ResolveResponse": {
        "properties": {
          "results": {
            "items": {
              "$ref": "#/components/schemas/ClusterResolutionResult"
            },
            "type": "array",
            "title": "Results"
          }
        },
        "type": "object",
        "required": [
          "results"
        ],
        "title": "ResolveResponse"
      },
      "SecondaryMapping": {
        "properties": {
          "gl_title": {
            "type": "string",
            "title": "Gl Title"
          },
          "statement_title": {
            "type": "string",
            "title": "Statement Title"
          }
        },
        "type": "object",
        "required": [
          "gl_title",
          "statement_title"
        ],
        "title": "SecondaryMapping"
      },
      "ServiceType": {
        "type": "string",
        "enum": [
          "card_settlement",
          "transfers",
          "cash_deposits",
          "pos_deposits",
          "pos",
          "ussd",
          "bill_payments",
          "atm",
          "nip",
          "other"
        ],
        "title": "ServiceType",
        "description": "Service types for reconciliation templates"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    }
  }
}
