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:
| Parameter | Type | Required | Description |
|---|---|---|---|
job_id | string | Yes | UUID 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
- Authenticate via
checkAuth() - Validate query parameter and fetch the job row
- Download original File from Supabase Storage using
storage_path - Parse original into
CellGridobjects viareadExcelBuffer() - Download Output File from
outputs/{job_id}/output.xlsx - Parse output and extract rows from the
Rent RollSheet - 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_mappingto its canonical field - Classify each field as
mapped,transformed, ormissing
- Locate the source row in the original grid by matching
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:
| Type | Description |
|---|---|
mapped | Source and canonical values match exactly (after trimming whitespace). These are excluded from the differences array. |
transformed | Source value exists but differs from the canonical value — the ETL applied a transformation (e.g., date normalization, currency parsing, status mapping). |
missing | Source 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
| Field | Type | Description |
|---|---|---|
unitId | string | The Unit identifier (from unit_id field, or row_N fallback) |
sourceRowNumber | number | 1-indexed row number in the original spreadsheet |
sourceCells | array | All non-empty cells from the source row |
sourceCells[].column | string | Column letter (e.g., "A", "B", "AA") |
sourceCells[].header | string | Header text from the header row, or column letter as fallback |
sourceCells[].value | string | Raw cell value from the source File |
canonicalFields | object | All extracted fields for this Unit (excluding raw_extra) |
differences | array | Fields where source and canonical values diverge |
ComparisonDiff
| Field | Type | Description |
|---|---|---|
canonicalField | string | Name of the canonical field (e.g., "market_rent") |
sourceColumn | string | Column letter in the source File |
sourceValue | string | Raw value from the source cell |
canonicalValue | unknown | Extracted/transformed value |
type | string | One of "mapped", "transformed", or "missing" |
Validation Errors
| Check | Status | Message |
|---|---|---|
Missing job_id | 400 | Missing job_id |
| Job not found | 404 | Job not found |
| Job not complete | 400 | Job not complete |
| No structure result | 400 | No structure result |
| Original File download failed | 500 | File download failed |
| Output File not found | 500 | Output file not found |
| Rent Roll Sheet missing from output | 500 | Rent Roll sheet not found in output |
Last updated on