Developer API

MySimpleReport API Integration Guide

Submit medical files or text, receive structured analysis, and build plain-language health report workflows into your own product.

POST /v1/analyze-file
curl -X POST https://dev.mysimplereport.com/v1/analyze-file \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "file_url": "https://example.com/report.pdf" }'
Version1.0.0
ProtocolHTTPS only
FormatJSON
AuthenticationBearer token
API

Build against MySimpleReport

The MySimpleReport API enables developers to programmatically submit medical documents, images, and text for AI analysis. The API returns a structured analysis object in JSON format — a plain-language title and explanation, detailed findings, key result cards, and suggested questions for your doctor — ready to integrate into your application workflow.

1. How Authentication Works

All API requests must be authenticated using an API key passed as a Bearer token in the Authorization header.

The Bearer Token Lifecycle

Every request must include your API Key inside the Authorization HTTP header using the standard Bearer scheme (defined in RFC 6750):

Authorization: Bearer YOUR_API_KEY

Behind the scenes: The server reads the header, strips out the Bearer prefix, and hashes your raw key utilizing secure SHA-256 algorithms. It checks its presence against the active database clusters, ensuring the key hasn't expired or crossed rate thresholds before granting request processing rights.

Security Notice: Never expose your API key in client-side code, public repositories, URL query parameters, request bodies, or logs. Store it securely using environment variables or a secrets manager over secure HTTPS.

Required Request Headers

Header Value Required Notes
Authorization Bearer YOUR_API_KEY Yes Prefix must be exactly Bearer (including the trailing space)
Content-Type application/json Yes All inbound request bodies must be JSON format
Accept application/json Yes All outbound responses are served in JSON format

Example Raw Header Block

POST /v1/analyze-file HTTP/1.1
Host: dev.mysimplereport.com
Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4
Content-Type: application/json
Accept: application/json

2. Base Configuration

Base URL https://dev.mysimplereport.com/v1
Protocol HTTPS (TLS 1.2+ required)
Data Format JSON (Request body & Response parsing)
Auth Method Bearer Token (API Key Verified)
Encoding UTF-8

3. API Endpoints

3.1 Analyze Single File

Submits a single medical document or image for analysis — either uploaded directly (multipart/form-data) or referenced by a publicly accessible URL.

POST /analyze-file

Request Body Fields

Parameter Type Required Description
file File (multipart) Either The document/image to analyze, uploaded directly as multipart/form-data. Use this or file_url.
file_url String (JSON) Either A publicly accessible URL to the file. The server downloads it. Use this or upload a file.
purpose String No Optional context hint (e.g., "lab_report", "radiology", "prescription")

Code Examples — Option A: upload a file directly

curl -X POST https://dev.mysimplereport.com/v1/analyze-file \
  -H "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" \
  -F "file=@/path/to/blood-test.pdf" \
  -F "purpose=lab_report"
import requests

url = "https://dev.mysimplereport.com/v1/analyze-file"
headers = {"Authorization": "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4"}

with open("blood-test.pdf", "rb") as f:
    response = requests.post(
        url,
        headers=headers,
        files={"file": ("blood-test.pdf", f, "application/pdf")},
        data={"purpose": "lab_report"},
    )

result = response.json()
print(response.status_code)
print(result["analysis"]["title"])
print(result["analysis"]["simple_explanation"])
import fs from "node:fs";

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("blood-test.pdf")]), "blood-test.pdf");
form.append("purpose", "lab_report");

const response = await fetch("https://dev.mysimplereport.com/v1/analyze-file", {
  method: "POST",
  headers: { "Authorization": "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" },
  body: form
});

const result = await response.json();
console.log(response.status);
console.log(result.analysis.title);
console.log(result.analysis.simple_explanation);
using System.Net.Http.Headers;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4");

using var form = new MultipartFormDataContent();
using var stream = File.OpenRead("blood-test.pdf");

var fileContent = new StreamContent(stream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
form.Add(fileContent, "file", "blood-test.pdf");
form.Add(new StringContent("lab_report"), "purpose");

var response = await client.PostAsync("https://dev.mysimplereport.com/v1/analyze-file", form);
var json = await response.Content.ReadAsStringAsync();

Console.WriteLine((int)response.StatusCode);
Console.WriteLine(json);
<?php
$ch = curl_init("https://dev.mysimplereport.com/v1/analyze-file");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    "file"    => new CURLFile("blood-test.pdf", "application/pdf"),
    "purpose" => "lab_report",
]);

$response = curl_exec($ch);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status . PHP_EOL;
$result = json_decode($response, true);
echo $result["analysis"]["simple_explanation"];

cURL — Option B: pass a file URL (JSON)

curl -X POST https://dev.mysimplereport.com/v1/analyze-file \
  -H "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "file_url": "https://yourdomain.com/files/blood-test.pdf",
    "purpose": "lab_report"
  }'

Expected Response (200 OK)

{
  "status": "success",
  "request_id": "5b5ccc65-9005-46dd-85cf-757c915bd386",
  "processed_at": "2026-07-16T15:23:18.4466629Z",
  "file_url": "https://yourdomain.com/files/blood-test.pdf",
  "purpose": "lab_report",
  "analysis": {
    "title": "Understanding Your Blood Test Results",
    "simple_explanation": "<h2>About Your Blood Work</h2><p>You recently had a blood test to check the health of your blood cells... Every single one of your blood counts is in a healthy range.</p>",
    "detailed_findings": "<h2>Detailed Findings</h2><h3>Blood Count Results</h3><ul><li><strong>Oxygen-Carrying Protein (Hemoglobin):</strong> Your result: 14.2 g/dL... within the normal range of 13.5 to 17.5 g/dL.</li></ul>",
    "important_findings_summary": "<h2>Important Findings Summary</h2><h3>Results That Need Attention</h3><p>Great news &mdash; all your results are within healthy ranges.</p>",
    "glossary": "<h2>Medical Terms Explained</h2><ul><li><strong>Hemoglobin:</strong> The protein in red blood cells that carries oxygen through your body.</li></ul>",
    "summary_cards": [
      { "label": "Oxygen-Carrying Protein (Hemoglobin)", "value": "14.2", "unit": "g/dL", "status": "normal", "note": "Healthy range: 13.5–17.5" },
      { "label": "White Blood Cell Count (WBC)", "value": "8200", "unit": "/mcL", "status": "normal", "note": "Healthy range: 4500–11000" },
      { "label": "Clotting Cells (Platelets)", "value": "225000", "unit": "/mcL", "status": "normal", "note": "Healthy range: 150000–450000" }
    ],
    "ask_your_doctor": [
      "Since my blood counts are all healthy, is there anything specific I should keep doing to maintain this good health?",
      "How often should I have these blood tests repeated as part of my general check-ups?"
    ]
  },
  "usage": {
    "documents_analyzed": 1,
    "credits_used": 1,
    "credits_remaining": null
  }
}

Important: simple_explanation, detailed_findings, important_findings_summary and glossary contain ready-to-render HTML (<h2>, <p>, <ul>, <strong>) — not plain text. Inject them into your page as HTML. title, summary_cards and ask_your_doctor are plain text. credits_remaining is null when the key has no prepaid credit balance.

3.2 Analyze Multiple Files

Submits two or more files in a single request for batch analysis (maximum of 20 elements per batch array request).

POST /analyze-multiple-files

Supported Formats Matrix

Category Formats Extension Mapping
Documents .pdf
Images .jpg, .jpeg, .png, .gif, .webp, .tiff, .bmp

Code Examples — Option A: upload files directly

curl -X POST https://dev.mysimplereport.com/v1/analyze-multiple-files \
  -H "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" \
  -F "files=@/path/to/blood-test.pdf" \
  -F "files=@/path/to/xray.jpg" \
  -F "purpose=lab_report"
import requests

url = "https://dev.mysimplereport.com/v1/analyze-multiple-files"
headers = {"Authorization": "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4"}

files = [
    ("files", ("blood-test.pdf", open("blood-test.pdf", "rb"), "application/pdf")),
    ("files", ("xray.jpg", open("xray.jpg", "rb"), "image/jpeg")),
]

response = requests.post(url, headers=headers, files=files, data={"purpose": "lab_report"})
result = response.json()

for item in result["results"]:
    print(item["filename"], "->", item["status"])
    if item["status"] == "success":
        print("   ", item["analysis"]["title"])
import fs from "node:fs";

const form = new FormData();
form.append("files", new Blob([fs.readFileSync("blood-test.pdf")]), "blood-test.pdf");
form.append("files", new Blob([fs.readFileSync("xray.jpg")]), "xray.jpg");
form.append("purpose", "lab_report");

const response = await fetch("https://dev.mysimplereport.com/v1/analyze-multiple-files", {
  method: "POST",
  headers: { "Authorization": "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" },
  body: form
});

const result = await response.json();
for (const item of result.results) {
  console.log(item.filename, "->", item.status);
  if (item.status === "success") console.log("   ", item.analysis.title);
}
using System.Net.Http.Headers;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4");

using var form = new MultipartFormDataContent();

foreach (var (path, mime) in new[] { ("blood-test.pdf", "application/pdf"), ("xray.jpg", "image/jpeg") })
{
    var bytes = await File.ReadAllBytesAsync(path);
    var part = new ByteArrayContent(bytes);
    part.Headers.ContentType = new MediaTypeHeaderValue(mime);
    form.Add(part, "files", Path.GetFileName(path));
}

form.Add(new StringContent("lab_report"), "purpose");

var response = await client.PostAsync("https://dev.mysimplereport.com/v1/analyze-multiple-files", form);
Console.WriteLine(await response.Content.ReadAsStringAsync());
<?php
$ch = curl_init("https://dev.mysimplereport.com/v1/analyze-multiple-files");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    "files[0]" => new CURLFile("blood-test.pdf", "application/pdf"),
    "files[1]" => new CURLFile("xray.jpg", "image/jpeg"),
    "purpose"  => "lab_report",
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
foreach ($result["results"] as $item) {
    echo $item["filename"] . " -> " . $item["status"] . PHP_EOL;
}

cURL — Option B: pass file URLs (JSON)

curl -X POST https://dev.mysimplereport.com/v1/analyze-multiple-files \
  -H "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "file_urls": [
      "https://yourdomain.com/files/blood-test.pdf",
      "https://yourdomain.com/files/xray.jpg"
    ],
    "purpose": "lab_report"
  }'

Expected Response (200 OK)

{
  "status": "success",
  "request_id": "z9y8x7w6-v5u4-t3s2-r1q0-p9o8n7m6l5k4",
  "processed_at": "2026-07-16T11:00:09Z",
  "total_files": 2,
  "purpose": "lab_report",
  "results": [
    {
      "file_url": "https://yourdomain.com/files/blood-test.pdf",
      "filename": "blood-test.pdf",
      "status": "success",
      "error": null,
      "analysis": {
        "title": "Understanding Your Blood Test Results",
        "simple_explanation": "<h2>About Your Blood Work</h2><p>Every single one of your blood counts is in a healthy range.</p>",
        "detailed_findings": "<h2>Detailed Findings</h2><ul><li><strong>Hemoglobin:</strong> 14.2 g/dL — within the normal range.</li></ul>",
        "important_findings_summary": "<h2>Important Findings Summary</h2><p>All results are within healthy ranges.</p>",
        "glossary": "<h2>Medical Terms Explained</h2><ul><li><strong>Hemoglobin:</strong> Carries oxygen through your body.</li></ul>",
        "summary_cards": [
          { "label": "Hemoglobin", "value": "14.2", "unit": "g/dL", "status": "normal", "note": "Healthy range: 13.5–17.5" }
        ],
        "ask_your_doctor": [ "How often should I repeat these blood tests?" ]
      }
    },
    {
      "file_url": "https://yourdomain.com/files/xray.jpg",
      "filename": "xray.jpg",
      "status": "error",
      "error": "The provided content could not be analyzed.",
      "analysis": null
    }
  ],
  "usage": {
    "documents_analyzed": 1,
    "credits_used": 1,
    "credits_remaining": null
  }
}

Billing — one request, one report: all files in a single call are treated as pages/images of one medical report, so the request costs 1 report no matter how many files you attach. Note the example above sends 2 files yet reports "documents_analyzed": 1. Batching the pages of one report is therefore cheaper than sending them as separate requests. A request where every file fails bills 0 and returns 422.

Per-file results: each file is still analyzed independently — the example shows one success and one failure. A failed file returns "status": "error", an error message and "analysis": null, while the others still succeed. The HTML-content note from 3.1 applies to each item's analysis block.

3.3 Analyze Text

Submits raw text content directly for processing. No file host requirement is needed (max limit of 100,000 characters).

POST /analyze-text

Code Examples

curl -X POST https://dev.mysimplereport.com/v1/analyze-text \
  -H "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "text": "Hemoglobin 14.2 g/dL, WBC 8200/mcL, Platelets 225000/mcL. All within normal limits.",
    "purpose": "lab_report"
  }'
import requests

response = requests.post(
    "https://dev.mysimplereport.com/v1/analyze-text",
    headers={
        "Authorization": "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4",
        "Content-Type": "application/json",
    },
    json={
        "text": "Hemoglobin 14.2 g/dL, WBC 8200/mcL, Platelets 225000/mcL. All within normal limits.",
        "purpose": "lab_report",
    },
)

result = response.json()
print(result["analysis"]["title"])
print(result["analysis"]["simple_explanation"])
const response = await fetch("https://dev.mysimplereport.com/v1/analyze-text", {
  method: "POST",
  headers: {
    "Authorization": "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    text: "Hemoglobin 14.2 g/dL, WBC 8200/mcL, Platelets 225000/mcL. All within normal limits.",
    purpose: "lab_report"
  })
});

const result = await response.json();
console.log(result.analysis.title);
console.log(result.analysis.simple_explanation);
using System.Text;
using System.Text.Json;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4");

var payload = new
{
    text = "Hemoglobin 14.2 g/dL, WBC 8200/mcL, Platelets 225000/mcL. All within normal limits.",
    purpose = "lab_report"
};

var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://dev.mysimplereport.com/v1/analyze-text", content);

Console.WriteLine(await response.Content.ReadAsStringAsync());
<?php
$ch = curl_init("https://dev.mysimplereport.com/v1/analyze-text");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer msr_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    "text"    => "Hemoglobin 14.2 g/dL, WBC 8200/mcL, Platelets 225000/mcL.",
    "purpose" => "lab_report",
]));

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
echo $result["analysis"]["simple_explanation"];

Expected Response (200 OK)

{
  "status": "success",
  "request_id": "5b5ccc65-9005-46dd-85cf-757c915bd386",
  "processed_at": "2026-07-16T15:23:18.4466629Z",
  "file_url": null,
  "purpose": "lab_report",
  "analysis": {
    "title": "Understanding Your Blood Test Results",
    "simple_explanation": "<h2>About Your Blood Work</h2><p>You recently had a blood test to check the health of your blood cells... Every single one of your blood counts is in a healthy range.</p>",
    "detailed_findings": "<h2>Detailed Findings</h2><h3>Blood Count Results</h3><ul><li><strong>White Blood Cell Count (WBC):</strong> Your result: 8200/mcL... within the normal range of 4500 to 11000/mcL.</li></ul>",
    "important_findings_summary": "<h2>Important Findings Summary</h2><h3>Results That Need Attention</h3><p>Great news &mdash; all your results are within healthy ranges.</p>",
    "glossary": "<h2>Medical Terms Explained</h2><ul><li><strong>WBC:</strong> Stands for White Blood Cells, your body's defense team against germs.</li></ul>",
    "summary_cards": [
      { "label": "Oxygen-Carrying Protein (Hemoglobin)", "value": "14.2", "unit": "g/dL", "status": "normal", "note": "Healthy range: 13.5–17.5" },
      { "label": "White Blood Cell Count (WBC)", "value": "8200", "unit": "/mcL", "status": "normal", "note": "Healthy range: 4500–11000" }
    ],
    "ask_your_doctor": [
      "Since my blood counts are all healthy, is there anything specific I should keep doing to maintain this good health?",
      "How often should I have these blood tests repeated as part of my general check-ups?"
    ]
  },
  "usage": {
    "documents_analyzed": 1,
    "credits_used": 1,
    "credits_remaining": null
  }
}

Live response: this is a real, unedited response shape from the API. file_url is always null for text analysis. The HTML-content note from 3.1 applies here too.

4. Request Parameters Reference

Parameter Name Target Endpoint(s) Type Specification Required Status Functional Description
file_url analyze-file String Yes URL route pointing to a single file object layout
file_urls analyze-multiple-files String[] (Array) Yes Array structure storing file URLs (maximum capacity size: 20)
text analyze-text String Yes Raw body content strings intended for validation parsing
purpose All Endpoints String No Context hint parameter targeting processing accuracy bounds
language analyze-text String No Language explicit indicator tracking standard ISO 639-1 layout formats

5. Status & Error Reference

All structured responses that fail processing return consistent error objects. Click an entry in the list down below to inspect detailed schema implementations:

HTTP Status Error Payload Code Root Core Cause Condition
400 Bad Request BAD_REQUEST Malformed payload JSON strings or absent mandatory parameters.
401 Unauthorized UNAUTHORIZED Missing credentials or invalid bearer token configurations.
401 Unauthorized KEY_EXPIRED The allocated API key has passed its preconfigured retention lifespan.
403 Forbidden KEY_DISABLED Key execution parameters suspended via developer administration consoles.
402 Payment Required QUOTA_EXPIRED Subscription tiers or assigned runtime quotas have reached end-of-life status.
422 Unprocessable Entity VALIDATION_ERROR Unreachable source URL, corrupted files, or unsupported type schemas.
429 Too Many Requests RATE_LIMIT_EXCEEDED_DAILY The workspace has depleted its rolling daily request count limit constraints.
429 Too Many Requests RATE_LIMIT_EXCEEDED_MONTHLY Monthly processing transaction quotas have been completely filled out.
429 Too Many Requests SPEND_LIMIT_EXCEEDED Financial safety limits or billing cap milestones were reached.
500 Internal Error INTERNAL_SERVER_ERROR Unexpected system state exceptions in backend server engine pools.
// Select a row from the validation matrix above to load contextual response payload schemas...