API Reference

ChangeCheck API v1 — Deterministic table diff over HTTP.

Authentication

All requests use your license key as a Bearer token:

Authorization: Bearer <your-license-key>

License keys are issued on purchase. Free-tier requests (no header) are limited to 5 per day per IP.

Endpoints

MethodPathDescriptionCredits
POST/v1/diffCompare two files1
GET/v1/diff/healthCheck auth & credits0

POST /v1/diff

Upload two files as multipart form-data. Returns a structured diff with added, removed, and modified rows.

Request fields

FieldTypeRequiredDescription
fileAfileYesBase file (CSV, XLSX, TSV)
fileBfileYesChanged file (CSV, XLSX, TSV)
keystringNoColumn name for row matching. Auto-detected if omitted.
normalizestringNofinance to enable finance number normalization. Default: off.

Quick Start

Basic comparison

curl -X POST https://changecheck.se/v1/diff \
  -H "Authorization: Bearer YOUR_KEY" \
  -F fileA=@before.csv \
  -F fileB=@after.csv

With key column

curl -X POST https://changecheck.se/v1/diff \
  -H "Authorization: Bearer YOUR_KEY" \
  -F fileA=@before.csv \
  -F fileB=@after.csv \
  -F key=employee_id

Health check

curl https://changecheck.se/v1/diff/health \
  -H "Authorization: Bearer YOUR_KEY"

Response Schema

Successful responses return a summary-first JSON structure. CI pipelines can read summary only; full row-level detail is in rows.

{
  "summary": {
    "rows_added": 12,
    "rows_removed": 3,
    "cells_modified": 47,
    "total_rows_file_a": 1500,
    "total_rows_file_b": 1509,
    "matched_by": "employee_id",
    "matched_by_confidence": "high",
    "has_schema_changes": true,
    "has_data_changes": true
  },
  "schema": {
    "added_columns": ["price"],
    "removed_columns": [],
    "renamed_columns": []
  },
  "rows": {
    "added": [
      {
        "key": "EMP-1042",
        "values": { "name": "Jane", "dept": "Sales" }
      }
    ],
    "removed": [
      {
        "key": "EMP-0017",
        "values": { "name": "Bob", "dept": "HR" }
      }
    ],
    "modified": [
      {
        "key": "EMP-0203",
        "changes": [
          { "column": "salary", "from": "50000", "to": "52000" },
          { "column": "dept", "from": "Engineering", "to": "Product" }
        ]
      }
    ]
  },
  "meta": {
    "request_id": "req_a1b2c3d4",
    "credits_remaining": 12,
    "engine_version": "diff-core@0.1.0",
    "processing_ms": 342,
    "deterministic": true
  }
}

Error Codes

All errors return a consistent JSON format:

{
  "error": {
    "code": "OUT_OF_CREDITS",
    "message": "No credits remaining.",
    "request_id": "req_a1b2c3d4"
  }
}
CodeHTTP StatusDescription
MISSING_FILE400fileA or fileB not provided
INVALID_FORMAT400File is not CSV/XLSX/TSV
INVALID_KEY400Specified key column not found in both files
FILE_EMPTY400File contains no data rows
UNAUTHORIZED401Missing or invalid license key
OUT_OF_CREDITS402No credits remaining
FILE_TOO_LARGE413File exceeds 4 MB upload limit
TOO_MANY_ROWS422File exceeds 5,000 rows
TOO_MANY_COLUMNS422File exceeds 50 columns
RATE_LIMITED429Too many requests
INTERNAL_ERROR500System error (credit auto-reverted)

Limits

LimitValue
Max rows per file5,000
Max columns per file50
Max file size4 MB per file
Rate limit (authenticated)60 requests/min
Rate limit (free tier)5 requests/day
Accepted formats.csv, .xlsx, .xls, .tsv