Skip to main content
This feature is in beta. Behavior and availability may change as we expand support.
Use resource ingestion when you have clinical PDFs or related images (scans, screenshots, print-to-PDF notes) that should become structured logs in Olira. You label the target log type at upload time; Olira stores the binary, runs text extraction / OCR, then emits an event log that flows into patient state like any other submission. This path is for document binaries. For already-structured payloads, use live logging or historical JSONL backfill. For continuous sensor Parquet, use passive signal ingestion.

Supported materials

Max file size is 100 MB per document. You choose the clinical target — the platform does not infer log_type or document_type / note_type from the filename.

Target log types

document_type values (for unstructured_report): clinical_note, radiology_imaging, operative_procedure, cardiology_diagnostic, pathology_report, lab_report, genomic_report, discharge_summary, patient_intake, external_records_package. note_type values (for clinical_note): progress_note, history_and_physical, social_history, family_history, medical_history, surgical_history, psychosocial_history, financial_history, discharge_summary, consultation_note, other. Payload schemas: clinical note, unstructured report.

Processing modes

processing_mode decides how many event logs one file becomes.

Why segmented_notes exists

In single_document mode every fact extracted from a file inherits that file’s one timestamp. That is correct for a single note, and wrong for a document covering years: a scanned clinic folder spanning 2018→2025 would land every blood pressure, diagnosis, and prescription in it on one date, and patient state would read as though all of it happened at once. In segmented_notes mode the file is treated as a container, not an event. It carries no timestamp and produces no log of its own. Olira finds each dated encounter entry in the OCR text and emits one clinical_note per entry, timestamped from the date written in the document. Each note then runs extraction independently, so its vitals_measurement, medication, and condition children carry the right visit date. Requires log_type: clinical_note (with note_type + source, which apply to every emitted note).

Hints

Two optional fields make date inference safer. Both are hints, not guarantees, and both are only accepted in segmented_notes mode.
  • date_hints bounds the document’s clinical span (YYYY, YYYY-MM, or a full ISO date) and says whether dates are written day-first. The span disambiguates two-digit years and rejects an implausible reading; day_first settles 03/04 between 3 April and March 4th.
  • layout_hints says what each page holds, in page order, so a printed identity card or a blank end-of-folder leaf is recognised rather than absorbed into a note.

Held segments

A detected segment is held — not emitted — when its date cannot be resolved, falls outside date_hints, or goes backwards relative to the previous entry, and when its text is empty or implausibly long. Held segments never become logs, and every one is listed on GET /v1/documents/{id} with a hold_reason, alongside segments_detected / segments_emitted / segments_held and unassigned_chars (non-whitespace characters that belonged to no segment and no classified region). A rising unassigned_chars is the signal that a split is dropping content.

Pipeline

  1. Upload — request a presigned URL, PUT the file bytes (with matching Content-Type), then commit.
  2. Textize — for born-digital PDFs (Word→PDF, EHR print-to-PDF), Olira prefers the embedded text layer when quality checks pass (chars/page, letter ratio, nonempty pages).
  3. Vision OCR — scanned PDFs, sparse text layers, and images fall back to vision OCR.
  4. Segment — segmented_notes only: find each dated encounter entry and resolve its date.
  5. Emit — Olira writes the event log(s) and continues through the normal graph / extraction path.
There is no human confirmation on the live document path. Commit starts OCR immediately.

Two ways to send resources

Live upload (single document)

Best for ongoing document arrival from your backend. Requires sdk:event-log.
For a clinical-note target:
For a scanned multi-visit folder — note there is no timestamp:
Under the hood the SDK calls:
  1. POST /v1/documents:upload-url
  2. Presigned PUT of the binary
  3. POST /v1/documents/{id}:commit
  4. GET /v1/documents/{id} while you poll
Method reference: upload_document, get_document.

Historical package (bulk PDFs + logs)

Best for onboarding backfills that mix JSONL-style patient/log rows with PDF binaries. Requires sdk:historical-ingest.
The SDK allocates upload URLs (POST /v1/ingestion/jobs:begin), PUTs each PDF, builds a manifest.jsonl that includes type=document rows, then creates the historical job. After you confirm, OCR and document log materialization run inside the historical workflow before view backfill. See create_ingestion_job and Backfilling historical data for confirmation, cancel, and progress polling.

Document statuses

Terminal statuses: log_emitted, logs_emitted, ocr_failed, segmentation_failed. Individual segments being held is not a failure — a document with held segments still reaches logs_emitted. Check segments_held to see it.

What you need

  1. API key with sdk:event-log (live upload) or sdk:historical-ingest (package jobs).
  2. Patient already in your org (or created in the same historical package via patient rows).
  3. A PDF or supported image file, plus the correct log_type labels.
  4. A stable idempotency_key so retries do not create duplicate document resources. This is a separate key from the one on log_batch / log_fhir (log() has no key) — document uploads have their own idempotency scope.

After emit

Once status is log_emitted (or logs_emitted), treat the result like any other log: inspect it in Console observability, read it via state / log query APIs, and expect downstream extraction and view updates according to your org configuration. Re-using the same idempotency_key after a document already left pending_upload returns a conflict — pick a new key for a new file.