# Surface Patient

## Serve Vcard

> Serve a vCard contact card for a workspace.\
> \
> Public, unauthenticated endpoint. iOS blocks clickable links in SMS\
> from unknown senders — sending a vCard first lets patients save the\
> number so subsequent SMS links render as tappable.\
> \
> Path: \`\`/s/vcard/{workspace\_slug}.vcf\`\`

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/vcard/{workspace_slug}.vcf":{"get":{"tags":["Surface Patient"],"summary":"Serve Vcard","description":"Serve a vCard contact card for a workspace.\n\nPublic, unauthenticated endpoint. iOS blocks clickable links in SMS\nfrom unknown senders — sending a vCard first lets patients save the\nnumber so subsequent SMS links render as tappable.\n\nPath: ``/s/vcard/{workspace_slug}.vcf``","operationId":"serve-vcard","parameters":[{"name":"workspace_slug","in":"path","required":true,"schema":{"type":"string","title":"Workspace Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Workspace or phone number not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Redirect To Surface

> Short-URL redirect: \`\`/s/f/{surface\_id}\`\` → \`\`/s/{token}\`\`.\
> \
> Generates a fresh HMAC token and issues a 302 redirect so that SMS\
> messages can contain a short, clickable link instead of the long\
> base64-encoded token URL.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/f/{surface_id}":{"get":{"tags":["Surface Patient"],"summary":"Redirect To Surface","description":"Short-URL redirect: ``/s/f/{surface_id}`` → ``/s/{token}``.\n\nGenerates a fresh HMAC token and issues a 302 redirect so that SMS\nmessages can contain a short, clickable link instead of the long\nbase64-encoded token URL.","operationId":"redirect-to-surface","parameters":[{"name":"surface_id","in":"path","required":true,"schema":{"type":"string","title":"Surface Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"302":{"description":"Redirect to full surface URL"},"404":{"description":"Surface not found"},"410":{"description":"Surface expired"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}}}
```

## Lookup Field

> Search healthcare reference data for form field autocompletion.\
> \
> Supports: medication (RxNorm), allergy (RxNorm), pharmacy (NPPES NPI),\
> insurance (static carrier list). Token-authenticated, no Bearer auth.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}}},"paths":{"/s/{token}/lookup/{lookup_type}":{"get":{"tags":["Surface Patient"],"summary":"Lookup Field","description":"Search healthcare reference data for form field autocompletion.\n\nSupports: medication (RxNorm), allergy (RxNorm), pharmacy (NPPES NPI),\ninsurance (static carrier list). Token-authenticated, no Bearer auth.","operationId":"lookup-surface-field","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"lookup_type","in":"path","required":true,"schema":{"type":"string","title":"Lookup Type"}},{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":200,"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"422":{"description":"Invalid lookup type"},"429":{"description":"Rate limited"}}}}}}
```

## Ocr Extract

> Extract structured data from an image (e.g. insurance card) using Gemini Vision.\
> \
> Returns extracted field key-value pairs and a confidence score.\
> Token-authenticated, no Bearer auth.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"OcrRequest":{"properties":{"image":{"type":"string","maxLength":10000000,"minLength":1,"title":"Image","description":"Base64-encoded image data"},"target_fields":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":50},{"type":"null"}],"title":"Target Fields","description":"Optional list of field keys to extract"}},"type":"object","required":["image"],"title":"OcrRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}/ocr":{"post":{"tags":["Surface Patient"],"summary":"Ocr Extract","description":"Extract structured data from an image (e.g. insurance card) using Gemini Vision.\n\nReturns extracted field key-value pairs and a confidence score.\nToken-authenticated, no Bearer auth.","operationId":"ocr-surface-extract","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OcrRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Render Surface

> Render a patient-facing surface as HTML.\
> \
> Token-authenticated — no Bearer auth required.\
> Records a surface.opened lifecycle event on first view.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}":{"get":{"tags":["Surface Patient"],"summary":"Render Surface","description":"Render a patient-facing surface as HTML.\n\nToken-authenticated — no Bearer auth required.\nRecords a surface.opened lifecycle event on first view.","operationId":"render-surface","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"410":{"description":"Token expired"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Get Surface Spec

> Return surface spec as JSON for the forms app.\
> \
> The forms app (Next.js) calls this on SSR to fetch the spec,\
> saved field values, and merged branding. Records surface.opened\
> event on first access.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}/spec":{"get":{"tags":["Surface Patient"],"summary":"Get Surface Spec","description":"Return surface spec as JSON for the forms app.\n\nThe forms app (Next.js) calls this on SSR to fetch the spec,\nsaved field values, and merged branding. Records surface.opened\nevent on first access.","operationId":"get-surface-spec","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"404":{"description":"Surface not found"},"409":{"description":"Already submitted"},"410":{"description":"Token expired or surface archived"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Get Availability

> Return available appointment slots for the surface's workspace.\
> \
> Queries FHIR Slot resources from world.events that are free and\
> within the requested date range. Token-authenticated, no Bearer auth.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}}},"paths":{"/s/{token}/availability":{"get":{"tags":["Surface Patient"],"summary":"Get Availability","description":"Return available appointment slots for the surface's workspace.\n\nQueries FHIR Slot resources from world.events that are free and\nwithin the requested date range. Token-authenticated, no Bearer auth.","operationId":"get-surface-availability","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date (YYYY-MM-DD) to start search","title":"Date"},"description":"ISO date (YYYY-MM-DD) to start search"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Number of days to search forward","default":7,"title":"Days"},"description":"Number of days to search forward"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"410":{"description":"Token expired"},"422":{"description":"Invalid date format"},"429":{"description":"Rate limited"}}}}}}
```

## Book Appointment

> Submit a booking request for a specific slot.\
> \
> Writes a booking.requested world event tied to the surface's entity.\
> Token-authenticated, no Bearer auth.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"BookingRequest":{"properties":{"slot_id":{"type":"string","maxLength":256,"minLength":1,"title":"Slot Id","description":"The FHIR Slot ID to book"}},"type":"object","required":["slot_id"],"title":"BookingRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}/book":{"post":{"tags":["Surface Patient"],"summary":"Book Appointment","description":"Submit a booking request for a specific slot.\n\nWrites a booking.requested world event tied to the surface's entity.\nToken-authenticated, no Bearer auth.","operationId":"book-surface-appointment","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"410":{"description":"Token expired"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Heal Field

> Auto-heal a form field value using Claude Haiku.\
> \
> Best-effort LLM correction — returns original value with confidence 0\
> if the service is unavailable or inference fails.\
> Token-authenticated, no Bearer auth.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HealFieldRequest":{"properties":{"key":{"type":"string","maxLength":128,"minLength":1,"title":"Key"},"value":{"type":"string","maxLength":2000,"minLength":1,"title":"Value"},"field_type":{"type":"string","maxLength":32,"title":"Field Type"},"label":{"type":"string","maxLength":256,"title":"Label"},"sensitive":{"type":"boolean","title":"Sensitive","default":false},"context":{"additionalProperties":true,"type":"object","title":"Context"}},"type":"object","required":["key","value","field_type","label"],"title":"HealFieldRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}/heal":{"post":{"tags":["Surface Patient"],"summary":"Heal Field","description":"Auto-heal a form field value using Claude Haiku.\n\nBest-effort LLM correction — returns original value with confidence 0\nif the service is unavailable or inference fails.\nToken-authenticated, no Bearer auth.","operationId":"heal-surface-field","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealFieldRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Submit Surface

> Submit a patient-facing surface form.\
> \
> Accepts standard HTML form POST. Writes surface.submitted event\
> with confidence 0.5 (self-reported data).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}/submit":{"post":{"tags":["Surface Patient"],"summary":"Submit Surface","description":"Submit a patient-facing surface form.\n\nAccepts standard HTML form POST. Writes surface.submitted event\nwith confidence 0.5 (self-reported data).","operationId":"submit-surface","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"409":{"description":"Already submitted"},"410":{"description":"Token expired"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"}}}}}}
```

## Save Field

> Auto-save a single field value.\
> \
> Called by client-side JavaScript on field blur.\
> Writes surface.field\_saved event with confidence 0.5.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"FieldSaveRequest":{"properties":{"value":{"title":"Value","description":"The field value to save"}},"type":"object","required":["value"],"title":"FieldSaveRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/s/{token}/fields/{key}":{"put":{"tags":["Surface Patient"],"summary":"Save Field","description":"Auto-save a single field value.\n\nCalled by client-side JavaScript on field blur.\nWrites surface.field_saved event with confidence 0.5.","operationId":"save-surface-field","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldSaveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid token"},"413":{"description":"Payload too large"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"},"500":{"description":"Save failed"}}}}}}
```
