{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/arkrel-com/json-schema/arkrel-com-categorized-transaction-schema.json",
  "title": "CategorizedTransaction",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/arkrel-com-openapi.yaml#/components/schemas/CategorizedTransaction",
  "type": "object",
  "required": [
    "transaction",
    "reconciled",
    "sourcePage",
    "ruleSource",
    "reason"
  ],
  "properties": {
    "transaction": {
      "type": "object",
      "required": [
        "documentId",
        "rowIndex",
        "date",
        "description",
        "amount"
      ],
      "properties": {
        "documentId": {
          "type": "string"
        },
        "rowIndex": {
          "type": "integer"
        },
        "date": {
          "type": "string",
          "description": "YYYY-MM-DD, or an empty string when the date is unknown."
        },
        "description": {
          "type": "string"
        },
        "amount": {
          "type": "number",
          "description": "Signed, a positive amount is money in, negative is money out. Never altered by categorization."
        }
      }
    },
    "category": {
      "type": [
        "object",
        "null"
      ],
      "allOf": [
        {
          "$ref": "#/$defs/TransactionCategory"
        }
      ]
    },
    "account": {
      "type": [
        "object",
        "null"
      ],
      "allOf": [
        {
          "$ref": "#/$defs/Account"
        }
      ]
    },
    "reconciled": {
      "type": "boolean",
      "description": "\"Reconciled to your statement\": the source document's own extraction/balance checks all passed. A SEPARATE fact from category confidence, never merged into one badge."
    },
    "sourcePage": {
      "type": [
        "integer",
        "null"
      ],
      "description": "A real page number when the extraction has one (a receipt/invoice's own total field); null for a bank-statement transaction table row, which has no per-row page in this product's extraction schema."
    },
    "ruleSource": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "standard",
        "user"
      ],
      "description": "Only set when `category.source` is \"rule\". \"standard\" for one of the built-in rules every org starts with, \"user\" for a rule the user created themselves from their own correction. A rule match is a deterministic pattern hit, never shown as a confidence percentage in the UI. Its source is shown instead."
    },
    "reason": {
      "type": [
        "string",
        "null"
      ],
      "description": "One short, plain-English line explaining WHY this row needs your input, null for anything already decided (a transfer, or a plain rule match). E.g. \"This looks like a large purchase or piece of equipment...\" or \"Our best guess, but not confident enough to apply automatically...\"."
    }
  },
  "$defs": {
    "Account": {
      "type": "object",
      "required": [
        "id",
        "name",
        "type",
        "source",
        "is_active",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "client_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "code": {
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "type": "string"
        },
        "type": {
          "$ref": "#/$defs/AccountType"
        },
        "subtype": {
          "type": [
            "string",
            "null"
          ]
        },
        "tax_line": {
          "type": [
            "string",
            "null"
          ],
          "description": "The IRS Schedule C (Form 1040) line this account maps to, e.g. \"Line 18 Office expense\". Null for every personal account."
        },
        "source": {
          "type": "string",
          "enum": [
            "standard",
            "custom",
            "imported_csv",
            "quickbooks",
            "xero"
          ]
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_active": {
          "type": "boolean"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "AccountType": {
      "type": "string",
      "enum": [
        "asset",
        "liability",
        "equity",
        "income",
        "expense",
        "personal"
      ],
      "description": "personal is this product's own addition, a personal-spending account, never a business classification, never deductible."
    },
    "CategorizationStatus": {
      "type": "string",
      "enum": [
        "needs_review",
        "categorized",
        "accepted"
      ]
    },
    "TransactionCategory": {
      "type": "object",
      "required": [
        "id",
        "document_id",
        "row_index",
        "status",
        "source",
        "is_transfer",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "client_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "document_id": {
          "type": "string"
        },
        "row_index": {
          "type": "integer"
        },
        "account_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "status": {
          "$ref": "#/$defs/CategorizationStatus"
        },
        "confidence": {
          "type": [
            "number",
            "null"
          ]
        },
        "source": {
          "type": "string",
          "enum": [
            "rule",
            "llm",
            "manual"
          ]
        },
        "rule_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_transfer": {
          "type": "boolean"
        },
        "transfer_account_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "matched_transaction_document_id": {
          "type": [
            "string",
            "null"
          ],
          "description": "Set only on a receipt/invoice row, the bank transaction it was matched to."
        },
        "matched_transaction_row_index": {
          "type": [
            "integer",
            "null"
          ]
        },
        "match_confidence": {
          "type": [
            "number",
            "null"
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  }
}