> ## Documentation Index
> Fetch the complete documentation index at: https://docs.olira.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging from your codebase

> Wire your backend to the Olira Python SDK: initialize the client, register patients, and emit logs that drive patient state.

This guide assumes your **organization, event types, and API keys** are already configured (Console and/or CLI; see [Setup](/setup)). Here we wire **your codebase** to the Olira Python SDK: initialize the client, register one or many patients, and emit **logs** that drive patient state.

## Install tooling

**CLI** (optional: keys, login, MCP config):

```bash theme={null}
brew install olira-ai/tap/olira
# or: curl -fsSL https://install.olira.ai | sh
```

**Python SDK** (required for ingestion from your backend):

```bash theme={null}
pip install olira
# or: uv add olira
```

## Authenticate in your service

Use an API key with at least **`sdk:event-log`** and **`api:manage-patients`** for creating patients and logging. Create the key in the Console or with `olira keys create` (see the [CLI key commands](/cli/keys)). Store it in a secret manager and pass it at runtime:

```python theme={null}
import os
import olira

olira.init(api_key=os.environ["OLIRA_API_KEY"])
# or set OLIRA_API_KEY and call olira.init()
```

## Initialize the SDK and create patients

### Single patient

```python theme={null}
patient = olira.create_patient(
    first_name="Ada",
    last_name="Example",
    email="ada@example.com",
    external_identifiers=[{"system": "mrn", "value": "MRN-12345"}],
)
patient_id = patient.id
```

### Multiple patients

Use **`create_patients_batch`** to register up to **500** patients in one `POST /v1/patients/batch` call. Pass a list of **`CreatePatientRequest`** objects; the response is a **`PatientBatchResult`** with **`items`** (successes, each with `index` and `id`) and **`errors`** (failures per index); partial success is supported.

```python theme={null}
from olira import CreatePatientRequest, ExternalIdentifier

result = olira.create_patients_batch([
    CreatePatientRequest(
        first_name=row["first_name"],
        last_name=row["last_name"],
        email=row.get("email"),
        external_identifiers=[ExternalIdentifier(system="mrn", value=row["mrn"])],
    )
    for row in enrollment_rows
])
for item in result.items:
    # item.index → position in input list, item.id → Olira patient id
    ...
for err in result.errors:
    # err.index, err.code, err.message: handle or retry failed rows
    ...
```

Build the request list from a comprehension, a CSV import, or any iterator. For a **single** registration you can still use **`create_patient`**. Anchor rules and field shapes match **`CreatePatientRequest`** in the [Python SDK reference](/reference/sdk).

## Log data

Use `olira.log()` or `olira.log_batch()` to send structured logs: an `OliraLogType` and a payload that matches each log type (see the [log types catalog](/reference/log-types/symptom-reports)). Use the correct **`patient_id`** for each log, whether you run one patient or many.

```python theme={null}
from olira import OliraLogType

olira.log(
    log_type=OliraLogType.SYMPTOM_REPORT,
    patient_id=patient_id,
    payload={"instrument": "esas_r", "symptoms": [{"name": "pain", "score": 3}]},
)
olira.flush()
```

Optional **`OliraTrace`** links a log to an object in your system (conversation id, questionnaire id, etc.) for provenance in observability and when reading state later.

## Verify ingestion

When your organization has observability enabled, use **Observability → Logs** and **Events** in the Console, and **Patient detail** to confirm modules and views update as expected. See [Console observability](/console/observability).
