Data Import

Before a practitioner opens Tiro.health, import the clinical context of the report you want them to complete. This lets you pre-fill patient and encounter information so users never have to re-type it.

Data import is the first step of a Capture API integration. Your backend writes a small set of FHIR resources into your data tenant — typically in the background, ahead of the context launch — so that the report is ready to be filled in the moment the user arrives.


Overview

Data import uses the same FHIR API as the rest of the platform, hosted at https://reports.tiro.health/fhir/r5. You can create resources one at a time, but the recommended approach is a single transaction Bundle so that all resources are created atomically and can reference each other.

The goal of the import step is to represent one instruction: "this practitioner should complete this report for this patient." In FHIR terms that is a Task of type complete-questionnaire, pointing at a Patient, with the reporting Practitioner available as a user in the tenant.

Authentication required. All import requests are authenticated. See Authentication for how to obtain credentials.


Minimum Resources

At minimum you import three resources. Only the Patient is strictly required to start a report; importing the Practitioner and Task up front gives the practitioner a ready-to-open entry in their worklist.

ResourceRequiredPurpose
PatientYesThe subject of the report. A single identifier (system + value) is enough; name and other demographics are optional but improve the UI.
PractitionerYesThe clinician who will author the report. Importing them ensures they exist as a user in the tenant. A single identifier is enough.
TaskYesThe complete-questionnaire order that appears in the practitioner's worklist. References the Patient via for.
EncounterOptionalLinks the report to a specific visit. Referenced from the Task via encounter and carried onto the resulting QuestionnaireResponse.

POST/fhir/r5

Import as a Transaction

Post a transaction Bundle to the FHIR API root. Resources reference each other by fullUrl using urn:uuid: placeholders; Tiro.health resolves those to real IDs and rewrites the references for you, regardless of the order the entries appear in.

The Bundle below imports a Patient, a Practitioner, and a draft complete-questionnaire Task in one atomic operation. If any entry fails, the whole transaction is rolled back.

Because the Task's code.text becomes the title shown in the worklist, set it to something the practitioner will recognise (e.g. "CT scan report").

Import Bundle

POST
/fhir/r5
curl -X POST https://reports.tiro.health/fhir/r5 \
  -H "Authorization: Basic {{apikey}}" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Bundle",
    "type": "transaction",
    "entry": [
      {
        "fullUrl": "urn:uuid:patient-001",
        "resource": {
          "resourceType": "Patient",
          "identifier": [{
            "system": "http://hospital.example.com/patients",
            "value": "PAT-12345"
          }],
          "name": [{"family": "Smith", "given": ["John"]}]
        },
        "request": { "method": "POST", "url": "Patient" }
      },
      {
        "fullUrl": "urn:uuid:practitioner-001",
        "resource": {
          "resourceType": "Practitioner",
          "identifier": [{
            "system": "http://hospital.example.com/practitioners",
            "value": "PRAC-67890"
          }],
          "name": [{"family": "Jones", "given": ["Sarah"]}]
        },
        "request": { "method": "POST", "url": "Practitioner" }
      },
      {
        "fullUrl": "urn:uuid:task-001",
        "resource": {
          "resourceType": "Task",
          "intent": "order",
          "status": "draft",
          "identifier": [{
            "system": "http://hospital.example.com/tasks",
            "value": "TASK-54321"
          }],
          "description": "Complete the CT scan report for John Smith.",
          "code": {
            "text": "CT scan report",
            "coding": [{
              "system": "http://fhir.tiro.health/CodeSystem/task-type",
              "code": "complete-questionnaire"
            }]
          },
          "for": { "reference": "urn:uuid:patient-001" }
        },
        "request": { "method": "POST", "url": "Task" }
      }
    ]
  }'

Response (transaction-response)

{
  "resourceType": "Bundle",
  "type": "transaction-response",
  "entry": [
    { "response": { "status": "201 Created", "location": "Patient/1" } },
    { "response": { "status": "201 Created", "location": "Practitioner/1" } },
    { "response": { "status": "201 Created", "location": "Task/1" } }
  ]
}

Each response entry carries a location with the assigned ID. Store the Task location (Task/1) if you want to track the report's progress or fetch the result later.


Idempotent Imports

Because imports usually run in the background — and may run more than once for the same patient — use conditional create so repeated imports don't create duplicates. Add an ifNoneExist query on the entry: if a resource already matches, Tiro.health reuses it instead of creating a new one.

Conditional create entry

{
  "fullUrl": "urn:uuid:patient-001",
  "resource": {
    "resourceType": "Patient",
    "identifier": [{
      "system": "http://hospital.example.com/patients",
      "value": "PAT-12345"
    }]
  },
  "request": {
    "method": "POST",
    "url": "Patient",
    "ifNoneExist": "identifier=http://hospital.example.com/patients|PAT-12345"
  }
}

Alternatively, use a conditional update (PUT Patient?identifier=...) to upsert a resource — creating it if it does not exist, or updating the matching resource in place. The same pattern applies to Encounter and Practitioner. Matching is always done on the external identifier you provided, so make sure every resource carries a stable identifier from your system. See Linking resources to your internal identifiers.


What Happens Next

A complete-questionnaire Task moves through a short lifecycle as it is prepared and filled in:

  1. draft — imported without a questionnaire. The report is not yet ready to open.
  2. ready — a questionnaire (form template) has been attached, either through the API or by the practitioner choosing one in the UI.
  3. in-progress — the practitioner has started filling in the form.
  4. completed — the form has been submitted and processed.

You can attach the questionnaire yourself by including a questionnaire input on the Task, or let the practitioner pick a template when they open the report. See the Task reference for input types and lifecycle operations.

Once the context is imported, hand the user over to Tiro.health with a context launch, and retrieve the finished report through the Data Export step.

Was this page helpful?