Inspiration

Every Medicaid-funded home-care visit in the United States must be electronically verified, with six data elements: service, recipient, caregiver, date, location, and start and end time. In 2026 states switched from soft edits to hard edits, so a claim without a matching verified visit is now denied automatically (Missouri from April 2026, with Minnesota, Ohio, Indiana, Pennsylvania, and Massachusetts following). Most agencies verify visits with a GPS clock-in from the caregiver's phone, which drifts, can be spoofed, and fails when the phone dies in a basement apartment.

At 6:10 AM a scheduler does not know whether the 6:00 AM caregiver is late, standing at the door with no signal, or not coming. Two weeks later the same visit comes back as a denied claim. Meanwhile the client's daughter texts the agency for the third time this month: "Did anyone actually come today?"

All three share one blind spot: nobody has an independent, timestamped record of when a person arrived at and left the client's door. Millions of those doors already have a Ring doorbell, owned by the family, producing signed events. VisitProof turns it into that record.

What It Does

VisitProof is a Ring Appstore style app and web console with four roles over one store:

  • Scheduler (Today board). Live visit status from the door. Exception cards for late arrival, no-show, early departure, and unobservable visits, grouped into Today, Earlier This Week, and Older, with Call Caregiver, Snooze, Resolve, and Backfill Times. A correction never overwrites what the door observed.
  • Compliance lead. Reconciles every EVV clock-in against the door record over Today, This Week, or Two Weeks: corroborated, contradicted, missing clock-in with door presence, missing both, or unobservable. Every observation, report, and resolution is appended to a hash-chained, signed ledger. One click exports a paginated PDF evidence pack with the chain and pack hash, and an Open EVV style JSON export for visit maintenance.
  • Family. One calm card a day ("The caregiver came for both visits"), at most one alert for today, earlier days collapsed. Granular consent (share with the agency, arrival snapshots with expiry, alerts), Export My Data, and Delete Everything, all enforced in code. Device Check and Live View read the family's Ring doorbell through the Ring Partner API.
  • Caregiver. Their own two weeks of visits with the door times next to their clock-in, so a caregiver whose phone died still has proof they were there, plus notes and disputes in their own signed column.
  • Ask VisitProof (Alexa+). "Did the caregiver come to Mom's today?" answered by an MCP server over Streamable HTTP, shown in an Echo Show style simulator. Each answer names the tool it called by a readable title, and the raw MCP request and result sit in a Response Detail tab labeled as protocol data.

Principles we held to: corroboration, not surveillance (it says a person arrived at the door, never who); events first, pixels optional (everything works with zero video, so Ring's TAKE encryption does not break it); three columns never merged (Observed, Reported, Resolved); unobservable windows are recorded as unobservable, never as absence.

How We Built It

Ring Partner API at runtime

Ring capability Where in the code
Typed client: users/me, devices with include, status, capabilities, configurations, location, event history, snapshots (303 flow), clips, WHEP sessions, subscriptions, app integrations (POST nonce confirm, PATCH completed) packages/ring-partner-sdk/src/client.ts
Webhook verification: HMAC-SHA256 over the raw body bytes, constant time, v1.1 schemas, dedupe on meta.request_id, 202 before any engine work packages/ring-partner-sdk/src/webhook.ts, apps/webhooks/src/receive.ts
One-way account linking: Token Exchange URL (60 second exchange), Account Link URL (nonce freshness and constant-time match), App Homepage URL apps/console/app/api/ring/token-exchange/, apps/console/app/link/, apps/console/app/ring/
Device Check and Ring history sync (provenance ring_history) apps/console/lib/ring/device-check.ts, apps/console/lib/ring/history-sync.ts
Live view over WHEP with Ring's 30 and 60 second session caps, ending a connected session that decodes no video within 8 seconds packages/ring-partner-sdk/src/whep.ts, packages/ring-partner-sdk/src/whep-video.ts, apps/console/app/family/live/
Captured Playground responses as fixtures, and a mock Ring Playground that serves them for offline tests packages/ring-partner-sdk/src/fixtures/playground/, packages/ring-partner-sdk/src/testing/mock-playground.ts
Emulator: HMAC-signed v1.1 deliveries and a two-week ground-truth plan, because the Playground cannot send webhooks packages/ring-partner-sdk/src/emulator/

Live Playground run (22 October 2026). Against the Playground sandbox doorbell, users/me, devices, status, capabilities, configurations, location, and history all returned 200 (history with zero events, so no event types were seen), subscriptions returned 422 for the Playground user, and a WHEP session negotiated H264 and Opus with ICE and DTLS connected but no media from the sandbox, because no simulation was running. Our first schemas rejected all four device sub-resources (real type names and many null fields), and our history path was wrong; both are fixed and tested against the captured responses, on which Device Check reads 4 of 4 required checks passing.

Second live run (22 October 2026, about 08:35 EAT, checked by our demo recorder). Device Check against the live Ring Partner API read 4 of 4 required checks passing. Sync Ring History succeeded live ("Ring History Synced") and returned real on_demand events with epoch millisecond times, which we now convert to ISO. After we started a Motion "Simulate live view event" in the Ring Developer Playground, VisitProof's own /family/live decoded real video over WHEP from the sandbox doorbell: 250 frames at 1280x720 (sample stream "Birds on Feeders" by Michael Black, CC BY 4.0). This confirms that the sandbox streams only during a simulated event.

Presence Engine. A pure, clock-injected TypeScript engine (packages/domain) implements twelve EARS requirements: observable windows, arrival clustering, a judge for ambiguous double arrivals, departure revised as events arrive, late, no-show and early-departure cards, an unobservable overlay from device lifecycle events, nearest-visit assignment for overlapping windows, and reconciliation bands at 10 and 30 minutes. Domain coverage is about 99 percent of statements.

Demo pipeline. pnpm demo seeds one New York agency, three clients, six caregivers, and 84 visits over two weeks, posts 181 signed webhooks (10 duplicated, as Ring's at-least-once delivery does) to the real receiver, replays the real engine handlers in simulated time, imports independent EVV clock-ins from a vendor-style CSV, and checks the outcome against the plan: 9 late, 4 no-shows, 5 early departures, 3 unobservable, 6 contradicted, 8 missing clock-ins.

AWS. See the AWS Builder section below.

MCP and Alexa+. apps/mcp uses the official TypeScript SDK 1.x: tools get_visit_status, list_visits, list_exceptions, explain_visit, get_client_summary, acknowledge_exception, add_visit_note (writes confirm through elicitation or a confirmed argument, because the documented Alexa+ client does not advertise elicitation), a schedule resource, a morning_briefing prompt, version negotiation for 2025-11-25 and 2025-03-26, Origin and Host validation, scoped bearer tokens, and protected-resource metadata. A conformance suite exercises it over real HTTP.

UI. Next.js 16 App Router, React 19, Tailwind CSS v4, and strictly shadcn/ui on Base UI primitives, with agency-local times everywhere and WCAG 2.2 AA as the bar.

Quality. 671 automated tests (Vitest), all passing on 22 October 2026: 655 across the ten workspace packages and 16 for the demo scripts. GitHub Actions CI, TypeScript strict, Zod at every boundary.

Challenges We Ran Into

  • The Ring Playground gives a live sandbox doorbell but no motion or doorbell events (history came back empty) and no webhook delivery, so we built a signed-webhook emulator and kept Playground calls for devices, history, and live view, with provenance labels on every event.
  • Our first live run failed on real data: every device sub-resource returned 200, but strict schemas written from the docs rejected the real type names and null fields, and Device Check showed 0 of 5 checks passing. We captured the responses as fixtures, corrected the schemas while still validating the fields we rely on, and built a mock Playground so the fix could be tested after the 30 minute token expired.
  • Live view connected (ICE and DTLS) but the sandbox doorbell sent no video until we started a live view event simulation in the Playground; with one running we decoded 250 frames at 1280x720. A black player looks like a WebRTC bug, so Live View now ends a session with no video after 8 seconds and tells the family plainly that Ring connected but no video arrived.
  • The official ring-api-helloworld sample checks a static bearer token instead of the X-Signature HMAC and uses an older payload shape, so we implemented verification from the documentation and tested it with our own vectors.
  • Departure detection: the first quiet gap after arrival is not a departure. The engine revises departure as later in-window events arrive.
  • Time zones: an agency in New York, a developer in Nairobi, and Ring timestamps in UTC. Every user-facing time is now rendered in the agency's zone.
  • Evidence integrity: an agency correction must never overwrite the door's observation, so corrections live in their own signed column.

Accomplishments That We're Proud Of

  • A one-command demo that goes over real HTTP through the real receiver and reproduces the planned dataset exactly.
  • A signed, hash-chained ledger and an evidence pack a compliance lead could hand to an auditor.
  • An honest product: it says what it can prove and what it cannot, and the UI labels every emulated event.

What We Learned

  • Treat absence carefully: "we saw nothing" and "we were not watching" are different claims, and the record must keep them apart.
  • Ring's read-only API is a strength for this product. VisitProof cannot control anything in the home, which makes it easier for families to say yes.
  • Capture real responses on first contact. Thirty minutes of a live token, recorded into fixtures and a mock server, was worth more than days of schemas written from documentation.

What's Next For VisitProof

Private-app pilots with home-care agencies, Ring Appstore certification (questionnaire drafted in docs/compliance.md), alternate-EVV vendor onboarding in Provider Choice states, Cognito sign-in, the MCP server on AgentCore Runtime, and an Echo Show family view through MCP Apps.

Boundaries

VisitProof is not an EVV system of record, not identity verification, not resident monitoring, and not a medical device. It never uses facial recognition and never correlates across Ring accounts.


Criteria Map

Criterion Evidence
Tech Implementation Ring Partner API client, HMAC webhook receiver, account-linking endpoints, WHEP live view, Presence Engine with 12 EARS requirements, signed ledger, 671 passing tests, CI
Design Four coherent role journeys, agency-local times, one calm daily message for families, strict shadcn/ui, designed empty, loading, and error states
Potential Impact 2026 Medicaid EVV hard edits, unreliable GPS clock-ins, family transparency; distribution through the Ring Appstore elder-care category and agency sales
Quality Of The Idea The doorbell already at the door as an independent proof-of-presence signal; agency-first and EVV-aware, where existing Ring apps watch the resident

Built With

Share this project:

Updates

Submission history