Clinical Trial Results Table QA API

Structural QA of two normalized tables. Product page and free test form.

Endpoint

PaidPOST https://www.spreadrun.com/api/v1/clinical-trial-table-validator, API key required, $0.25 per completed audit
DemoPOST https://www.spreadrun.com/api/demo/clinical-trial-table-validator, no key, 512 KB, 10 runs per day
Content-Typeapplication/json

Request

A JSON object with exactly two string fields, each holding a UTF-8 CSV table with a header row. Extra fields are rejected.

{
  "studiesCsv": "trial_id,condition,phase\nNCT90000001,Type 2 diabetes,PHASE3\n...",
  "outcomesCsv": "trial_id,outcome_id,outcome_type,primary_endpoint,result_status,results_first_post_date\n..."
}
FieldRequired columns
studiesCsvtrial_id, condition, phase. One row per trial.
outcomesCsvtrial_id, outcome_id, outcome_type, primary_endpoint, result_status, results_first_post_date. One row per outcome measure.

Rejected with HTTP 400 and not charged: a body that is not this JSON object, a missing or empty table, missing required columns, duplicate headers, more than 40 columns, rows with a different number of cells than the header, malformed CSV, more than 10,000 rows in a table, more than 5 MiB of CSV in total, or a request body over 4.4 MB (HTTP 413). The last limit comes first in practice.

Report

FieldMeaning
statusPASS when no rule fired, otherwise FAIL.
rowCountsData rows read from each table.
fieldCoverageShare of rows with a non-empty value, per required column, 0 to 1.
issueCount, issueCountsTotal findings and findings per code.
issuesUp to 1,000 findings: table, record (1-based data row, header excluded), field, code. Cell values are never echoed.
issuesTruncatedTrue when more than 1,000 findings exist.
inputSha256SHA-256 of each submitted table, so you can tie a report to an exact input.
scopeWhat the audit does not certify.

The audit is deterministic: the same tables always produce the same report.

Finding codes

CodeMeaning
MISSING_VALUEA required column is empty in this row.
INVALID_NCT_IDtrial_id is not "NCT" followed by exactly 8 digits.
DUPLICATE_KEYRepeats an earlier row: trial_id in the studies table, trial_id plus outcome_id in the outcomes table.
ORPHAN_OUTCOMEThe outcome points to a trial_id that has no row in the studies table.
INVALID_OUTCOME_TYPEoutcome_type is not PRIMARY, SECONDARY or OTHER_PRE_SPECIFIED.
INVALID_ISO_DATEresults_first_post_date is not a real calendar date written as YYYY-MM-DD.

Example response

A paid audit of the synthetic sample tables with defects (studies, outcomes). Generated by running the real endpoint code.

{
  "requestId": "7f3c2a1e-5b8d-4c6f-9e0a-1d2b3c4d5e6f",
  "api": "clinical-trial-table-validator",
  "mode": "paid",
  "charged": true,
  "priceCents": 25,
  "balanceCents": 950,
  "report": {
    "schemaVersion": 1,
    "status": "FAIL",
    "rowCounts": {
      "studiesCsv": 6,
      "outcomesCsv": 7
    },
    "fieldCoverage": {
      "studiesCsv": {
        "condition": 1,
        "phase": 1,
        "trial_id": 1
      },
      "outcomesCsv": {
        "outcome_id": 1,
        "outcome_type": 1,
        "primary_endpoint": 0.857143,
        "result_status": 1,
        "results_first_post_date": 1,
        "trial_id": 1
      }
    },
    "issueCount": 7,
    "issueCounts": {
      "DUPLICATE_KEY": 2,
      "INVALID_ISO_DATE": 1,
      "INVALID_NCT_ID": 1,
      "INVALID_OUTCOME_TYPE": 1,
      "MISSING_VALUE": 1,
      "ORPHAN_OUTCOME": 1
    },
    "issues": [
      {
        "table": "studiesCsv",
        "record": 4,
        "field": "trial_id",
        "code": "INVALID_NCT_ID"
      },
      {
        "table": "studiesCsv",
        "record": 6,
        "field": "trial_id",
        "code": "DUPLICATE_KEY"
      },
      {
        "table": "outcomesCsv",
        "record": 4,
        "field": "primary_endpoint",
        "code": "MISSING_VALUE"
      },
      {
        "table": "outcomesCsv",
        "record": 5,
        "field": "outcome_id",
        "code": "DUPLICATE_KEY"
      },
      {
        "table": "outcomesCsv",
        "record": 3,
        "field": "results_first_post_date",
        "code": "INVALID_ISO_DATE"
      },
      {
        "table": "outcomesCsv",
        "record": 6,
        "field": "trial_id",
        "code": "ORPHAN_OUTCOME"
      },
      {
        "table": "outcomesCsv",
        "record": 7,
        "field": "outcome_type",
        "code": "INVALID_OUTCOME_TYPE"
      }
    ],
    "issuesTruncated": false,
    "inputSha256": {
      "studiesCsv": "34a162e906102e1701f4f90de8eea9c57fade81ac11de5310c11b44d46ef4ae9",
      "outcomesCsv": "4e355d3c00765d6bb0e63e7352f923cf5fda2d8a9d255ae1b57c0dc0639cca96"
    },
    "scope": "Structural QA only; no source authenticity, clinical accuracy, freshness, regulatory compliance or reuse-rights certification."
  }
}

Errors

See the shared error table. Example input error (HTTP 400, not charged):

{
  "error": {
    "code": "input_error",
    "message": "studiesCsv: unique headers and required columns are mandatory (maximum 40).",
    "requestId": "7f3c2a1e-5b8d-4c6f-9e0a-1d2b3c4d5e6f",
    "charged": false
  }
}

Code samples

curl -X POST https://www.spreadrun.com/api/v1/clinical-trial-table-validator \
  -H "Authorization: Bearer $SPREADRUN_API_KEY" \
  -H "Content-Type: application/json" \
  --data "$(jq -n --rawfile s studies.csv --rawfile o outcomes.csv '{studiesCsv: $s, outcomesCsv: $o}')"