PrevIQ Docs

Ingestion

Inspect load history, scheduled jobs, and database stats; upload raw data.

These endpoints back the data-operations views. Most clients use them read-only to confirm data freshness; uploading is typically handled by OSPRI.

Database stats

GET /api/v1/ingestion/stats

Live database-level counts behind the data status panel.

Response

{
  "normalized_records": 934512,
  "prevalence_rollups": 1751,
  "db_size_bytes": 391323648,
  "db_size_mb": 373.2,
  "last_ingestion": "2026-05-22T07:47:00",
  "vendor_count": 8,
  "syndrome_count": 7
}

Ingestion history

GET /api/v1/ingestion/history

Lists recorded ingestion runs (newest last). Each run reports vendor_id, source_file, rows_ingested, rows_skipped, rows_deduplicated, and qa_flags.

Monthly jobs

GET /api/v1/ingestion/jobs

Lists scheduled/monthly ingestion job attempts with status (queued, running, succeeded, failed, skipped) and counts.

  • limitinteger, default: 50 — Maximum jobs to return.

Upload & ingest

POST /api/v1/ingestion/run

Upload a raw export and ingest it (parse → normalize → store → rebuild rollups). Sent as multipart/form-data.

  • filefile, required — An Ignite-style .csv, or an Excel .xlsx / .xlsm with a Raw Data sheet.
  • vendor_idstring — Required only when the filename doesn't follow the Ignite -RPT-... pattern.

cURL

curl -X POST "https://api.previq.ospri.bio/api/v1/ingestion/run" \
  -F "file=@AFC-RPT-PositiveNegative-20260409.csv" \
  -F "vendor_id=AFC"

Response (ingested)

{
  "data": {
    "status": "ingested",
    "vendor_id": "AFC",
    "source_file": "AFC-RPT-PositiveNegative-20260409.csv",
    "inserted": 18342,
    "rows_skipped": 0,
    "qa_flags": [],
    "rollups": { "vendor": 412, "syndrome": 73, "cross_vendor": 61 },
    "duration_seconds": 41.7
  },
  "meta": { "total": 1, "limit": 0, "offset": 0, "query": { "vendor_id": "AFC" } }
}

Note

Idempotent. PrevIQ hashes the file's contents; re-uploading the same file returns status: "skipped" instead of double-counting.

Important

Only .csv, .xlsx, and .xlsm are accepted (400 otherwise). A vendor_id is required if it can't be inferred from the filename. Large files can take 30–90 seconds — keep the connection open.