Data & World Model
Event-sourced world model with confidence scoring, entity graphs, enrichment, entity intelligence, and structured query endpoints.
The Platform API provides access to a unified, event-sourced world model that aggregates entities, events, and relationships from all connected systems: EHRs, voice conversations, manual imports, and AI enrichment. Every piece of data flows through a single event store, and entity state is always a computed projection of events.
Conceptual overview. For the design rationale behind the world model - why event sourcing, how confidence-based truth works, and how agents read and write during conversations - see the World Model conceptual documentation. This page covers the API surface.
Different from Classic API data access. The Classic API provides SQL access to organization-scoped relational tables. The Platform API uses an event-sourced world model that unifies data from multiple sources (EHR, voice, imports) with confidence scoring.
Design Thesis
The world model rests on a small set of invariants that shape every endpoint on this page:
Events are the only source of truth. Entity state is always a computed projection from events. There is no direct mutation path: the only way to change state is
insert event -> recompute projection.Events are append-only and immutable. New information creates a new event that supersedes the old one. The old event stays for audit, temporal debugging, and undo.
Entity state is a pure function of events. Same events, same state. Concurrent recomputation is safe because the projection is deterministic.
Confidence resolves conflicts, not timestamps. When two sources disagree, the projection takes the highest-confidence data. Within the same confidence class, most recent wins.
Open schema.
entity_typeandevent_typeare free-form text, not enums. New kinds of entities and observations require no schema migration.
Event Sourcing Model
Every fact in the system (a patient's name, an appointment booking, an insurance verification, an agent-produced insight) is stored as an immutable event with a confidence score:
entity_type
What kind of entity (free-form text: patient, appointment, practitioner, location, call, etc.)
event_type
What happened (free-form text: patient.created, appointment.booked, coverage.verified, etc.)
data
Event payload (structured data, FHIR resources, agent observations, etc.)
confidence
Reliability score (0.0-1.0) that determines projection priority and sync eligibility
source
Origin system (voice_agent, connector_runner, ehr_sync, transcript_extraction, etc.)
is_current
Whether this is the latest version (managed by storage layer on supersede)
effective_at
When the fact was true in the real world
review_status
Review state (e.g. auto_approved, approved, rejected, flagged)
Confidence as Trust Architecture
Every event carries a confidence score that determines its reliability, downstream behavior, and sync eligibility:
Authoritative
1.0
From source system or human-corrected
Yes (auto)
EHR API, manual entry, human correction
Human-approved
0.95
Confirmed by a human reviewer
Yes (auto)
Human review approval
High
0.9
Operator-verified or high-quality adapter data
Yes (auto)
Operator verification, trusted adapter
EHR-trusted
0.8
Trusted EHR clinical data
Yes (auto)
EHR clinical records
Verified
0.7
LLM-verified or EHR-ingested data
Yes (auto)
LLM verification pass, EHR ingestion
Self-report
0.5
Patient-submitted data, partially corroborated
No
Patient-submitted form data
Agent-raw
0.3
Raw agent inference, unverified
No
Raw voice agent write
Rejected
0.0
Discarded or explicitly rejected
Never
Junk call, hallucination
Confidence scores resolve conflicts in projections: if two events disagree about a patient's phone number, the higher-confidence one wins. Among equal confidence, the most recent one wins.
Why continuous confidence, not binary staging: binary (draft/production) forces a hard cutover. With continuous confidence, different consumers set their own thresholds: the voice agent trusts its own writes at any confidence (session-scoped), the world model API serves data above a minimum threshold, outbound sync requires verified+, and researchers can query everything. One store, many views.
See Voice Agent, Confidence-Gated Writes for how voice agent writes progress through the confidence pipeline.
Supersedes Chain
When a new event replaces an older one (e.g., updating a patient's phone number), the new event references the old one via supersedes. The storage layer sets is_current=false on the superseded event. Projections only consider current events, ensuring state is always up-to-date while maintaining the full history for audit.
How Agents Read and Write
Agents interact with the world model through three channels:
Ambient (pushed): data the agent should always have - caller identity, patient state, related entities, location context - is injected into the system prompt and refreshed as the conversation evolves.
Queried (pulled): data whose search space is too large to push - slot search, patient lookup, entity search - is retrieved through tool calls that return human-readable results.
Extracted (captured): structured data the agent expresses in conversation (insurance details, contact info, preferences) is captured by a parallel extraction listener and written at moderate confidence, below the verified threshold. Explicit write tools remain for high-stakes data.
The World Model conceptual documentation covers the design rationale for this split and how it evolves as models improve.
Entity Types
The world model supports an open-ended set of entity types. entity_type is free-form text, not an enum. No schema migration is needed to add new types. An agent discovering a new kind of entity creates events with the new type, and the system handles it.
person
Any individual in the system
Patient (demographics, conditions, medications, insurance), practitioner (profile, NPI, specialty), operator (availability, performance). A single person entity can hold multiple roles; the projection detects roles from event data.
organization
A company or healthcare organization
Practice, payer, employer. Name, contacts, identifiers
place
A physical site
Clinic, hospital, office. Address, phone, hours, status
appointment
A scheduled visit
Status, participants, times, cancellation, confirmation
deal
A business opportunity or engagement
Status, pipeline stage, value, contacts
call
A voice conversation
Context, escalation history, safety state, human segments, audit
outbound_task
A scheduled outreach task
Lifecycle, retry state, scheduling, dispatch history
FHIR resource types on events (Patient, Practitioner, Location, etc.) stay unchanged. The ontological type applies at the entity level, while FHIR types describe the data format of individual events.
Typed Entity Response Fields
Entity API responses include typed top-level fields for common attributes, promoted from the projected entity state. These fields are available on all entity types. Fields that do not apply to a given entity type return null.
name
string
Person, organization
phone
string (E.164)
Person, organization
email
string
Person, organization
birth_date
string (YYYY-MM-DD)
Person (patient)
gender
string
Person (patient)
mrn
string
Person (patient)
status
string
All entity types
source
string
All entity types
appointment_status
string
Appointment
appointment_start
datetime
Appointment
appointment_end
datetime
Appointment
appointment_type
string
Appointment
domain
string
Organization
industry
string
Organization
direction
string
Call
duration_seconds
float
Call
call_sid
string
Call
The state field (object containing the full projected state) is deprecated. Use the typed fields above instead. The state field will continue to be returned for backward compatibility but may be removed in a future version.
Entity Enrichment
Entities can carry arbitrary per-key attributes beyond the typed response fields. Enrichment values are first-class, source-attributed, confidence-scored events, not an opaque blob on the entity. Each write produces an entity.enriched event that participates in the same supersedes chain and confidence resolution as every other world model event.
Registry-Governed Keys
Every workspace maintains a registry of enrichment keys. A key is scoped to a specific (entity_type, key) pair and declares:
value_type: one ofstring,number,boolean,date,enum,json.allowed_values: required whenvalue_type=enum.min_confidence: floor on write confidence; writes below this are rejected.is_pii: marks the attribute for downstream PII handling.source_hint,description: free-form text for admins.
Writes against an unregistered key are rejected with 400. Agent-extracted values whose key is not registered are silently dropped, so they do not pollute the event stream or compete with governed values. This gives admins full control over which attributes are tracked without blocking agent-side capture.
key and value_type are immutable after registration; create a new key and migrate if those need to change. Deleting a registered key does not delete historical entity.enriched events (the audit trail is preserved); only future writes are rejected.
Winner Selection and Audit
Reads return the current winner per (entity, key), one row with full provenance (value, value type, confidence, source, source system, effective time, ingested time, event ID). Winners are selected by confidence class (authoritative > human-approved > AI-verified > uncertain) with recency as the tiebreaker, the same resolution that governs every other world model projection.
The supersedes chain for any key is queryable for audit and temporal debugging. Each historical entry carries the full provenance plus supersedes (pointer to the event it replaced) and is_current (whether it is still the winner).
Unified Write Path
The same write path handles manual admin edits, connector backfills, form submissions, and agent-extracted captures, differentiated only by source and confidence. Validation errors (unknown key, wrong value type, enum miss, sub-floor confidence) all return 400 with a specific message.
All writes and registry mutations require the admin role or above (Workspace:Update). See the API Reference below for the full endpoint contract.
Entity Graph
Entities are connected by directed relationship edges, discovered automatically from data:
Relationships are discovered from:
Reference parsing: automatically extracted during entity resolution (e.g., Appointment.participant -> Patient).
Explicit events:
relationship.establishedevents created by connectors or agents.Agent discovery: autonomous agents identify relationships through data analysis.
Relationships are themselves events: discoverable, versioned, and confidence-scored.
Agent-Produced Knowledge
Agents analyze incoming data and produce derived events: insights, correlations, predictions, corrections. These derived events live in the same event store as raw data, linked to their source evidence, so other agents can read and act on them - closing the loop between observation and action.
Data Sources
External data feeds that push or pull data into the workspace:
continuous
Polled on a frequent interval
EHR patient updates
scheduled
Polled on a cron schedule
Daily reporting
manual
Only synced via explicit API trigger
One-time imports
webhook
Receives push events (no polling)
Real-time notifications
Each data source supports status checks, sync history, and health monitoring. The connector runner manages the full lifecycle of data source polling and sync.
The data sources list endpoint accepts repeatable source_type query parameters for filtering by multiple source types in a single request (e.g., ?source_type=ehr&source_type=smart_fhir).
Self-Service Secret Provisioning
For smart_fhir data sources, the create and update endpoints support inline secret provisioning. Pass private_key_value in the connection_config and the API automatically provisions the key to secure storage, storing only a secure secret-store reference in the data source record. API responses redact all secret fields (*_value, *_pem, *_secret, *_password) and mask the stored secret reference. No manual secret provisioning is needed when connecting SMART-compliant EHR systems.
Raw Records
Source records that cannot yet be mapped into the unified entity model are still captured: the connector runner stores them as raw events carrying the original record payload (with a .raw event type). Data is never lost, just not yet unified.
Data Quality Pipeline
Data quality is a pipeline, not a gate. Every piece of data carries a confidence level, and different consumers read at different confidence thresholds:
Capture at source-appropriate confidence. Connector-runner writes from authoritative systems land at authoritative confidence; agent-extracted conversation data lands at moderate confidence; raw agent inference lands at agent-raw confidence.
Verification raises confidence. Verified data becomes sync-eligible; human approval or correction produces a new, higher-confidence event that supersedes the original.
Outbound sync is gated on confidence. Only events at verified confidence or above are eligible to sync to external systems. The connector runner enforces this multi-layer confidence gate before any data reaches production EHR systems.
Proposed writes to external systems can additionally be routed through human review as external write proposals before they execute - see Review Queue.
Entity Narrative Briefs
AI-generated narrative summaries of a patient entity's world model data. The platform reads the last 90 days of events, synthesizes them into a structured narrative, and persists the result as a world model event for fast retrieval.
Generate a brief on demand with POST /v1/{workspace_id}/entities/{entity_id}/brief. The response includes the narrative in both Markdown and structured JSON, evidence pointers (event IDs that informed the narrative), a confidence score (0.0-1.0), the event count, and a prompt version identifier. Returns 404 if the entity is not one of these types (patient, cohort, territory, emirate, district) or does not exist.
Retrieve the latest cached brief with GET /v1/{workspace_id}/entities/{entity_id}/brief. Cache misses fall through to the event store and repopulate the cache transparently. When no brief has been generated, the response returns a consistent empty shape (null event_id and content fields) rather than a 404.
Briefs are scoped to patient, cohort, territory, emirate, and district entities. Permissions: viewer+.
Entity Intelligence
Read endpoints for exploring individual entities: their relationship graph, data provenance, full lineage, suspected duplicates, and search.
GET /v1/{workspace_id}/world/entities/{entity_id}/graph. One-level relationship graph.
Returns center (entity metadata), edges[] (edge type, confidence), and neighbors[] (entity metadata for connected nodes). Responds with 404 if the entity is not found.
GET /v1/{workspace_id}/world/entities/{entity_id}/provenance. Data provenance and confidence history.
Returns sources[] (contributing data sources), confidence_history[] (score over time), and merge_history[] (entity resolution events). Responds with 404 if the entity is not found.
GET /v1/{workspace_id}/world/entities/{entity_id}/lineage. Full data lineage. Responds with 404 if the entity is not found.
The response contains the same sources, confidence_history, and merge_history sections as the provenance endpoint, plus outbound_sinks and review_history keys that are currently always empty arrays (kept for wire stability). For per-sink outbound sync status, use GET /world/sync/by-sink.
GET /v1/{workspace_id}/world/entities/duplicates. Suspected duplicate entities.
entity_type
string
-
Filter by entity type
confidence_max
float (0-1)
1.0
Max confidence threshold
Returns historical same_as merge edges sorted by ascending confidence (lowest means most uncertain). New same_as edges are no longer written; the results reflect previously recorded merges.
GET /v1/{workspace_id}/world/search. Enhanced entity search.
q
string
Required
Search text (case-insensitive substring match on display name)
entity_type
string
-
Filter by entity type
source
string
-
Filter by event source
confidence_min
float (0-1)
-
Min confidence threshold
limit
integer (1-100)
20
Page size
offset
integer
0
Pagination offset
Returns results[] + total count.
Permissions: viewer+.
World Sync Status
GET /v1/{workspace_id}/world/sync/by-sink. Per-sink outbound sync summary.
Shows multi-sink outbound sync progress for workspaces with multiple outbound sinks. The endpoint takes no query parameters and returns sinks[], one entry per outbound data source:
data_source_id
string (UUID)
The outbound data source (sink)
name
string
Sink display name
source_type
string
Sink type
total
integer
Total outbound-eligible events for this sink
synced
integer
Events successfully synced
failed
integer
Events that failed to sync
pending
integer
Events awaiting sync
Generic Data Query
A structured query endpoint provides flexible table access with REST-style filter syntax:
Filter operators: eq, neq, gt, gte, lt, lte, like, ilike, in, is
Other parameters: select=col1,col2, order=col.asc, limit=100 (max, default 20), offset=0
Security: column whitelist per table, hidden sensitive columns, workspace isolation enforced server-side, maximum 100 rows per request.
API Reference
Last updated
Was this helpful?

