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.