bridge · v1

Sandwich Pipe

A single signed webhook for care data. Agencies, EHRs, and home-health platforms push structured events at Sandwich Pipe — visits, notes, medications, incidents — and Sandwich lights up the right loved-one record for the right family in real time. HMAC-signed, institution-scoped, forward-compatible.

What it is

Sandwich Pipe is the private-link layer between care-data producers and Sandwich's family-facing app. Think of it as Plaid for caregiving: agencies, EHRs, and home-health platforms push structured events at Sandwich Pipe, and Sandwich lights up the right loved-one record for the right family in real time.

Sandwich Soft agencies don't need to integrate. If you're running Sandwich Soft, Sandwich Pipe is already wired into clock-in and clock-out — just toggle family-share on a client to start streaming. The integration spec below is for outside partners (other agency platforms, EHRs, hospital discharge systems) who want to push events into Sandwich.
About the URL: the canonical partner-facing endpoint is api.joinsandwich.com/sandwichpipe/v1/events. The api. subdomain is being deployed; while it's being set up, sandbox partners receive a Cloud Run *.run.app URL during onboarding. Code against the canonical URL — we'll route DNS to the right backend before you go live. Earlier drafts of the docs referenced pipe.joinsandwich.com and ingest.joinsandwich.com; both have been retired.

Why a pipe

  • Neutral shape. One event schema — institution_id, subject_ref, event_type, payload — lets us onboard any partner without redesigning the app.
  • Signed and replayable. Every request carries X-SandwichPipe-Signature: sha256=…, computed over the raw body with a per-partner secret. Replays are cheap; forgeries are not.
  • Fire-and-forget on the partner side. Partners never block their own workflow waiting on Sandwich. If Sandwich Pipe is down, events are queued and retried with exponential backoff.
  • Family-controlled visibility. Events flow only when the loved one's family-share is on. Partners don't need to know who can see what — Sandwich enforces it on the receiving side.

Event envelope

POST https://api.joinsandwich.com/sandwichpipe/v1/eventsjson
{
  "institution_id": "sandwichsoft-sunrise-home-care",
  "subject_ref":    "client_8c1f",
  "event_type":     "visit_ended",
  "occurred_at":    "2026-04-16T21:04:00Z",
  "payload": {
    "caregiver_id":      "caregiver_maria_r",
    "actual_end":        "2026-04-16T21:04:00Z",
    "duration_minutes":  92
  }
}

Field reference:

institution_id
Stable identifier for your organization. Issued by Sandwich during partner onboarding.
subject_ref
Your internal ID for the client. Sandwich uses this to map to the right loved-one record. Stable across events for a given client.
event_type
One of the v1 event types listed below. Forward-compatible — additional types may appear; clients should ignore unknown ones.
occurred_at
ISO 8601 timestamp for when the event actually happened (not when you sent it).
payload
Event-specific data. Schema varies by event_type — see Event types below.

Signing requests

Compute HMAC-SHA256(raw_body, partner_secret) and send the hex digest prefixed with sha256=. Sandwich verifies in constant time and rejects anything older than 5 minutes (clock-skew tolerant).

request headershttp
POST /sandwichpipe/v1/events HTTP/1.1
Host: api.joinsandwich.com
Content-Type: application/json
X-SandwichPipe-Institution: sandwichsoft-sunrise-home-care
X-SandwichPipe-Signature: sha256=4f8a9b2e…
X-SandwichPipe-Timestamp: 2026-04-16T21:04:01Z
signing — pseudocodets
const sig = "sha256=" + hmacSha256Hex(secret, rawBody);
headers["X-SandwichPipe-Signature"]   = sig;
headers["X-SandwichPipe-Institution"] = institutionId;
headers["X-SandwichPipe-Timestamp"]   = new Date().toISOString();

Per-partner secrets are issued at onboarding and rotated quarterly. A second secret window is provided during rotation so you can roll keys without dropped events.

Event types (v1)

visit_started
A caregiver clocked in at a client's home. Payload: caregiver_id, scheduled_start, actual_start, optional location.
visit_ended
Clock-out. Payload: caregiver_id, actual_end, duration_minutes.
note_added
A caregiver observation was logged. Payload: caregiver_id, note_text, optional structured_summary.
med_administered
A medication dose was administered. Payload: medication_name, dose_amount, dose_unit, administered_by, optional scheduled_at.
vital_recorded
A vital sign was recorded. Payload: vital_type, value, unit, recorded_by, optional secondary_value.

Future event types will be added without breaking changes. Partners should send unknown types as new ones become available; Sandwich will accept and forward to families based on family-share configuration.

Family share

Family share is opt-in per client. An agency using Sandwich Soft toggles family-share on a client record, which provisions a per-client shared secret and starts forwarding that client's events to Sandwich Pipe. Toggle it off and events stop at the agency boundary — no events ever cross into the family app, and prior data is purged on request.

For outside partners, family-share is established by the agency that owns the client relationship. Sandwich will not display events to a family unless the agency has affirmatively opted that client in. This keeps the partner's compliance posture clean — you forward events to Sandwich Pipe, and Sandwich enforces the family-side authorization.

Errors & retries

Sandwich Pipe responds with one of these statuses. Partners should treat 5xx as retriable with exponential backoff and 4xx as terminal (fix the request and resend, but don't retry the original).

202 Accepted
Event was queued. The response body returns event_id for your audit log.
400 Bad Request
Body could not be parsed, required field missing, or occurred_at not ISO 8601. Fix the request and resend.
401 Unauthorized
Signature verification failed or timestamp older than 5 minutes. Check the secret and clock skew.
403 Forbidden
Institution does not have an active integration. Check with Sandwich ops if this appears.
404 Not Found
No mapping exists for the subject_ref. The agency hasn't opted that client in to family-share, or the subject was deleted. Treat as terminal — do not retry.
429 Too Many Requests
Rate limit exceeded. Backoff and retry per the Retry-After header.
5xx Server Error
Sandwich temporary issue. Retry with exponential backoff (recommended: 1s, 2s, 4s, 8s, 16s, 32s, then drop after ~5min total).

Becoming a partner

Sandwich Soft agencies get Sandwich Pipe for free — it's wired into clock-in and clock-out. Outside partners (EHRs, hospital discharge systems, other agency platforms) can email hello@joinsandwich.com to start the onboarding conversation.

What you'll need:

  • A signed Business Associate Agreement (BAA) — Sandwich will provide a template.
  • A list of institution_id namespaces you want issued (one per tenant on your platform if you're multi-tenant).
  • A short security review on your end — we'll run one too — confirming the receiving system handles redacted PHI per HIPAA.

Sandbox secrets are typically issued within a week of the security review.

Looking for the rest of the stack? MCP · Sandwich Soft · All docs