Usage metering
Billing accuracy matters. This page documents the exact counting rules.
What we count
| Metric | Counted when |
|---|---|
| Session | WebRTC session opens and stays open for ≥ 5 seconds |
| Minute | Each second of session duration, summed across all sessions, rounded up to the next full minute per billing period |
| Function call | Every conversation.item.tool_call the AI emits that the widget executes |
| DB query | Every POST /v1/:siteId/query call — no matter the result |
| Image description | Every POST /v1/:siteId/describe-image call |
What we do NOT count
- Dropped connections < 5 seconds — user clicked the orb, changed their mind, hung up
- Failed token mint — if OpenAI / your key rejected us before WebRTC opened
- Our own test sessions — the “Test voice” button in the dashboard is free and tagged separately
- Silent failed sessions — if the WebRTC handshake failed, no minutes charged (we log the failure)
Session boundaries
A session starts when the WebRTC peer connection emits connectionstatechange === 'connected'.
A session ends on any of:
- User clicks the orb again (hang up)
- User closes the tab
- Inactivity timeout (default 5 min of no speaking on either side)
- 2-hour hard cap
- Network error causing both ICE and WebRTC to give up
The session_end event is emitted within ~1s of the end; duration_seconds is the measured length.
Minute rounding
For billing, we round per billing period, not per session:
- Your monthly minutes = sum of every session’s seconds ÷ 60, ceil.
- So 30 sessions of 90 seconds each = 30 × 90 = 2,700 seconds = 45 minutes (not 30 × 2 = 60).
This is cheaper for you than per-session rounding.
Visibility
- Dashboard → Usage — a live bar showing
current_month / monthly_limit, updated ~every 60s. - Dashboard → Analytics — drill in by day, by site, by function type.
- Analytics API —
/v1/:siteId/analytics/summary(see analytics). - Webhooks — subscribe to
usage.thresholdevents (fires at 50%, 80%, 100%, 150% of monthly limit).
Billing period
- Free plan — calendar month (UTC), resets at midnight UTC on the 1st.
- Paid plans — billing day = your signup day. E.g. sign up April 17 → billing period is always 17th → 17th. Resets mid-month.
Change your billing date via Stripe (Dashboard → Billing → Invoice History → request date change).
Timezone of events
event.created_atis always UTC, ISO 8601.- The dashboard UI localizes to your browser’s timezone.
- Business-hour calculations (when the AI answers “are we open?”) use your site’s configured timezone (see time zones), not UTC.
Cost computation
For managed plans:
cost_centsis the amount Spelo will bill you for that session.- Computed from session duration × plan’s per-minute rate (bundled + overage).
- Settled at end of billing period.
For BYOK:
cost_centsis Spelo’s estimate of the OpenAI cost.- Based on token counts OpenAI reports in the session summary.
- Actual OpenAI invoice might differ slightly (±3%) due to rounding / pricing updates.
- Spelo’s own fee for BYOK is 0 — you pay for the platform via your plan’s fixed monthly fee.
Reconciliation
Once per day we export per-site usage to your Stripe customer record. If a session isn’t in your invoice that should be (or vice versa), tell support with the session_id and we’ll investigate.
Multi-site accounting
If you run multiple sites in one workspace:
- All minutes count against the workspace’s plan limit.
- Per-site breakdowns in the dashboard show which site used what.
- Some plans support per-site budgets (Enterprise) — a site that hits its budget self-disables.
Testing without burning minutes
Two ways:
- Dashboard → Test voice. Uses a separate test-mode OpenAI key (or your BYOK key, but still flagged as
test_mode: true). - Test-mode API key. API keys prefixed
vk_test_work against staging data. No real sessions.
Suspicious activity
We monitor for abuse patterns (many 5-second sessions from one IP, identical transcripts, scripted behavior). Detected abuse is logged to our side and we notify you if it affects your bill. You can request credits for confirmed abuse.
Export
- CSV export in the dashboard
- Webhook subscription for realtime push
- SSE stream for ops dashboards