Statement Object

A Statement represents an uploaded bank statement file that has been processed to extract transactions.

Object Structure

{
  "id": "stmt123xyz",
  "file_name": "HDFC_Statement_Jan_2025.pdf",
  "mime_type": "application/pdf",
  "file_type": "pdf",
  "file_size": "245760",
  "parser_type": "hdfc_savings__pdf",
  "step": "complete",
  "error": null,
  "account_id": "acc123xyz",
  "account_name": "HDFC Savings",
  "account_currency": "INR",
  "is_archived": false,
  "created_at": "2025-01-05T10:30:00.000Z",
  "period_start": "2025-01-01",
  "period_end": "2025-01-31",
  "opening_balance": 5000050,
  "closing_balance": 4825075,
  "data_source": {
    "period_start": "extracted",
    "period_end": "extracted",
    "opening_balance": "computed",
    "closing_balance": "computed"
  },
  "review": {
    "is_done": true,
    "at": "2025-01-06T14:30:00.000Z",
    "type": "human",
    "by": "user123",
    "work_record_id": "wr456"
  }
}

Fields

Core Fields

FieldTypeDescription
idstring12-character unique identifier
file_namestringOriginal uploaded file name
created_atstringISO 8601 timestamp of upload

File Information

FieldTypeDescription
mime_typestringMIME type of the uploaded file
file_typestringSimplified file type (csv, pdf, xlsx)
file_sizestringFile size in bytes

Processing Fields

FieldTypeDescription
parser_typestringParser used to extract transactions
stepstringCurrent processing step
errorstringError message if processing failed

Relationship Fields

FieldTypeDescription
account_idstringID of the matched account
account_namestringName of the matched account
account_currencystringCurrency code of the matched account, e.g. INR, USD (read-only, derived from the account; defaults to INR)

Status Fields

FieldTypeDescription
is_archivedbooleanWhether statement is archived

Review Fields

FieldTypeDescription
reviewobjectReview status (null if never reviewed)
review.is_donebooleanWhether review is complete
review.atstringISO 8601 timestamp of review
review.typestringReviewer type: ai or human
review.bystringUser ID if human reviewer, null if AI
review.work_record_idstringWorkRecord documenting the review

Period Fields

FieldTypeDescription
period_startstringStatement period start date (YYYY-MM-DD)
period_endstringStatement period end date (YYYY-MM-DD)

These fields represent the date range covered by the bank statement. They can be:

  • Extracted directly from the statement document
  • Computed from the first/last transaction dates
  • Entered manually by the user

Balance Fields

FieldTypeDescription
opening_balanceintegerOpening balance at period start (smallest currency unit)
closing_balanceintegerClosing balance at period end (smallest currency unit)

Balance values are returned as integers in the smallest currency unit (e.g., paise for INR, cents for USD). This is consistent with transaction inflow, outflow, and balance fields.

Data Source Tracking

FieldTypeDescription
data_sourceobjectTracks how each field value was determined

The data_source object contains source information for period and balance fields:

Source ValueDescription
extractedParsed directly from statement document (high reliability)
computedDerived from transaction data (medium reliability)
user_enteredManually entered by user
user_updatedOriginally extracted/computed, then modified by user
unknownSource not determined

File Types

TypeMIME TypesDescription
csvtext/csvComma-separated values
pdfapplication/pdfPDF bank statements
xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetExcel files
xlsapplication/vnd.ms-excelLegacy Excel files

Processing Steps

Statements progress through these steps during processing:

StepDescription
uploadedFile uploaded, processing queued
read_fileFile content extracted to raw data
identify_statementBank/parser type detected
parse_statementTransactions extracted from file
detect_accountAccount matched or created
create_transactionsDuplicates filtered out, non-duplicate transactions saved
completeProcessing finished successfully

Processing Flow

uploaded -> read_file -> identify_statement -> parse_statement
                                                    |
                                                    v
              complete <- create_transactions <- detect_account

create_transactions is a single job that both filters duplicates (against existing transactions in the same account and period) and inserts the survivors. Statements for the same account serialize their processing here — a pg-boss singleton policy keyed on account_id prevents two concurrent uploads from racing the duplicate check and double-inserting.

Error States

If processing fails at any step:

  • step remains at the failed step
  • error contains the error message

Common errors:

  • "Unable to detect parser" - No matching parser for file format
  • "No transactions found" - Parser ran but found no transactions
  • "Password required" - PDF is password-protected

Parser Types

Parser types follow the naming convention: {bank}_{account_type}__{format}

Examples:

Parser TypeDescription
hdfc_savings__pdfHDFC Bank savings account PDF
hdfc_savings__csvHDFC Bank savings account CSV
icici_cc__csvICICI Credit Card CSV
sbi_savings__xlsxSBI savings account Excel
axis_cc__pdfAxis Credit Card PDF

The parser type is detected automatically based on file content and structure.


Detail-Only Fields

These fields are only returned when fetching a single statement via GET /api/v1/statements/:id:

FieldTypeDescription
orgstringOrganization ID
checksobjectValidation check results (balance verification, date sequence, etc.)
parsed_dataobjectExtracted transactions and metadata
raw_dataobjectRaw file content for reprocessing

See Get Statement for detailed structure of these fields.

Internal Fields (Not Exposed)

These fields exist in the database but are never exposed via API:

FieldDescription
extracted_dataLegacy field (deprecated)
locationFile storage location
passwordPDF password (if provided)

Field Selection

When retrieving statements, use the fields parameter:

GET /api/v1/statements?fields=id,file_name,step,account_name

Available fields: id, file_name, mime_type, file_type, file_size, parser_type, step, error, account_id, account_name, account_currency, is_archived, review, created_at, period_start, period_end, opening_balance, closing_balance, data_source

Detail-only fields (single statement): org, checks, parsed_data, raw_data


Example: Completed Statement

{
  "id": "stmt001done",
  "file_name": "ICICI_CC_Dec_2024.csv",
  "mime_type": "text/csv",
  "file_type": "csv",
  "file_size": "15360",
  "parser_type": "icici_cc__csv",
  "step": "complete",
  "error": null,
  "account_id": "acc002card",
  "account_name": "ICICI Credit Card",
  "account_currency": "INR",
  "is_archived": false,
  "created_at": "2025-01-02T14:22:00.000Z",
  "period_start": "2024-12-01",
  "period_end": "2024-12-31",
  "opening_balance": 2500000,
  "closing_balance": 3250050,
  "data_source": {
    "period_start": "computed",
    "period_end": "computed",
    "opening_balance": "extracted",
    "closing_balance": "extracted"
  }
}

Example: Failed Statement

{
  "id": "stmt002fail",
  "file_name": "unknown_bank_statement.pdf",
  "mime_type": "application/pdf",
  "file_type": "pdf",
  "file_size": "512000",
  "parser_type": null,
  "step": "identify_statement",
  "error": "Unable to detect parser for this file format",
  "account_id": null,
  "account_name": null,
  "account_currency": "INR",
  "is_archived": false,
  "created_at": "2025-01-03T09:15:00.000Z",
  "period_start": null,
  "period_end": null,
  "opening_balance": null,
  "closing_balance": null,
  "data_source": {}
}

Example: Processing Statement

{
  "id": "stmt003proc",
  "file_name": "HDFC_Jan_2025.xlsx",
  "mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "file_type": "xlsx",
  "file_size": "98304",
  "parser_type": "hdfc_savings__xlsx",
  "step": "create_transactions",
  "error": null,
  "account_id": "acc001bank",
  "account_name": "HDFC Savings",
  "account_currency": "INR",
  "is_archived": false,
  "created_at": "2025-01-05T11:00:00.000Z",
  "period_start": "2025-01-01",
  "period_end": "2025-01-31",
  "opening_balance": 10000000,
  "closing_balance": 9500025,
  "data_source": {
    "period_start": "computed",
    "period_end": "computed",
    "opening_balance": "computed",
    "closing_balance": "computed"
  }
}