For the complete documentation index, see llms.txt. This page is also available as Markdown.

Surfaces

Agent-generated data collection interfaces: SurfaceSpec, fields, channels, lifecycle, and submission handling.

Surfaces are agent-generated data collection interfaces delivered to patients through existing communication channels. Agents analyze entity state and data gaps in the world model, generate a SurfaceSpec, and the platform renders and delivers it. Submissions flow back as world model events through standard confidence gates and review.

Conceptual overview. For the architecture, healthcare examples, and design rationale, see Surfaces in the conceptual docs.

Voice Agent Surface Tools

A family of context graph tools allows voice agents to create and manage surfaces during live calls:

Tool
Parameters
Returns

create_surface

entity_id (required), title (required), fields (required, list), description, channel, expires_in_hours, resource_type, context

surface_id, url, status, expires_at

create_surface_from_template

template_id (required), entity_id (required)

surface_id, url, status, prefilled_count, total_fields. Resolves a form template against the patient's entity state, prefilling fields with known data.

get_form_templates

optional category, patient_type filters

Reusable form templates for the workspace

deliver_surface

surface_id (required), channel_address (required: phone number or email)

surface_id, url, status

check_surface_status

surface_id (required)

surface_id, status, title, fields_count, entity_id, created_at

get_surface_progress

surface_id (required)

Field-level completion status (which fields are filled vs empty)

reshape_surface

surface_id (required)

New surface_id and url containing only the unfilled fields from an abandoned form

list_entity_surfaces

entity_id (required), status (optional filter)

surfaces[] (id, title, status, channel, created_at), count

get_surface_insights

entity_id (required)

entity_id, completion_rate, preferred_channel, total_surfaces, completed, pending_surfaces, recent_surfaces[]

extract_surface_file_text

surface_id (required)

Readable text extracted from submitted PDF file fields

get_surface_insights queries the entity's surface analytics before creating new surfaces. Returns completion rate, preferred channel, and count of pending (unfinished) surfaces. Call this before create_surface to avoid surface fatigue: if a patient already has multiple pending surfaces or a low completion rate, the agent may choose to collect data verbally instead.

These tools proxy through the Platform API surface endpoints. Authentication uses the call's agent_session JWT, which is workspace-scoped, so surface operations are automatically isolated to the correct workspace.

All of these tools handle errors gracefully: if the Platform API is unreachable, the agent receives an error message rather than an exception, so it can continue the call.

Permissions

Two scopes control surface access:

Scope
Grants

surfaces:read

View surface specs, submissions, and lifecycle status

surfaces:write

Generate new surface specs

Both scopes are included in the member role by default. RBAC enforcement is applied on all surface CRUD routes (view, create, update, delete).

Management API

Endpoint
Method
Description

/v1/{ws}/surfaces

POST

Create a surface. Returns spec + signed token + absolute url.

/v1/{ws}/surfaces

GET

List surfaces. Filterable by entity_id, status. Paginated.

/v1/{ws}/surfaces/{id}

GET

Get a specific surface with current status.

/v1/{ws}/surfaces/{id}

PATCH

Update a surface spec.

/v1/{ws}/surfaces/{id}

DELETE

Archive (soft-delete) a surface.

/v1/{ws}/surfaces/review

GET

List surfaces pending review.

/v1/{ws}/surfaces/{id}/approve

POST

Approve a surface pending review.

/v1/{ws}/surfaces/{id}/reject

POST

Reject a surface pending review.

/v1/{ws}/surfaces/{id}/reshape

POST

Create a new surface containing only the unfilled fields.

/v1/{ws}/surfaces/{id}/progress

GET

Get field-level completion status.

/v1/{ws}/surfaces/{id}/deliver

POST

Deliver via email (or record a web handoff). Sends the surface URL to channel_address, records a lifecycle event. SMS/phone-number delivery is not supported and returns 422.

The delivery endpoint sends the surface URL to the patient, marks the surface as delivered, writes an audit event, and publishes a surface.delivered SSE event for real-time dashboards.

Delivery behavior: email-shaped delivery targets are sent through the workspace's configured email transport (the surface must have been created with channel='email' and a bound use_case_id). The email body contains a short redirect link (/s/f/{surface_id}) that 302-redirects to the full signed token URL. Non-email, non-phone targets record a web handoff. Phone-number targets are rejected with 422.

Error responses: the deliver endpoint returns 404 (surface not found), 409 (already delivered/completed/expired, or test surface), 422 (validation, including a rejected phone target), and 429 (rate limited). Email delivery additionally returns 503 when email transport is not configured.

The response includes delivery metadata:

Field
Type
Description

surface_id

string

The surface that was delivered

status

string

Updated status. Literal of delivered or pending_review.

channel

string

The delivery channel used

channel_address

string

The delivery target (email)

url

string

The full surface URL

message_id

string

Provider message ID for tracking

from_number

string

The number the message was sent from

from_address

string

The address the email was sent from

delivery_provider

string

The delivery provider used

delivered_at

string

ISO 8601 timestamp of delivery

Lifecycle SSE events: surface.delivered, surface.opened, surface.submitted are published in real time as they happen.

Surface expiry: Non-terminal surfaces (not yet completed) automatically expire after their configured TTL. Expired surfaces reject renders, submissions, and auto-saves.

Channels

Channel
Value
Delivery Method

Email

email

Email with branded link

Web

web

Direct link for portals or dashboards

SMS

sms

Spec value only - link delivery is not supported (returns 422); use email or web

While sms is a valid channel value on a spec, the deliver endpoint does not support SMS link delivery (phone-shaped addresses return 422). Delivery is email or web.

Field Types

Type
Value
Use Case

Short text

text

Name, address, pharmacy

Long text

textarea

Symptoms, special instructions

Date

date

Date of birth, appointment date

Phone

phone

Contact number, emergency contact

Email

email

Patient email for follow-up

Number

number

Age, weight, dosage

Single select

select

Preferred provider, insurance type

Multi select

multiselect

Symptom checklist, available days

Checkbox

checkbox

Consent confirmation, HIPAA acknowledgment

Photo

photo

Insurance card, wound photo, ID

Signature

signature

Digital consent, authorization

File

file

Referral letter, lab results, prior records

Heading

heading

Section headers within longer forms (display only)

Info

info

Read-only explanatory text between fields (display only)

SurfaceSpec

The specification an agent generates to define a data collection surface.

Field
Type
Required
Default
Description

entity_id

UUID

Yes

-

Entity this surface is for

title

string

Yes

-

Surface title shown to patient

description

string

No

-

Explanatory text below the title

fields

SurfaceField[]

Yes

-

1-200 data collection fields

channel

ChannelType

No

web

Delivery channel

expires_in_hours

integer

No

168 (7 days)

TTL in hours (range: 1-8760)

context

object

No

{}

Agent-provided context metadata

resource_type

string

No

-

Optional resource type tag (max 128 chars)

branding

BrandingConfig

No

-

Custom branding overrides (falls back to workspace branding)

sections

SurfaceSection[]

No

-

Multi-page form sections (each groups fields into a step)

submit_button_text

string

No

-

Custom label for the submit button (max 128 chars)

completion_title

string

No

-

Title shown after submission (max 256 chars)

completion_message

string

No

-

Message shown after submission (max 2000 chars)

completion_action_url

string

No

-

Optional link shown on the completion screen (max 2048 chars)

SurfaceField

A single data collection field within a surface.

Field
Type
Required
Default
Description

key

string

Yes

-

Unique field identifier (1-128 chars)

label

string

Yes

-

Display label shown to patient

field_type

FieldType

Yes

-

One of the 14 field types above

required

boolean

No

true

Whether the field must be filled

options

string[]

No

-

Choices for select, multiselect fields

description

string

No

-

Help text below the field

placeholder

string

No

-

Placeholder text (max 256 chars)

prefill_value

any

No

-

Pre-populated value from known data

validation

object

No

-

Field-specific validation rules

sensitive

boolean

No

false

PHI flag for additional handling

condition

object

No

-

Conditional display rules (show/hide based on other fields)

consent_text

string

No

-

Consent language displayed with the field (max 5000 chars)

BrandingConfig

Visual branding applied to the patient-facing form. Can be set at workspace level (default for all surfaces) or per-surface (overrides workspace defaults).

Field
Type
Required
Description

logo_url

string

No

Logo image URL (max 2048 chars)

primary_color

string

No

Primary brand color, e.g., #1A73E8 (max 32 chars)

background_color

string

No

Page background color (max 32 chars)

font_family

string

No

Font family name (max 256 chars)

Workspace-level branding is configured through the branding settings endpoints:

Endpoint
Method
Description

/v1/{ws}/settings/branding

GET

Get workspace default branding (any role)

/v1/{ws}/settings/branding

PUT

Update workspace default branding (admin/owner)

When rendering a surface, the platform merges workspace branding with surface-level branding. Surface-level values take precedence. Changes to workspace branding are audit-logged.

SurfaceSection

Groups fields into pages for multi-step forms. When sections are defined, the patient sees one section at a time with navigation between steps.

Field
Type
Required
Description

title

string

Yes

Section heading shown to patient

description

string

No

Explanatory text for the section

field_keys

string[]

Yes

1-100 field keys from the surface's fields array to include in this section

condition

object

No

Conditional display rules for the whole section

SurfaceSubmission

Data submitted by a patient when completing a surface.

Field
Type
Description

surface_id

UUID

Which surface was submitted

entity_id

UUID

Entity the surface belongs to

data

object

Submitted field values (keyed by field key)

submitted_at

ISO timestamp

When the submission occurred

channel

ChannelType

Channel the submission came through

fields_submitted

string[]

List of field keys that were filled

partial

boolean

Whether this is a partial (auto-save) submission

Lifecycle

Status
Value
Description

Created

created

Spec generated and stored

Pending review

pending_review

Surface awaiting field-engineer review before delivery

Delivered

delivered

Sent to patient via channel

Opened

opened

Patient opened the link

Partial

partial

Some fields auto-saved

Completed

completed

All required fields submitted

Expired

expired

TTL exceeded without completion

Archived

archived

Soft-deleted via the DELETE/archive route

Data Flow

Submissions are written to the world model as events:

  • Source: surface (distinguishable from EHR, voice, or manual imports)

  • Confidence: Initial confidence level for patient-reported data

  • Entity: All surface events (creation, delivery, submission) are linked to the entity_id on the event row, so they appear in entity timeline queries and trigger state recomputation

When a patient submits a surface, entity state recomputation runs within the same transaction. Submitted form data flows directly into entity demographic and clinical projections with no delay.

Surface data flows through the same confidence gates, review queues, and entity resolution pipelines as data from any other source. No special handling is required.

Patient-Facing Endpoints

Patients access surfaces through HMAC-signed URL tokens. No login or account is required, and each token grants access to one specific surface.

Endpoint
Auth
Description

GET /s/f/{surface_id}

None

Short URL redirect. Generates a fresh HMAC token and issues a 302 redirect to /s/{token}. Used in email delivery for compact links. Returns 404 if not found, 410 if expired.

GET /s/{token}

Token (no API key)

Render surface as mobile-first HTML. Updates status to opened.

POST /s/{token}/submit

Token (no API key)

Accept form submission. Writes events at confidence 0.5. Rejects if already completed or expired. Triggers entity state recomputation within the same transaction.

PUT /s/{token}/fields/{key}

Token (no API key)

Incremental auto-save for a single field. Updates status to partial.

Token format: HMAC-SHA256 signed with a configured secret. Contains surface ID and expiration. Validated on every request.

Rate limiting (per IP):

  • Render: 30 requests/minute

  • Submit: 10 requests/minute

  • Auto-save: 30 requests/minute

Field value validation: Individual field values are capped at 10KB to prevent payload abuse.

Rendering: server-side HTML generation for all 14 field types. Mobile-first, XSS-safe. Photo and file uploads use native device capabilities. Signature fields use touch input.

Atomic lifecycle: status transitions (opened, partial, completed) are written atomically. Check and insert happen in a single transaction to prevent race conditions like double submissions.

When creating a surface via the management API, the response includes the signed token and full url if the token secret is configured.

Gap Scanner Settings

The gap scanner is a background loop on the connector runner that proactively detects missing entity data and creates surfaces. Configuration is per-workspace via settings endpoints.

GET /settings/gap-scanner. Get current gap scanner settings (any role).

PUT /settings/gap-scanner. Update gap scanner settings (admin/owner). Partial updates supported.

POST /settings/gap-scanner/preview. Preview gap detection (dry run) without creating surfaces.

POST /settings/gap-scanner/scan. Trigger one scan tick on demand.

Setting
Type
Default
Description

enabled

boolean

false

Enable/disable the scanner

scan_interval_seconds

integer

300 (5 min)

How often to scan

appointment_lookahead_hours

integer

72 (3 days)

How far ahead to check for upcoming appointments

cooldown_hours

integer

168 (7 days)

How long before re-scanning the same entity

max_surfaces_per_tick

integer

10

Maximum surfaces created per scan cycle

max_pending_surfaces

integer

3

Skip entities with this many unfinished surfaces (fatigue gating)

min_completion_rate

float (0-1)

0.0

Skip entities whose completion rate is below this threshold

channel_optimization

boolean

false

When enabled, use each entity's historically preferred channel instead of the requirement's default

requirements

GapRequirement[]

[]

Gap detection rules

GapRequirement

Field
Type
Required
Default
Description

name

string

Yes

-

Rule name

entity_type

string

No

person

Entity type to scan

trigger

string

No

upcoming_appointment

When to check: upcoming_appointment or recent_interaction

required_fields

GapRequiredField[]

Yes

-

1-50 fields that must be present

channel

ChannelType

No

email

Delivery channel for generated surfaces (sms is not a deliverable channel)

priority

string

No

normal

low, normal, or high

surface_title

string

No

Rule name

Title for generated surfaces

surface_description

string

No

-

Description shown on generated surfaces

GapRequiredField

Field
Type
Required
Description

path

string

Yes

Dot-notation path into entity state (e.g., insurance.carrier)

label

string

Yes

Display label for the surface field

field_type

FieldType

No

Field type (default: text)

min_items

integer

No

For list fields, minimum items required

The scanner reports through the connector runner's metrics. Changes to settings are audit-logged.

Surface Analytics

Four endpoints under /v1/{workspace_id}/analytics/surfaces/ for closed-loop optimization:

Endpoint
Description

GET /analytics/surfaces/completion-rates

Overall completion rate, time-bucketed trend, by-source breakdown (agent, gap scanner, manual). Filterable by entity_id.

GET /analytics/surfaces/channel-effectiveness

Per-channel completion rate and average time-to-complete

GET /analytics/surfaces/field-abandonment

Per-field drop-off rate and save rate for abandoned surfaces

GET /analytics/surfaces/entity/{entity_id}

Per-entity surface history: completion stats, preferred channel, recent surfaces

Common parameters (completion-rates, channel-effectiveness, field-abandonment):

Parameter
Type
Default
Description

days

integer (1-90)

30

Lookback window

date_from / date_to

date

-

Explicit date range

interval

1h / 1d / 1w

1d

Time bucket for trend data (completion-rates only)

Entity history accepts limit (1-100, default 20).

All endpoints require viewer+ permissions and are workspace-scoped.

Entity Type

Surfaces introduce the interaction entity type to the world model ontology. Surface lifecycle events (created, delivered, opened, submitted) are tracked as first-class entities with full event sourcing.

API Reference

Last updated

Was this helpful?