A working AI phone front desk in ~150 lines: provision a real US number with an AI agent answering it, receive signed call webhooks, and view transcripts & recordings — all on the KwickPhone API. No Twilio to wire up, no speech stack to assemble; you get a live number and clean JSON.
One-click deploy the dashboard + webhook receiver. Render prompts for KP_API_KEY and
KP_WEBHOOK_SECRET; then point your number's webhook_url at
https://<your-service>.onrender.com/webhooks/kp. (Free tier: ephemeral disk — received events reset
on restart — and idle spin-down, so the first webhook after a quiet spell hits a cold start.)
Heads up — this uses real money. Provisioning a number costs $5/month and live AI talk time is billed per minute. Use the free test numbers / starter credits on your account while you build, and release numbers you're done with. See pricing.
provision.js— buys a number and prints itswebhook_secret(shown once).server.js— a tiny dashboard that lists your numbers, shows recent calls live from the API, and receivescall.completedwebhooks (signature-verified) — with transcript/recording links proxied server-side so your API key never reaches the browser.
git clone https://github.com/<you>/ai-front-desk-demo
cd ai-front-desk-demo
npm install
cp .env.example .env # then add your KP_API_KEY (from https://kwickphone.com/app/developer)- Fund your API balance at https://kwickphone.com/app/billing (provisioning needs ≥ $5).
- Expose a public URL for webhooks (local dev:
ngrok http 3000→ copy the https URL). - Provision a number, pointing its webhook at your public URL:
Copy the printed
node provision.js +13465551234 346 https://YOUR-PUBLIC-HOST/webhooks/kp
webhook_secretinto.envasKP_WEBHOOK_SECRET. - Run the dashboard:
Call your new number. The call appears under "Recent calls", and a signed
npm start # http://localhost:3000call.completedwebhook lands under "Webhook events received".
KwickPhone signs each delivery: X-KwickPhone-Signature: v1=<hmac> where the HMAC-SHA256 is computed
over "{timestamp}.{rawBody}" keyed by the number's webhook_secret. lib/verify.js recomputes it
over the raw body and compares in constant time, and rejects stale timestamps (replay protection).
Always verify on a public HTTPS endpoint — KwickPhone refuses to deliver to private/internal hosts.
provision.js CLI: provision a number, print its webhook_secret
server.js dashboard + webhook receiver + transcript/recording proxies
lib/kp.js tiny KwickPhone API client (server-side; key stays on the server)
lib/verify.js webhook signature verification (HMAC + replay guard)
python/ the same demo in Python (Flask) — see python/README.md
The identical demo is in python/ — provision.py, server.py (Flask),
lib/kp.py, and lib/verify.py. Same API, same signed-webhook scheme. See python/README.md.
Want a fuller example? chess-club-receptionist takes the next step — it acts on calls instead of just displaying them: extracts structured intake from each transcript (heuristic or Claude), builds an RSVP roster + questions queue + leads, and sends the organizer a nightly email/Slack digest.
Any Node host (Render, Railway, Fly, a VPS). Set KP_API_KEY and KP_WEBHOOK_SECRET as environment
variables (never commit .env). Point your number's webhook_url at https://<your-host>/webhooks/kp.
- Never commit secrets.
.envanddata.jsonare gitignored. - The API key is used only server-side; the browser never sees it.
- Webhook signatures are verified before any event is trusted.
Full API reference: https://kwickphone.com/integrations/api/reference/ · Overview: https://kwickphone.com/integrations/api/
MIT licensed.