voice-cost-clock
Live, daily-refreshed price clock for production voice-agent APIs.
The voice-agent space exploded in May 2026 (AssemblyAI launched their Voice
Agent API, Vapi raised, Retell pushed Business tier, Deepgram switched to
concurrency-metered, OpenAI cut Realtime output rates). Pricing today spans a
5x range ($0.07 → $0.35/min) and is buried inside SDK docs and pricing
footnotes. voice-cost-clock is the live, dated, side-by-side view that
buyers need.
What it does
- Fetches each provider's public pricing page (or a documented fallback URL) on a
node-cronschedule (every 6 hours by default). - Extracts per-minute base rate, telephony per-leg cost, and compliance-tier add-ons via provider-specific regex.
- Stores every snapshot in better-sqlite3 (WAL) so price history per provider is queryable.
- Renders a dark-theme single-page dashboard with:
- Leaderboard ranked cheapest → most expensive across four preset scenarios.
- Recent price changes feed (auto-diffed between snapshots).
- Custom calculator for arbitrary
minutes/month × avg-duration × telephony × compliancescenarios. - Per-provider detail card with a Chart.js price-history sparkline and the raw scraped snippet.
No mock data
Every number you see in the UI comes from a live fetch() against the
provider's public pricing page within the last refresh window. Rows whose
fetcher fails (timeout, 404, regex no-match, or JS-rendered SPA) are surfaced
as unparseable with the actual error — never replaced with synthetic
values.
Telephony per-leg is the one disclosed baseline assumption (Twilio
standard rate, $0.013/leg) — every provider's notes field discloses this
explicitly when it's applied.
Data sources
| slug | provider | URL | refresh |
|---|---|---|---|
| vapi | Vapi | https://vapi.ai/pricing | 6h |
| retell | Retell AI | https://www.retellai.com/pricing | 6h |
| bland | Bland AI | https://www.bland.ai/pricing | 6h |
| deepgram-voice | Deepgram Voice Agent | https://deepgram.com/pricing | 6h |
| elevenlabs | ElevenLabs Conversational AI | https://elevenlabs.io/pricing | 6h |
| assemblyai | AssemblyAI Voice Agent | https://www.assemblyai.com/pricing | 6h |
| livekit | LiveKit Agents | https://livekit.io/pricing | 6h |
| openai-realtime | OpenAI Realtime API | https://openai.com/api/pricing/ | 6h |
Each fetcher has a primary URL and a documented fallback URL it tries on
failure. Fallback choices are visible in fetchers/<slug>.js.
Endpoints (all public, no auth)
| Method | Path | Description |
|---|---|---|
| GET | /voice-cost-clock/ | Single-page dashboard |
| GET | /voice-cost-clock/health | Smoke check (RNDLAB orchestrator hits this) |
| GET | /voice-cost-clock/api/stats | Counters, last refresh timestamp |
| GET | /voice-cost-clock/api/providers | Providers + latest snapshot for each |
| GET | /voice-cost-clock/api/leaderboard?scenario=default\|customer_support\|outbound\|assistant | Ranked TCO array |
| GET | /voice-cost-clock/api/history/:slug?limit=60 | Time-series of snapshots |
| GET | /voice-cost-clock/api/changes?limit=50 | Recent diffed price-change events |
| GET | /voice-cost-clock/api/scenarios | Scenario definitions |
| POST | /voice-cost-clock/api/calculate | Custom-scenario calculator |
| POST | /voice-cost-clock/api/refresh | Manual re-scrape (idempotent, single-flight) |
Run locally
npm install
cp .env.example .env
node server.js
# http://localhost:4887/voice-cost-clock/
better-sqlite3 ships a prebuilt binary for darwin-arm64 and linux-x64/arm64;
no toolchain required on the deploy host.
Configuration
| env | default | purpose |
|---|---|---|
| PORT | 4887 | HTTP listen port |
| BASE_PATH | /voice-cost-clock | Nginx-style sub-path |
| DB_PATH | ./data/voice-cost-clock.db | SQLite file |
| REFRESH_CRON | 0 /6 | node-cron schedule |
| COLD_START_DELAY_MS | 5000 | Delay after listen before first refresh |
| FETCH_TIMEOUT_MS | 15000 | Per-provider HTTP timeout |
| FETCH_USER_AGENT | voice-cost-clock/1.0 (+https://holyai.me/voice-cost-clock) | UA string |
No API keys are required — every source is a public pricing page. There is
no ADMIN_PASS, no Basic Auth, no /admin. All endpoints are public on
purpose; this is a price-watch, not a vault.
Deploy
See DEPLOY_MANIFEST.json. The RNDLAB orchestrator picks it up viacowork-deploy-bridge/queue.jsonl:
target_dir:/var/www/projects/voice-cost-clocksystemd_name:voice-cost-clocknginx_route:/voice-cost-clockupstream:http://127.0.0.1:4887- Health check:
GET /voice-cost-clock/healthreturns 200 with provider count.
Scenarios
| key | minutes/mo | avg call | telephony | HIPAA |
|---|---|---|---|---|
| default | 1000 | 5 min | yes | no |
| customer_support | 5000 | 8 min | yes | no |
| outbound | 10000 | 2 min | yes | no |
| assistant | 500 | 30 sec | no | no |
The calculator endpoint accepts any combination via POST body.
Methodology disclosure
This is a price-watch. Provider quality, latency, language coverage, compliance
posture, and integration burden vary widely — compare those independently.
Token-billed providers (OpenAI Realtime) are converted to per-minute using an
explicit audio-token assumption documented in their fetcher
(fetchers/openai-realtime.js).
License
MIT.
Co-author
Built by Cowork (Claude Opus 4.7).