REST endpoints
Process reports, retrieve BiomPINs, and export results over HTTP. Use the Web Widget if you want the hosted upload and review interface instead.
Base URL: https://biomapi.com · Interactive API · OpenAPI schema
First request
Section titled “First request”Download the synthetic report as report.json, then submit it:
curl --fail-with-body https://biomapi.com/api/v1/biom/process \ -F "file=@report.json" \ -o result.jsonThis validates JSON without calling Gemini. To extract a PDF, change the filename to report.pdf. The example response shows the complete response to the synthetic JSON input. Request IDs, timestamps, and app versions vary.
Endpoints
Section titled “Endpoints”| Operation | Purpose |
|---|---|
| POST /biom/process | Extract or validate a report |
| GET /biom/retrieve | Retrieve a BiomPIN |
| POST /biom/export | Download CSV, XLSX, and JSON in a ZIP |
| GET /biom/usage | Check quotas and key validity |
| POST /biom/feedback | Rate a fresh BiomAI extraction |
| GET /status | Read lightweight service status |
| GET /health | Check Gemini and database readiness |
All operation paths use the /api/v1 prefix.
POST /api/v1/biom/process
Section titled “POST /api/v1/biom/process”Process a biometry file and return structured measurements.
File routing
Section titled “File routing”BiomAPI selects the engine from the file extension. If the filename has no extension, it checks the PDF/image header:
| Extension | Engine | What happens |
|---|---|---|
| PDF, JPG/JPEG (including JFIF/JPE), PNG, GIF, BMP | BiomAI | Report prepared for Gemini extraction |
| JSON | BiomJSON | Schema validation + metadata preservation |
BiomAPI ignores trailing whitespace in filenames. For PDFs and images without an extension, it checks a limited part of the file header. JSON requires a .json extension.
An unsupported extension or a PDF/image header that conflicts with the filename returns HTTP 400 before BiomAPI reserves extraction credits. The MIME type supplied by the client does not override these checks.
Request
Section titled “Request”Multipart form data:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
file |
file | Yes | — | Biometry report file |
biompin |
bool | No | false |
Generate a BiomPIN for secure sharing |
stream |
bool | No | false |
Return SSE progress events followed by the complete result or terminal error |
service_tier |
string | No | standard |
BiomAPI tier for PDF/images: standard or slow; ignored for JSON |
Headers:
| Header | Description |
|---|---|
Authorization: Bearer <key> |
Optional BiomAPI key — unlocks higher per-user rate limits |
X-Gemini-API-Key: <key> |
Optional BYOK Gemini key — uses your own Google quota |
X-BiomAPI-Integrator-ID: <id> |
Optional lowercase integration identifier used for operational attribution |
X-BiomAPI-Integrator-Origin: <origin> |
Optional integration origin; only its hostname is retained for operational attribution |
Integration headers identify your application for operational tracking. They are optional and declared by the caller. They do not authenticate the caller or change quotas.
Use a stable lowercase ID of up to 64 characters. Start with a letter or digit. Later characters may also include ., _, or -. BiomAPI retains only the origin hostname. The biomapi.* namespace is reserved by convention for official clients. The widget sets these headers automatically.
Optional progress stream
Section titled “Optional progress stream”Set stream=true to receive text/event-stream. The default remains a single JSON response.
Each SSE data field contains one JSON object:
type |
Fields | Meaning |
|---|---|---|
progress |
stage |
A processing phase from the table below |
heartbeat |
None | The connection is active; this does not measure model progress |
result |
result |
Complete, validated standard response, including BiomPIN when requested |
error |
status, body, retry_after |
Terminal failure; body uses the normal JSON error envelope and status carries its HTTP-equivalent status |
stage |
Meaning |
|---|---|
preparing |
Checking the request and preparing the uploaded report |
waiting |
Waiting for the next allowed provider attempt start |
processing |
Starting a provider attempt and awaiting its first content token |
retrying |
Scheduling another provider attempt |
receiving |
First nonempty content chunk received; collecting the remaining response |
validating |
Parsing and validating the complete extracted data, or uploaded JSON |
finalizing |
Preparing the API response and optional BiomPIN |
Stages describe observed work, not a percentage, remaining-time estimate, or guarantee of
success. A retry can return from receiving to retrying, processing, and receiving.
JSON inputs skip provider stages. Clients may group stages into simpler labels; the web app
shows receiving, validating, and finalizing as “Finalizing…”.
Progress events contain only the stage name. There are no token, reasoning, or partial clinical payloads in these events. Repeated states are suppressed and fast transitions may be coalesced. Upload status is measured by your client, before server events are available. The terminal result and error payloads retain their existing contracts; validation errors may include input details in the error body.
Heartbeat events are sent after five seconds without a stage update. Authentication and
multipart parsing can fail with a normal HTTP error before the stream starts. Once it
starts, HTTP 200 alone does not indicate success: require a terminal result event.
An error event or a connection ending without a terminal event is a failure. Do not
automatically resubmit interrupted extractions, because the original may have consumed a credit.
Streaming uses the same quota and retry rules as JSON responses. Each streaming provider
attempt has a total time limit, even when chunks continue arriving. Preprocessing, pacing,
and retries remain within the workflow limit. Canceling a stream stops request work where
possible; credits already reserved are retained.
BiomPIN generation
Section titled “BiomPIN generation”BiomPIN is off by default (biompin=false). Set biompin=true to request sharing details in the response. If share creation fails, processing can still succeed with biompin: null. For example, this can happen when the database is unavailable.
BYOK behavior
Section titled “BYOK behavior”If you supply X-Gemini-API-Key, extraction uses your Gemini quota for that request. BYOK overrides managed routing and uses the biomai_byok quota bucket. If your key fails, BiomAPI does not retry with a managed credential. BYOK has no effect on JSON uploads because BiomJSON does not call the LLM.
Standard and Slow processing
Section titled “Standard and Slow processing”service_tier=standard uses normal-priority processing and costs 1 BiomAI credit. service_tier=slow costs 0.5 credit and suits non-urgent work. Slow can take much longer. Keep the request open for the server’s configured Slow timeout.
The server can enable these recovery policies:
- Switch Slow to Standard after an eligible provider failure or when the reserved recovery window begins.
- Use Priority retries for Standard requests.
Clients can select only standard or slow. All retries keep the configured model. Recovery does not add BiomAPI credits. The total remains 1 credit for Standard or 0.5 credit for Slow.
On eligible retries, assigned credentials may switch to server-default credentials if that API key’s fallback policy is explicitly enabled. BYOK always keeps the supplied credentials. Google bills the account used for each attempt. For BYOK, this can include higher provider-tier charges.
With default timeouts, Standard has a 70-second workflow limit and a 30-second initial provider attempt. If Priority recovery is enabled, later attempts have half the initial limit: 15 seconds by default. Up to two deadline retries are allowed. Provider 499 CANCELLED and 504 DEADLINE_EXCEEDED responses share that allowance.
Retry delays, queueing, and preprocessing use the same workflow budget. Later attempts may have less time or may not start.
Slow has a 900-second workflow limit. If recovery is enabled, Flex can use up to the first 830 seconds, including preprocessing and queueing.
After the switch, Standard recovery has up to 70 seconds within the original 900-second deadline. Each provider attempt is capped at 30 seconds. Slow and Standard without Priority recovery keep one deadline retry. Recovery cannot guarantee success or extend the workflow deadline.
The selected tier is operational request data and is not added to extraction metadata or the StandardAPIResponse payload.
Rate limiting
Section titled “Rate limiting”Standard extraction costs 1 credit; Slow costs 0.5. JSON validation costs 1 credit after success. Extraction attempts can count even if they fail or time out. Check /api/v1/biom/usage for your allowance and credits and limits for the full rules.
Round-trip re-upload (JSON)
Section titled “Round-trip re-upload (JSON)”Upload a report inside a top-level data object, or a saved StandardAPIResponse. Bare reports are rejected with HTTP 422. For newly constructed BiomDIRECT data, you do not need to supply response metadata. See JSON input / BiomDIRECT for required objects, complete examples, and what BiomAPI adds.
Saved responses are revalidated, supported provenance is reconstructed, and response metadata is refreshed. Uploaded BiomPIN information is not reused. See re-uploading a saved response for details.
Posterior keratometry
Section titled “Posterior keratometry”BiomAI extracts explicitly printed posterior and total keratometry into extra_data for IOLMaster700 reports only; absent groups remain null. JSON input can supply these measurements independently of the core biometer. Notes are supplied through JSON or manual entry and are supported for any core biometer. See the extra-data schema.
Response
Section titled “Response”Example PDF/image extraction with biompin=true. All values and identifiers below are synthetic; the PIN is illustrative.
{ "data": { "biometer": { "device_name": "IOLMaster700", "manufacturer": "Zeiss" }, "exam_date": "2026-09-05", "patient": { "name": "SD", "id": "SYN-001", "date_of_birth": "1965-03-15", "gender": "Male" }, "right_eye": { "AL": 23.45, "ACD": 3.12, "K1_magnitude": 43.25, "K1_axis": 5, "K2_magnitude": 44.5, "K2_axis": 95, "WTW": 11.8, "LT": 4.52, "CCT": 545, "lens_status": "Phakic", "post_refractive": "None", "keratometric_index": 1.3375 }, "left_eye": { "AL": 23.52, "ACD": 3.08, "K1_magnitude": 43.0, "K1_axis": 175, "K2_magnitude": 44.25, "K2_axis": 85, "WTW": 11.9, "LT": 4.48, "CCT": 542, "lens_status": "Phakic", "post_refractive": "None", "keratometric_index": 1.3375 } }, "extra_data": null, "metadata": { "request_id": "3f5e3c51-d0b9-45fd-a7f4-6d7a3b592f42", "schema_version": "1.1.0", "app_version": "2.2.15", "extraction": { "method": "BiomAI", "timestamp": "2026-09-05T10:00:00Z", "byok": false, "llm": "gemini-3.8-flash", "input_schema_version": null } }, "biompin": { "pin": "lunar-rocket-731904", "expires_at": "2026-10-06T10:00:00Z", "db_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }}See Response Schema for the complete field reference.
When analytics is enabled, every successful BiomAI PDF/image extraction (including
BYOK) can be rated through POST /api/v1/biom/feedback.
Keep the original metadata.request_id for this purpose. No opt-in header or
additional processing parameter is needed. JSON processing is not eligible,
even if it preserves BiomAI extraction metadata.
Errors
Section titled “Errors”| Code | Condition |
|---|---|
400 |
Empty file, unsupported extension, invalid file content, or password-protected PDF |
422 |
JSON schema mismatch (major version) or Pydantic validation failure |
429 |
Rate limit exceeded for the applicable engine bucket |
500 |
Processing failed, including LLM extraction errors |
504 |
BiomAI extraction exceeded an attempt, recovery-phase, or workflow deadline, or exhausted recovery after a provider cancellation/deadline response; the error detail identifies the boundary |
POST /api/v1/biom/feedback
Section titled “POST /api/v1/biom/feedback”Submit an optional accuracy rating for a successful BiomAI extraction. Available to web-app and API clients when analytics is enabled. No API key is required and ratings do not consume extraction quotas.
Request
Section titled “Request”Send Content-Type: application/json and only these two fields (maximum body
size: 256 bytes):
{ "request_id": "3f5e3c51-d0b9-45fd-a7f4-6d7a3b592f42", "rating": "accurate"}The optional X-BiomAPI-Integrator-ID and X-BiomAPI-Integrator-Origin
headers are accepted for soft operational attribution. They do not change the
two-field JSON contract, feedback eligibility, or processing behavior.
request_id must be the original metadata.request_id returned by
POST /api/v1/biom/process for a PDF/image extraction. Do not use a retrieval
request ID. rating must be accurate or inaccurate.
Do not include files, extracted values, patient information, or contact text.
The biomai_feedback analytics event contains the submitted rating as
outcome (accurate or inaccurate), the feedback HTTP
request_id (matching its X-Request-ID response header), and the original
process_request_id, plus deployment environment and app version.
Availability and retries
Section titled “Availability and retries”References are eligible for up to 24 hours after processing, subject to a 10,000-entry process-local limit. Eviction or a server restart expires the reference. JSON validation, manual edits, and retrieval do not create eligible references.
The first rating is final. Resubmitting the same rating returns success without
emitting another event; submitting a different rating returns 409.
Response
Section titled “Response”{"success": true}Success means the rating was handed to the analytics SDK, not confirmation of
delivery to PostHog. A 503 leaves the reference unrated, so retrying is safe.
Errors
Section titled “Errors”| Code | Condition |
|---|---|
404 |
Unknown, ineligible, expired, or evicted extraction reference |
409 |
The extraction already has a different rating |
413 |
Request body exceeds 256 bytes |
415 |
Content-Type is not application/json |
422 |
Invalid JSON, request ID, rating, or extra fields |
503 |
Feedback analytics is temporarily unavailable |
GET /api/v1/biom/retrieve
Section titled “GET /api/v1/biom/retrieve”Retrieve encrypted biometry data using a BiomPIN code.
How it works
Section titled “How it works”Supply the complete BiomPIN to retrieve and decrypt its result. Retrieval reserves a credit before PIN validation and decryption. An accepted attempt therefore consumes a credit even if it fails. See BiomPIN for identity, encryption, and expiry.
Request
Section titled “Request”GET /api/v1/biom/retrieve?biom_pin=lunar-rocket-731904| Parameter | Required | Description |
|---|---|---|
biom_pin |
Yes | Full PIN including numeric suffix: word-word-123456 |
The optional Authorization, X-BiomAPI-Integrator-ID, and X-BiomAPI-Integrator-Origin headers are also accepted. The integration headers have the same soft-attribution behavior as on /process.
Browser integrations can use the Browser SDK for fragment consumption, sharing, browser-local history, and patient identifier context. Its BiomAPI.biompin.retrieve() helper performs public retrieval. Your application owns processing and authenticated retrieval requests.
Wrong PIN attempts
Section titled “Wrong PIN attempts”By default, three wrong numeric PINs against an existing share permanently delete it. The threshold request returns 429; subsequent requests return 404. This online protection cannot prevent guessing against a copied database.
Response
Section titled “Response”Retrieval returns the same StandardAPIResponse structure as /process. The stored result excludes patient initials and ID. Retrieval assigns a new metadata.request_id and keeps the extraction provenance and original BiomPIN expiry.
Responses use Cache-Control: no-store. Do not store them in persistent response caches.
Errors
Section titled “Errors”| Code | Condition |
|---|---|
400 |
PIN doesn’t match the word-word-123456 format |
404 |
PIN not found, already expired, or destroyed after too many wrong attempts |
422 |
Missing required biom_pin query parameter |
429 |
Retrieval quota exceeded, or this attempt destroyed the share after repeated wrong numeric PINs |
POST /api/v1/biom/export
Section titled “POST /api/v1/biom/export”Generate a ZIP archive in any combination of CSV, XLSX, and JSON formats.
This endpoint does not require authentication or apply rate limits. It converts supplied data without calling an LLM.
The server limits request body size and the number of responses in one export. If it returns 413, split the dataset into smaller exports. Send a Content-Length header; the server requires it before parsing JSON.
Archive contents
Section titled “Archive contents”| File | Description |
|---|---|
biomapi-export-YYYYMMDD-HHMMSS.csv |
Combined by-eye CSV of all results |
biomapi-export-YYYYMMDD-HHMMSS.xlsx |
Formatted workbook containing the same by-eye data |
biomapi-{patientId}-{device}.json |
One JSON file per report |
CSV and XLSX files contain two rows per report: one for the right eye (right_eye=1) and one for the left (right_eye=0). Each row includes exam, patient, device, anterior biometry, posterior keratometry, and total keratometry fields.
TK columns (tk1, tk1_axis, tk2, tk2_axis) follow the existing columns. PK and TK share pk_device_name. Missing TK values produce empty cells.
JSON filenames: BiomAPI converts data.patient.id to filename-safe text and combines it with data.biometer.device_name. If no patient ID is available, it uses the current date. It adds a numeric suffix to duplicate filenames in the same archive.
Request body
Section titled “Request body”formats accepts any non-empty combination of csv, xlsx, and json. It defaults to all three when omitted.
{ "responses": [ { "json_data": { "data": { "biometer": { "device_name": "IOLMaster700", "manufacturer": "Zeiss" }, "patient": {}, "right_eye": { "AL": 23.45 }, "left_eye": {} }, "extra_data": null, "metadata": { "request_id": "3f5e3c51-d0b9-45fd-a7f4-6d7a3b592f42", "schema_version": "1.1.0", "app_version": "2.2.15", "extraction": { "method": "BiomDIRECT", "timestamp": "2026-09-05T10:00:00Z", "input_schema_version": "1.0.0", "source_app": null, "source_version": null } }, "biompin": null }, "filename": "report.json" } ], "formats": [ "csv", "xlsx", "json" ]}The optional X-BiomAPI-Integrator-ID and X-BiomAPI-Integrator-Origin
headers are accepted for the same soft operational attribution used by process
and retrieve requests.
Response
Section titled “Response”application/zip file download.
Errors
Section titled “Errors”| Code | Condition |
|---|---|
400 |
Invalid Content-Length, empty response list, or empty formats array |
411 |
Missing Content-Length header |
413 |
Request body or response count exceeds the server limit |
422 |
Invalid request body, including missing fields or unsupported export formats |
500 |
Export generation failed |
GET /api/v1/biom/usage
Section titled “GET /api/v1/biom/usage”Returns current rate limit usage and API key validity for the caller.
This endpoint has no rate limit. It reads quota usage from persistent storage. If storage is unavailable, it returns HTTP 503 in the standard error response.
What it returns
Section titled “What it returns”Public callers see per-IP usage. Authenticated callers see per-user usage. The engines section shows used/limit/resets for all four engine buckets regardless of which ones have been used.
The keys section reports validity of the BiomAPI key (instant, in-memory check) and optionally the Gemini BYOK key.
Validating your Gemini key
Section titled “Validating your Gemini key”Pass ?validate=true to test the X-Gemini-API-Key header against the live Gemini API. This adds an external request. Without validate=true, the gemini entry reports only "provided": true. It does not check validity.
Request
Section titled “Request”GET /api/v1/biom/usageGET /api/v1/biom/usage?validate=true| Query parameter | Default | Description |
|---|---|---|
validate |
false |
Also validate X-Gemini-API-Key against Gemini API |
Response
Section titled “Response”The response reports used, limit, and resets_in_seconds for biomai, biomai_byok, biomjson, and retrieve. Public callers receive the deployment’s per-IP limits. Authenticated callers receive the quotas configured for their API key.
keys field details:
| Scenario | biomapi value |
gemini value |
|---|---|---|
| No keys provided | {"provided": false} |
{"provided": false} |
| BiomAPI key provided, valid | {"provided": true, "valid": true, "user_id": "..."} |
— |
| BiomAPI key provided, invalid | {"provided": true, "valid": false} |
— |
Gemini key provided, validate=false |
— | {"provided": true} |
Gemini key provided, validate=true, valid |
— | {"provided": true, "valid": true} |
Gemini key provided, validate=true, invalid |
— | {"provided": true, "valid": false} |
resets_in_seconds is the time until the oldest charge leaves the rolling window. At that point, some credits become available again. The whole allowance does not reset.
Errors
Section titled “Errors”| Code | Condition |
|---|---|
422 |
Invalid validate query parameter; a boolean value is required |
GET /api/v1/status
Section titled “GET /api/v1/status”Lightweight API status and deployment metadata. Public, no authentication required.
Use this endpoint for frequent polling when integrations need the BiomPIN database instance identifier. It does not call Gemini, open a database session, count BiomPIN records, or emit analytics.
Response
Section titled “Response”{ "status": "ok", "gemini_llm": "gemini-3.8-flash", "environment": "production", "app_version": "2.2.15", "schema_version": "1.1.0", "db_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}| Field | Description |
|---|---|
status |
Always "ok" if the API process can serve the request |
gemini_llm |
The Gemini model configured on the server |
environment |
Deployment environment |
app_version |
Running BiomAPI package version |
schema_version |
Current response schema version |
db_id |
BiomPIN database instance identifier |
Performance
Section titled “Performance”| Field | Cost |
|---|---|
db_id |
In-memory value initialized at startup; no per-request DB lookup |
environment, app_version, schema_version, gemini_llm |
Configuration/package metadata reads |
GET /api/v1/health
Section titled “GET /api/v1/health”Active health check. Public, no authentication required.
Use this endpoint for monitoring when you need live Gemini and database readiness. Avoid high-frequency polling because it may perform external API and database work.
Response
Section titled “Response”{ "status": "operational", "gemini_api_connected": true, "db_connected": true, "db_records": 42, "gemini_llm": "gemini-3.8-flash", "environment": "production", "app_version": "2.2.15", "schema_version": "1.1.0", "db_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}| Field | Description |
|---|---|
status |
"operational" (all healthy), "degraded" (one of Gemini/DB unavailable), "error" (both unavailable) |
gemini_api_connected |
Whether the server’s Gemini API key is valid and reachable; this may call Gemini and is cached for 60 seconds |
db_connected |
Whether the BiomPIN SQLite database manager is initialized |
db_records |
Total BiomPIN records from SELECT COUNT(*) FROM share |
gemini_llm |
The Gemini model configured on the server |
environment |
Deployment environment |
app_version |
Running BiomAPI package version |
schema_version |
Current response schema version |
db_id |
BiomPIN database instance identifier |
Web pages and documentation resources
Section titled “Web pages and documentation resources”These URLs remain accessible but are excluded from the OpenAPI schema and Swagger’s operation list. For browser workflows, see the Web App guide and Web Widget guide.
| Route | Description |
|---|---|
GET / |
Main web application (SPA) |
GET /pin/{biompin} |
Direct BiomPIN access — pre-fills the BiomPIN tab and auto-retrieves |
GET /widget |
Web app with the integrator handoff interface |
GET /browser-sdk-demo |
Browser SDK demo: widget, sharing, and fragment imports |
GET /docs/ |
This documentation site |
GET /apidocs |
Swagger UI (interactive API explorer) |
GET /openapi.json |
OpenAPI 3.1 schema for the public REST endpoints (powers Swagger UI) |
GET /llms.txt |
LLM-readable site index (also /llms-full.txt, /llms-small.txt) |
