Inspiration
Home-service visits run on trust, and that trust runs out the first time two people remember the same morning differently. A cleaner says she rang the bell and nobody answered. The homeowner says nobody ever came. Both can be telling the truth, and neither can prove it.
A doorbell camera already sees that exact moment, but the only way to share it is to hand over footage of your front door. I wanted proof of arrival that never needs the footage.
What it does
Doorstep Receipts turns Ring doorstep events into a shareable proof-of-arrival receipt.
The homeowner books an arrival window and picks the door. A doorbell press or a person detected during the watch period becomes a verdict: in the window, early, late, no arrival detected, or can't tell when the camera was offline. The contractor gets an expiring, revocable link showing the verdict and times only: no footage, no device details. The homeowner can mark any signal "Not them" and confirm when the contractor left.
How I built it
A Node.js and TypeScript service receives Ring Partner API webhooks (v1.1). Each delivery is verified with HMAC-SHA256 over the raw request body, deduplicated by request id, and passed through a privacy gate.
Everything else is counted and discarded before it reaches storage, and the dashboard shows both counters. Only two kinds of signal are ever kept: doorbell presses and people at the door.
Amazon Bedrock (Converse API) writes the summary from a small facts object that contains no ids and no footage. If the output mentions a clock time that is not in the facts, or the call fails, a deterministic template is used instead.
Because I couldn't find an official Ring simulator, I built one. It sends properly signed webhook payloads to the same endpoint a real doorbell would, so the whole pipeline runs without hardware. The dashboard is plain JavaScript and CSS under a strict content-security policy, and 39 automated tests cover the signature check, payload parsing, verdict logic, privacy gate, public receipt, and API.
Challenges
- Deciding what a doorbell can honestly prove. It sees arrivals, but not someone leaving through another door, and a missing detection is not proof of a missing visitor. I made the product say so instead of hiding it.
- Making the simulator trustworthy. The fake events had to take the real path, including a valid signature over the exact bytes. Re-serialising the JSON before verifying changes the bytes and breaks the HMAC, so the handler verifies the raw body.
- Docs that disagree. The event list differs between pages, and the field holding a motion event's subtype appears in different places across sources, so the parser reads the documented location and falls back to the others.
- Demoing time. The server rejects events dated in the future, so a demo can't show a late arrival in a window that hasn't closed yet. I added demo visits that have already ended, and the simulator greys out scenarios that don't fit the selected visit, with the reason on the button.
- Two small traps. The content-security policy would have blocked inline handlers and styles, and newer time-formatting libraries put a narrow non-breaking space before AM/PM, which breaks plain string comparison.
What I learned
- Privacy is stronger as a property of the data flow than as a setting. If data is dropped before storage, there is nothing to leak or misuse.
- Saying "can't tell" makes a proof tool more credible, not less.
- Never let a model state a fact you can check. Grounding its output against the facts it was given is cheap.
- Reading Ring's docs as an integrator showed what is missing: a sandbox that can inject events, a published payload schema, and a dwell or departure event.
What's next
Ring OAuth account linking, multiple properties, contractor-side scheduling, and a departure event from Ring to replace the time-on-site estimate.
Try it
Built With
- amazon
- amazon-web-services
- arrival
- artificial
- automation
- bedrock
- cybersecurity
- data
- dispute
- home
- intelligence
- javascript
- node.js
- of
- privacy
- proof
- ring
- smart
- typescript
- webhooks
Log in or sign up for Devpost to join the conversation.