evidence.guide REST API

Upload a research PDF, poll for completion, and consume structured study data as JSON.

v1HTTPS onlyBearer auth

Send requests with Authorization: Bearer <token>. Generate and rotate keys in your Dashboard → API Keys.

import time, requests

API = "https://api.evidence.guide/v1"
HEADERS = {"Authorization": "Bearer <API_KEY>"}

# 1) Upload a PDF
with open("trial.pdf", "rb") as f:
    res = requests.post(f"{API}/parse", headers=HEADERS, files={"file": f})
res.raise_for_status()
job_id = res.json()["job_id"]

# 2) Poll for completion (202 = still processing)
while True:
    res = requests.get(f"{API}/result/{job_id}", headers=HEADERS)
    res.raise_for_status()
    data = res.json()
    status = data.get("status")
    if status == "completed":
        break
    if status == "failed":
        raise RuntimeError(data.get("error", {}).get("message", "job_failed"))
    time.sleep(int(res.headers.get("Retry-After", 5)))

# 3) Use the structured output
payload = data["result"]
print(payload["studies"][0]["p_value"])

Endpoints (v1)

Minimal surface area: upload → poll → feedback.

POST /parse

Submit a research PDF for structured extraction.

  • Body: multipart/form-data with file (PDF). File uploads only; DOI strings are not accepted in v2.
  • Returns: {"job_id": "job_123"}
  • Notes: PDFs with a text layer recommended; OCR scans may reduce accuracy.

GET /result/{job_id}

Fetch job status and structured result payload.

{
  "status": "queued | processing | completed | failed | cancelled",
  "result": { "...": "present when completed" },
  "error": {
    "message": "present when failed"
  }
}

When status is queued or processing, the response includes Retry-After: <seconds>. Respect it to stay within rate limits.

POST /studies/{study_id}/feedback

Attach human corrections or notes to a completed study. Stored server-side for evaluation; does not mutate prior results.

{
  "label": "correct | incorrect | unclear | missing",
  "comment": "Optional context for reviewers",
  "field_name": "p_value" // Optional: target a specific extracted field
}

Returns 201 Created with the new feedback identifier.

Response schema (concise)

Fields may be null or omitted when not extractable.

{
  "metadata": {
    "title": "string",
    "doi": "string|null",
    "year": 2024,
    "journal": "string|null"
  },
  "studies": [
    {
      "design": "between|within|observational|null",
      "n": 120,
      "arms": ["treatment","control"],
      "hypotheses": ["H1 ..."],
      "tests": [
        {
          "stat": "t|F|chi2|z|r|beta|OR|RR|HR|other",
          "value": -2.31,
          "df": [58],
          "p": 0.024,
          "effect_size": { "type": "d|r|g|OR|...", "value": 0.35, "ci": [0.10, 0.60] },
          "measure": "primary_outcome",
          "note": "optional"
        }
      ],
      "excerpts": [
        { "text": "quoted sentence...", "page": 5 }
      ]
    }
  ]
}

Errors & rate limits

// 400 Bad Request
{ "error": "invalid_request", "message": "No file provided." }

// 401 Unauthorized
{ "error": "unauthorized", "message": "Invalid or revoked API key." }

// 402 Insufficient credits
{ "error": "insufficient_credits", "message": "Top up credits in the dashboard." }

// 404 Not Found
{ "error": "not_found", "message": "Unknown job_id." }

// 429 Rate limited
{ "error": "rate_limited", "message": "Too many requests. Retry later." }

Default rate limit: 60 requests per minute per account. Polling endpoints include Retry-After; back off ≥5 seconds if not provided to avoid 429 responses.

Common pitfalls

Quick fixes before emailing us.

401 Unauthorized

Wrong or rotated key. Generate a new one in Dashboard → API Keys.

402 Insufficient credits

Buy credits in Dashboard → Billing, then retry the request.

Polling too fast

Use the Retry-After header or a ≥5s exponential backoff between polls.

Scanned PDFs

Prefer PDFs with a text layer; OCR or export to PDF/A before uploading.

FAQ

Where do I get an API key?
Dashboard → API Keys. Keys are masked after creation; rotate regularly.
Webhooks?
Not yet; polling only in v2.
SDKs?
Use the quickstart snippets for now.
Support?
Email [email protected].