Skip to main content

API Endpoints

The HTTP surface is intentionally small — Clinisync exposes one upload endpoint and serves the static frontend.

MethodPathPurpose
POST/uploadAccept a multipart spreadsheet upload, write per-sheet CSVs + a manifest, and return JSON describing them. See Upload Endpoint.
POST/previewDry-run: identical pipeline to /upload but writes nothing. Returns the same JSON shape minus files / manifest, plus a previewRows block per sheet (capped at 25 rows) and a kAnonymity block reporting k, minK, and whether the cleaned output meets the threshold.
POST/detectScan an uploaded workbook for likely PHI / PII / quasi-identifier columns and return a suggested rule set ready to feed back into /upload or /preview. No files written.
GET/downloads/:filenameReturns a previously generated CSV or manifest. Strict filename allowlist (only files produced by the load step), gated on the same auth as /upload.
GET/ (and any other static file)Serves the browser UI from public/.

There is no GET /logs, no list endpoint for past uploads, and no individual download endpoint. Cleaned CSVs and the manifest are returned by filename in the /upload response and can be retrieved out-of-band from the csvs/ directory while they exist (see retention below).

Status codes

CodeReturned for
200Successful upload — body is JSON with files, manifest, sheets, and aggregate stats.
400No file, unsupported extension (anything outside .xlsx, .xls, .ods), or file larger than 5 MB.
401CLINISYNC_API_KEY is set on the server and the request did not include a matching Authorization: Bearer or X-API-Key header.
422Virus scanner detected malware in the uploaded file (only when CLAMAV_TCP_HOST is configured).
429Rate limit exceeded — Retry-After header tells you how long to wait. Default: 30 requests / 60 s per IP.
500Internal error during ETL. The uploaded file is removed in the finally handler regardless.
503Virus scanner was configured but unreachable; uploads are rejected rather than silently bypassing the scanner.

Retention

Cleaned files are not kept indefinitely. Every successful /upload triggers a sweep of the csvs/ directory that deletes anything older than CLINISYNC_CSV_TTL_HOURS (default 24 h). Plan to download the files referenced in the response within that window.

Auth, rate limit, virus scan

All three are off by default and gate themselves on environment variables:

  • CLINISYNC_API_KEY — when set, every request must carry the key. Comparison is crypto.timingSafeEqual.
  • REDIS_URL — when set, the per-IP rate limiter swaps its in-memory store for Redis (atomic INCR+PEXPIRE NX).
  • CLAMAV_TCP_HOST — when set, the upload is scanned via clamd before reaching the ETL pipeline.

See .env.example for the full list.