Inspiration

I'm a solo builder from a remote village in Assam, building everything from an Android phone with no laptop and no budget. When I saw CALL-E, I thought about the gap between "data you already have" and "action in the real world" — a spreadsheet full of names and phone numbers is useless until someone actually picks up the phone and talks to each person. I wanted SheetCall to close that gap: point it at any spreadsheet, and it turns rows into real, structured phone calls.

What it does

SheetCall is a web operator console built on the CALL-E API. It loads records from five different sources — paste CSV, an Excel/CSV file, a Google Sheets link, paste JSON, or Airtable — and runs each one through a small state machine before anything happens on a real phone:

  1. Validate — E.164 phone format, a CALL-E-supported region, a matching locale, not on a do-not-call list, not a duplicate.
  2. Eligibility — is it currently a reasonable local hour to call in that region? Calling-hour windows are based on real regulatory guidance (TRAI/TCCCPR for India, TCPA for the US, Ofcom for the UK), not an arbitrary default.
  3. Call — handed to CALL-E's Calls API.
  4. Classify — the terminal result comes back and is sorted into Done (confident), Review (a human should check), No answer, or Error, with the confidence score and evidence attached.

A Dry Run mode exercises the exact same pipeline with a local fixture and places no real call, so an operator can catch bad data before spending a credit or ringing a real phone.

How I built it

Everything was built from an Android phone — no laptop. The original plan was a Google Sheets Apps Script add-on, but the Apps Script editor was unusable on a phone (unreadably small text, no working pinch-zoom), so I rebuilt it as a plain static web app with Vercel serverless functions, deployed straight from GitHub on every push.

The architecture keeps the state machine (runtime.js) completely storage-agnostic and provider-agnostic — it doesn't know it's running on Vercel, or that CALL-E is the call provider, or that the source was an Excel file rather than a paste. An adapter layer (sources.js) normalizes all five input types into one record shape, and a separate adapter (calle.js) is the only file that ever touches the CALL-E API key.

Challenges I ran into

  • Security without a backend team: the CALL-E API key had to live only in a server environment variable, never in the browser. CALL-E's webhook is also unsigned, so the webhook handler trusts nothing from the payload except the call_id, and re-fetches the authoritative call state from CALL-E's own Calls API before updating anything.
  • A real regulatory bug: my first version had a hardcoded 9am-6pm, Monday-Friday calling window for every one of CALL-E's 42 supported regions — not based on anything real. I researched actual telemarketing-hour rules (India's TCCCPR, the US TCPA, UK Ofcom) and rebuilt the windows per-region instead of guessing.
  • A silent language-matching bug: the validator was deriving a region's expected language code by taking the first two letters of the English language name (e.g. "German" -> "ge"), which is wrong for German, Chinese, Portuguese, Malay, and Turkish. It was silently blocking valid German-locale records. Fixed with an explicit ISO 639-1 lookup table, caught by writing a small local simulation script against the actual record set I was testing.
  • Building entirely on a phone: every file edit, every deploy, every GitHub PR in this project went through a phone browser. No terminal, no IDE.

Accomplishments that I'm proud of

Getting a real, working outbound phone call to go from a spreadsheet row to my own phone ringing, with the AI actually discussing the invoice and the result classified automatically back in the app — entirely built and operated from a phone.

What I learned

That a "simple" feature like a calling-hour window is never actually simple once you look at the real regulations behind it, and that host-agnostic design (keeping the runtime ignorant of the storage layer, the call provider, and the input source) makes a project much easier to extend under time pressure — adding four more input sources on top of the original CSV-paste-only version didn't require touching the state machine at all.

What's next for SheetCall

Surfacing the CALL-E call ID and a timestamp directly in the record detail view, adding researched calling-hour rules for more of CALL-E's 42 supported regions (only India, the US, and the UK are backed by real regulatory research today), and exploring SheetCall as the first adapter of a broader "universal workflow runtime" — the same state machine running against other data sources and other action providers, not just phone calls.

Built With

Share this project:

Updates

Submission history