Inspiration

Every clinic, pharmacy and school district in America already calls you automatically. Those calls play a recording and count a keypress: press 1 to confirm, press 2 to cancel.

There is no button for "I can't come Thursday, my ride fell through - can you do Friday?"

To say that, she has to hang up, call the main line, wait on hold, and hope somebody bilingual picks up. So she doesn't. She doesn't show up either. And the chart says no-show.

28.9 million people in the United States speak English less than "very well" (US Census Bureau, ACS 2024 1-Year Estimates, Table DP02). At a safety-net primary care clinic, patients with limited English proficiency had 32% higher adjusted odds of missing an appointment (J Gen Intern Med, 2023). And when Spanish-preferring patients switched to a Spanish-speaking primary care physician, good glycemic control rose 10 percentage points (JAMA Internal Medicine, 2017).

The problem is not that she cannot be reached. It is that nothing that reaches her can hear her answer, and nothing that speaks for her checks itself first.

What it does

Ringback turns a one-way robocall into a conversation, using nothing but phone calls.

  1. You click Call the inbox in the browser. That is a real call, placed with the Vonage Client SDK.
  2. The line answers with a recording notice and asks "Who is this for?" You say a name out loud. Speech recognition matches it against your directory; every person has a language.
  3. "Say your message now." You speak it in English.
  4. Claude translates it, back-translates it, and flags anything risky. Then the line reads the back-translation to you, in your own language: "You are about to send..." Press 1 to send, 2 to re-record, 3 to hear the Spanish yourself. Silence cancels.
  5. Press 1 and her ordinary phone rings. A voice says her name and the message in Spanish. No app, no login, no data plan. "Press 1 if you understood, or speak after the tone."
  6. She speaks her answer in Spanish. It is transcribed, translated, and rings your browser back - a banner, a ring tone, Answer, and you hear her answer in English.
  7. The board shows one word per message: sent, delivered, understood, replied, left on voicemail, unsupported language.

Every reminder system stops at delivered. The good ones reach confirmed. This one gets to "Friday morning."

Two things it refuses to do

It will not speak in your name without asking. The read-back gate is not a confirmation dialog, it is the product. When a machine translates emergency-department instructions, the meaning survives 82.5% of the time (Taira et al., J Gen Intern Med, 2021) - about one in six gets it wrong, and the person who would carry that error is the one who cannot check it. So the machine tells you what it is about to say, in your language, and waits.

It will not fake a language it does not have. Vonage text-to-speech covers en-US and es-US end to end. It has no Haitian Creole voice. So a Creole directory entry stops before dialing and says so out loud, rather than reading Creole in a French voice and hoping. On the board that row reads unsupported language. Two languages real, the rest honest.

Why someone would pay for this

This is not a new obligation looking for a budget. Under 45 C.F.R. 92.201(a), implementing Section 1557 of the Affordable Care Act, a covered entity "must take reasonable steps to provide meaningful access to each individual with limited English proficiency," and 92.201(b) requires that assistance be "accurate and timely." An automated call that plays English at someone who speaks none of it, and can accept nothing back but a keypress, is not meaningful access.

The lens I explored: Access

"How could you leverage the API to redefine who gets access to communication?"

The person Ringback is for owns a phone that rings. That is the whole device requirement. No app to install, no account to create, no portal to log into, no data plan, no English to read - and she gets a full two-way conversation, including the part where her answer is what changes the outcome. Access is not only being reached. It is being heard back.

Vonage Voice API features used

Every one of these is load-bearing. Remove any and the loop breaks.

  • Client SDK in-app voice - the browser is the sender's phone: "Call the inbox", and the ring-back leg that delivers her reply
  • Inbound call + answer webhook, NCCO - the whole IVR is server-generated NCCO
  • input with speech - "Who is this for?" matched against the directory, and the message capture
  • input with DTMF - the 1 / 2 / 3 read-back gate, and "press 1 if you understood"
  • talk with per-language TTS - en-US to the sender, es-US to the recipient, name first
  • Outbound calls - the delivery leg to her phone, and the ring-back leg to the browser
  • record + transcription - fallback capture when live speech recognition returns nothing usable
  • Advanced machine detection (detect_beep) - voicemail path, state left on voicemail, one retry
  • Speech context hints - directory names and reply vocabulary per language

How I built it

Node.js and TypeScript, one Fastify process. @vonage/server-sdk for NCCO and outbound calls, @vonage/client-sdk for the browser leg. Claude for translation with structured output - one frozen system prompt returning translation, back-translation and flags. SQLite via better-sqlite3, no ORM. The board is static HTML plus a small TypeScript bundle with state pushed over server-sent events. Deployed on Fly.io. 47 unit tests over the state machine and the NCCO scripts.

Challenges I ran into

The recogniser could not hear the name. "Marisol" came back as "Mary Sol", "Maricel", even "merry soul" - and often only in the second or third alternative. Exact-match lookup failed every run. Fixed with a five-tier matcher over all recogniser alternatives (exact, word-in-sentence, despaced, length-aware Levenshtein, per-word) that returns undefined on ambiguity rather than guessing the wrong person.

Replies were being cut in half. endOnSilence: 2 ended the capture on a natural mid-sentence pause - the server had recorded only a fragment. Raising it to 4 with a 30-second maxDuration and per-language vocabulary hints fixed it.

The ring-back was invisible. The Client SDK auto-answered the incoming call instantly, so the most important moment in the product arrived as silence. The board now names the caller, plays a generated ring tone, and offers Answer or Decline.

Speaking English into a Spanish recogniser returns nothing at all, and the first version did nothing with silence, so the call simply ended on her. Now it re-prompts in her language, guarded so a redelivered webhook cannot loop the call.

Accomplishments that I'm proud of

The loop closes. A person with no app, no account and no data plan received a message in her language and answered it in her own words, and those words arrived as speech in a browser on the other side - over the public telephone network, with a machine that checked itself before it spoke in someone else's name.

What I learned

That the interesting problem in machine translation is not accuracy, it is accountability. The read-back gate started as a nicety and became the thing the whole product rests on.

What's next for Ringback

Group broadcast with per-person states; batching routine messages into one call per shift; more live languages (pt-BR and bn-IN are already supported by Vonage TTS and ASR); a PSTN number for the sender as a fallback to the in-app call; a scheduling or EHR hook so the directory is not seeded by hand.


Real calls, real translation, real transcription, real speech recognition. The scenario is staged: the directory is seeded demo data and "Marisol" is a composite played by the builder. Built with AI-assisted coding (Claude Code); the product decisions, the testing, the phone-side verification and the Vonage account are my own.

Built With

Share this project:

Updates

Submission history