Skip to Content
API ReferenceGET /api/comparison

GET /api/comparison

Builds a per-Unit source-vs-canonical comparison by downloading both the original uploaded File and the extracted output, then walking the column mapping to match source cells to canonical fields. Used to power the side-by-side review UI.

Request

Method: GET

Query Parameters:

ParameterTypeRequiredDescription
job_idstringYesUUID of a completed job

Headers: Authorization: Bearer <token>

GET /api/comparison?job_id=abc-123-def Authorization: Bearer <token>

Prerequisites

  • The job must have status = complete
  • The job must have a structure_result
  • Both the original File and the Output File (outputs/{job_id}/output.xlsx) must exist in storage

Processing Steps

  1. Authenticate via checkAuth()
  2. Validate query parameter and fetch the job row
  3. Download original File from Supabase Storage using storage_path
  4. Parse original into CellGrid objects via readExcelBuffer()
  5. Download Output File from outputs/{job_id}/output.xlsx
  6. Parse output and extract rows from the Rent Roll Sheet
  7. Build comparison — for each extracted Unit (up to 200):
    • Locate the source row in the original grid by matching unit_id
    • Collect all non-empty source cells for that row
    • Map each column in column_mapping to its canonical field
    • Classify each field as mapped, transformed, or missing

Unit Cap

The comparison is limited to the first 200 Units. For Files with more than 200 Units, only the first 200 are included in the response. This keeps payload sizes manageable for the review UI.

Diff Classification

Each field where the source and canonical values diverge is classified into one of three types:

TypeDescription
mappedSource and canonical values match exactly (after trimming whitespace). These are excluded from the differences array.
transformedSource value exists but differs from the canonical value — the ETL applied a transformation (e.g., date normalization, currency parsing, status mapping).
missingSource cell is empty or null but a canonical value was produced (or vice versa).

Response

Success (200):

{ "units": [ { "unitId": "101", "sourceRowNumber": 5, "sourceCells": [ { "column": "A", "header": "Unit #", "value": "101" }, { "column": "B", "header": "Resident", "value": "John Smith" }, { "column": "C", "header": "Sq Ft", "value": "850" }, { "column": "D", "header": "Rent", "value": "$1,200.00" } ], "canonicalFields": { "unit_id": "101", "tenant_name": "John Smith", "sqft": 850, "market_rent": 1200 }, "differences": [ { "canonicalField": "market_rent", "sourceColumn": "D", "sourceValue": "$1,200.00", "canonicalValue": 1200, "type": "transformed" } ] } ] }

Response Types

ComparisonUnit

FieldTypeDescription
unitIdstringThe Unit identifier (from unit_id field, or row_N fallback)
sourceRowNumbernumber1-indexed row number in the original spreadsheet
sourceCellsarrayAll non-empty cells from the source row
sourceCells[].columnstringColumn letter (e.g., "A", "B", "AA")
sourceCells[].headerstringHeader text from the header row, or column letter as fallback
sourceCells[].valuestringRaw cell value from the source File
canonicalFieldsobjectAll extracted fields for this Unit (excluding raw_extra)
differencesarrayFields where source and canonical values diverge

ComparisonDiff

FieldTypeDescription
canonicalFieldstringName of the canonical field (e.g., "market_rent")
sourceColumnstringColumn letter in the source File
sourceValuestringRaw value from the source cell
canonicalValueunknownExtracted/transformed value
typestringOne of "mapped", "transformed", or "missing"

Validation Errors

CheckStatusMessage
Missing job_id400Missing job_id
Job not found404Job not found
Job not complete400Job not complete
No structure result400No structure result
Original File download failed500File download failed
Output File not found500Output file not found
Rent Roll Sheet missing from output500Rent Roll sheet not found in output
Last updated on