Returns a LogQuery builder scoped to one patient.
POST
/
v1
/
state
/
{patient_id}
/
logs
/
query
import olira
from olira import F
olira.init(api_key="YOUR_API_KEY")
# Filter, order, limit
rows = (
olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.eq("type", "symptom_report")
.gt("payload.score", 4)
.order("timestamp", desc=True)
.limit(50)
.execute()
)
for row in rows:
print(row["timestamp"], row["payload"])
# .with_count() — total_count + has_more in one request (opt-in)
rows = (
olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.eq("type", "symptom_report")
.with_count()
.limit(50)
.execute()
)
print(rows.total_count, rows.has_more) # e.g. 5000, True
# Paginate through all matches (server cap: 1000/request)
offset, all_rows = 0, []
while True:
batch = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "symptom_report").limit(1000).offset(offset).execute()
all_rows.extend(batch.rows)
if len(batch) < 1000:
break
offset += 1000
# Other patterns
rows = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").or_(F("payload.score").gt(7), F("type").eq("mood_report")).limit(10).execute()
n = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "symptom_report").count()
row = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "demographics").order("timestamp", desc=True).limit(1).maybe_single()
using Olira;
OliraModule.Init(apiKey: "YOUR_API_KEY");
// Filter, order, limit
var rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "symptom_report")
.Gt("payload.score", 4)
.Order("timestamp", desc: true)
.Limit(50)
.Execute();
foreach (var row in rows)
Console.WriteLine($"{row["timestamp"]} {row["payload"]}");
// WithCount() — total_count + has_more in one request (opt-in)
rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "symptom_report")
.WithCount()
.Limit(50)
.Execute();
Console.WriteLine($"{rows.TotalCount} {rows.HasMore}"); // e.g. 5000, True
// Paginate through all matches (server cap: 1000/request)
var offset = 0;
var allRows = new List<Dictionary<string, object?>>();
while (true)
{
var batch = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").Eq("type", "symptom_report").Limit(1000).Offset(offset).Execute();
allRows.AddRange(batch.Rows);
if (batch.Count < 1000)
break;
offset += 1000;
}
// Other patterns
rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Or(new F("payload.score").Gt(7), new F("type").Eq("mood_report"))
.Limit(10)
.Execute();
var n = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").Eq("type", "symptom_report").Count();
var row = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "demographics")
.Order("timestamp", desc: true)
.Limit(1)
.MaybeSingle();
POST /v1/state/8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82/logs/query
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"filter": [
{"field": "type", "op": "eq", "value": "symptom_report"},
{"field": "payload.score", "op": "gt", "value": 4}
],
"order": [{"field": "timestamp", "desc": true}],
"limit": 25
}
LogQueryResult(
count=3,
rows=[
{"id": "log-1", "type": "symptom_report", "timestamp": "2026-01-14T12:00:00Z", "payload": {"score": 7}},
{"id": "log-2", "type": "symptom_report", "timestamp": "2026-01-13T09:00:00Z", "payload": {"score": 5}},
{"id": "log-3", "type": "symptom_report", "timestamp": "2026-01-12T08:00:00Z", "payload": {"score": 6}},
],
patient_id="8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82",
organization_id=None,
)
{
"error": true,
"status_code": 401,
"error_type": "authentication_error",
"message": "Could not validate credentials",
"details": [
{
"type": "authentication_error",
"message": "Could not validate credentials"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 403,
"error_type": "authorization_error",
"message": "Insufficient OAuth scope for this endpoint",
"details": [
{
"type": "authorization_error",
"message": "Insufficient OAuth scope for this endpoint"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 404,
"error_type": "not_found_error",
"message": "Patient not found",
"details": [
{
"type": "not_found_error",
"message": "Patient not found"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 422,
"error_type": "validation_error",
"message": "Request validation failed (1 error)",
"details": [
{
"type": "missing",
"message": "Field required",
"field": "patient_id",
"location": ["body", "patient_id"],
"input_value": null
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 429,
"error_type": "server_error",
"message": "Rate limit exceeded",
"details": [
{
"type": "rate_limit",
"message": "Too many requests; retry after backoff"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 500,
"error_type": "internal_server_error",
"message": "An internal server error occurred",
"details": [
{
"type": "internal_server_error",
"message": "An unexpected error occurred while processing your request"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
olira.logs(patient_id: str) -> LogQueryResult
OliraModule.Logs(string patientId) // -> LogQueryResult
sdk:state-read
Chain filter, projection, ordering, and aggregation methods, then call a terminal to run: .execute() → LogQueryResult, .count() → int, .single() / .maybe_single() → dict. Filter paths must be rooted at type, timestamp, ingested_at, trace, or payload — other roots return 422. Add .with_count() to include total_count and has_more in the response (one extra server-side COUNT op, opt-in). Server cap: limit ≤ 1000 per request — paginate with .limit(1000).offset(n) for larger result sets.
Parameters
str
required
Olira patient id.
Returns
LogQueryResult — Iterable, indexable result. Call .as_logs() to parse rows into typed LogEntry when no .select() was used.
int
Rows returned in this page.
list[dict]
Projected or raw log dicts.
int | None
Total matching rows across all pages. Only set when .with_count() was used.
bool | None
True when more rows exist beyond this page. Only set when .with_count() was used.
str | None
Echo of the queried patient id.
str | None
Set on population queries.
Raises
| Exception | When |
|---|---|
ValidationError | Unknown operator (client-side check), or HTTP 422 from the server (invalid field root, unsupported op, limit > 1000). |
AuthError | HTTP 401 or 403 — invalid API key or insufficient OAuth scope for this endpoint. |
ServerError | HTTP 409 (e.g. conflicting external identifier) or repeated 5xx after retries; includes status_code when applicable. |
RateLimitError | HTTP 429 — rate limited; check retry_after (seconds). |
NetworkError | Connection timeout, DNS failure, or read error after retries. |
import olira
from olira import F
olira.init(api_key="YOUR_API_KEY")
# Filter, order, limit
rows = (
olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.eq("type", "symptom_report")
.gt("payload.score", 4)
.order("timestamp", desc=True)
.limit(50)
.execute()
)
for row in rows:
print(row["timestamp"], row["payload"])
# .with_count() — total_count + has_more in one request (opt-in)
rows = (
olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.eq("type", "symptom_report")
.with_count()
.limit(50)
.execute()
)
print(rows.total_count, rows.has_more) # e.g. 5000, True
# Paginate through all matches (server cap: 1000/request)
offset, all_rows = 0, []
while True:
batch = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "symptom_report").limit(1000).offset(offset).execute()
all_rows.extend(batch.rows)
if len(batch) < 1000:
break
offset += 1000
# Other patterns
rows = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").or_(F("payload.score").gt(7), F("type").eq("mood_report")).limit(10).execute()
n = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "symptom_report").count()
row = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "demographics").order("timestamp", desc=True).limit(1).maybe_single()
using Olira;
OliraModule.Init(apiKey: "YOUR_API_KEY");
// Filter, order, limit
var rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "symptom_report")
.Gt("payload.score", 4)
.Order("timestamp", desc: true)
.Limit(50)
.Execute();
foreach (var row in rows)
Console.WriteLine($"{row["timestamp"]} {row["payload"]}");
// WithCount() — total_count + has_more in one request (opt-in)
rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "symptom_report")
.WithCount()
.Limit(50)
.Execute();
Console.WriteLine($"{rows.TotalCount} {rows.HasMore}"); // e.g. 5000, True
// Paginate through all matches (server cap: 1000/request)
var offset = 0;
var allRows = new List<Dictionary<string, object?>>();
while (true)
{
var batch = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").Eq("type", "symptom_report").Limit(1000).Offset(offset).Execute();
allRows.AddRange(batch.Rows);
if (batch.Count < 1000)
break;
offset += 1000;
}
// Other patterns
rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Or(new F("payload.score").Gt(7), new F("type").Eq("mood_report"))
.Limit(10)
.Execute();
var n = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").Eq("type", "symptom_report").Count();
var row = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "demographics")
.Order("timestamp", desc: true)
.Limit(1)
.MaybeSingle();
POST /v1/state/8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82/logs/query
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"filter": [
{"field": "type", "op": "eq", "value": "symptom_report"},
{"field": "payload.score", "op": "gt", "value": 4}
],
"order": [{"field": "timestamp", "desc": true}],
"limit": 25
}
LogQueryResult(
count=3,
rows=[
{"id": "log-1", "type": "symptom_report", "timestamp": "2026-01-14T12:00:00Z", "payload": {"score": 7}},
{"id": "log-2", "type": "symptom_report", "timestamp": "2026-01-13T09:00:00Z", "payload": {"score": 5}},
{"id": "log-3", "type": "symptom_report", "timestamp": "2026-01-12T08:00:00Z", "payload": {"score": 6}},
],
patient_id="8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82",
organization_id=None,
)
{
"error": true,
"status_code": 401,
"error_type": "authentication_error",
"message": "Could not validate credentials",
"details": [
{
"type": "authentication_error",
"message": "Could not validate credentials"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 403,
"error_type": "authorization_error",
"message": "Insufficient OAuth scope for this endpoint",
"details": [
{
"type": "authorization_error",
"message": "Insufficient OAuth scope for this endpoint"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 404,
"error_type": "not_found_error",
"message": "Patient not found",
"details": [
{
"type": "not_found_error",
"message": "Patient not found"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 422,
"error_type": "validation_error",
"message": "Request validation failed (1 error)",
"details": [
{
"type": "missing",
"message": "Field required",
"field": "patient_id",
"location": ["body", "patient_id"],
"input_value": null
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 429,
"error_type": "server_error",
"message": "Rate limit exceeded",
"details": [
{
"type": "rate_limit",
"message": "Too many requests; retry after backoff"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 500,
"error_type": "internal_server_error",
"message": "An internal server error occurred",
"details": [
{
"type": "internal_server_error",
"message": "An unexpected error occurred while processing your request"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
⌘I
import olira
from olira import F
olira.init(api_key="YOUR_API_KEY")
# Filter, order, limit
rows = (
olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.eq("type", "symptom_report")
.gt("payload.score", 4)
.order("timestamp", desc=True)
.limit(50)
.execute()
)
for row in rows:
print(row["timestamp"], row["payload"])
# .with_count() — total_count + has_more in one request (opt-in)
rows = (
olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.eq("type", "symptom_report")
.with_count()
.limit(50)
.execute()
)
print(rows.total_count, rows.has_more) # e.g. 5000, True
# Paginate through all matches (server cap: 1000/request)
offset, all_rows = 0, []
while True:
batch = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "symptom_report").limit(1000).offset(offset).execute()
all_rows.extend(batch.rows)
if len(batch) < 1000:
break
offset += 1000
# Other patterns
rows = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").or_(F("payload.score").gt(7), F("type").eq("mood_report")).limit(10).execute()
n = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "symptom_report").count()
row = olira.logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").eq("type", "demographics").order("timestamp", desc=True).limit(1).maybe_single()
using Olira;
OliraModule.Init(apiKey: "YOUR_API_KEY");
// Filter, order, limit
var rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "symptom_report")
.Gt("payload.score", 4)
.Order("timestamp", desc: true)
.Limit(50)
.Execute();
foreach (var row in rows)
Console.WriteLine($"{row["timestamp"]} {row["payload"]}");
// WithCount() — total_count + has_more in one request (opt-in)
rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "symptom_report")
.WithCount()
.Limit(50)
.Execute();
Console.WriteLine($"{rows.TotalCount} {rows.HasMore}"); // e.g. 5000, True
// Paginate through all matches (server cap: 1000/request)
var offset = 0;
var allRows = new List<Dictionary<string, object?>>();
while (true)
{
var batch = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").Eq("type", "symptom_report").Limit(1000).Offset(offset).Execute();
allRows.AddRange(batch.Rows);
if (batch.Count < 1000)
break;
offset += 1000;
}
// Other patterns
rows = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Or(new F("payload.score").Gt(7), new F("type").Eq("mood_report"))
.Limit(10)
.Execute();
var n = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82").Eq("type", "symptom_report").Count();
var row = OliraModule.Logs("8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82")
.Eq("type", "demographics")
.Order("timestamp", desc: true)
.Limit(1)
.MaybeSingle();
POST /v1/state/8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82/logs/query
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"filter": [
{"field": "type", "op": "eq", "value": "symptom_report"},
{"field": "payload.score", "op": "gt", "value": 4}
],
"order": [{"field": "timestamp", "desc": true}],
"limit": 25
}
LogQueryResult(
count=3,
rows=[
{"id": "log-1", "type": "symptom_report", "timestamp": "2026-01-14T12:00:00Z", "payload": {"score": 7}},
{"id": "log-2", "type": "symptom_report", "timestamp": "2026-01-13T09:00:00Z", "payload": {"score": 5}},
{"id": "log-3", "type": "symptom_report", "timestamp": "2026-01-12T08:00:00Z", "payload": {"score": 6}},
],
patient_id="8a4fde23-0f1b-4c2a-9d7e-b36c1a5f0e82",
organization_id=None,
)
{
"error": true,
"status_code": 401,
"error_type": "authentication_error",
"message": "Could not validate credentials",
"details": [
{
"type": "authentication_error",
"message": "Could not validate credentials"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 403,
"error_type": "authorization_error",
"message": "Insufficient OAuth scope for this endpoint",
"details": [
{
"type": "authorization_error",
"message": "Insufficient OAuth scope for this endpoint"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 404,
"error_type": "not_found_error",
"message": "Patient not found",
"details": [
{
"type": "not_found_error",
"message": "Patient not found"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 422,
"error_type": "validation_error",
"message": "Request validation failed (1 error)",
"details": [
{
"type": "missing",
"message": "Field required",
"field": "patient_id",
"location": ["body", "patient_id"],
"input_value": null
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 429,
"error_type": "server_error",
"message": "Rate limit exceeded",
"details": [
{
"type": "rate_limit",
"message": "Too many requests; retry after backoff"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}
{
"error": true,
"status_code": 500,
"error_type": "internal_server_error",
"message": "An internal server error occurred",
"details": [
{
"type": "internal_server_error",
"message": "An unexpected error occurred while processing your request"
}
],
"timestamp": "2026-05-06T12:00:00+00:00"
}

