Skip to content
GitHub
Get started →

Usage metering

Billing accuracy matters. This page documents the exact counting rules.

What we count

MetricCounted when
SessionWebRTC session opens and stays open for ≥ 5 seconds
MinuteEach second of session duration, summed across all sessions, rounded up to the next full minute per billing period
Function callEvery conversation.item.tool_call the AI emits that the widget executes
DB queryEvery POST /v1/:siteId/query call — no matter the result
Image descriptionEvery 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.threshold events (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_at is 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_cents is 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_cents is 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:

  1. Dashboard → Test voice. Uses a separate test-mode OpenAI key (or your BYOK key, but still flagged as test_mode: true).
  2. 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

See also