Pricing and Credits#
Labs Cloud uses a prepaid minute ledger. One Supafone minute covers hosted agent runtime, Supafone Supervisor work, managed model/TTS/STT access, logs, QA, and optimizer reports.
Pricing data is exposed publicly:
curl https://api.labs.supafone.ai/v1/pricingPlans#
| Plan | Price | Included minutes | Overage | Included numbers |
|---|---|---|---|---|
| Developer | $49/mo | 300 | $0.14/min | 0 |
| Growth | $249/mo | 2,500 | $0.11/min | 3 |
| Scale | $999/mo | 12,000 | $0.085/min | 20 |
The trial signup grants five managed-runtime minutes to the account, not five minutes per API key, agent, device, or process. Browser WebRTC, PSTN, SDK, CLI, and MCP calls that use Supafone-managed infrastructure debit the same account ledger.
Before a managed call starts, Supafone atomically reserves that call's allowed runtime from the account balance. Concurrent calls therefore cannot each spend the same remaining seconds. When a call ends, Supafone settles the connected seconds and refunds the unused reservation. A provider failure cancels the reservation; expired abandoned reservations are reclaimed. The balance response may include active_reserved_seconds so clients can distinguish spendable time from time held by calls already starting or in progress.
What a recording costs#
Supafone does not add a second fee just because a call is recorded. Hosted calls debit the connected voice-agent runtime from the minute ledger. The recording artifact is included. Transcription, supervisor/Supafone Supervisor work, QA, and longer-term storage remain separate internal meters so usage and margins stay auditable; the customer still sees one clear Supafone balance.
Usage Meters#
| Meter | Unit | Notes |
|---|---|---|
agent_minute | minute | Live hosted voice-agent runtime |
self_healing | second | Supervisor, QA, optimizer, and silent-guidance work |
tts | spoken second | Hosted voice output |
stt | audio second | Prerecorded and live transcription |
shared_number_pool | pooled route | Default shared Supafone number pool |
managed_number | number-month | Dedicated Supafone-managed phone number |
premium_number | number-month | $3/month premium number |
Balance#
curl https://api.labs.supafone.ai/v1/billing/balance \
-H "Authorization: Bearer $SUPAFONE_LABS_API_KEY"Response shape:
{
"plan": "growth",
"seconds_remaining": 150000,
"minutes_remaining": 2500,
"top_up": {
"developer": "https://...",
"growth": "https://...",
"scale": "https://...",
"pricing": "/v1/pricing"
}
}Hosted Stripe Checkout#
The SDK and MCP create Checkout Sessions on the server, so a secret Stripe key never enters a client application or model context:
checkout = client.labs.billing.checkout(
kind="plan",
plan_key="growth",
)
print(checkout["checkout_url"])After payment, poll client.labs.billing.status(checkout_session_id). Use client.labs.billing.portal() to return an authenticated Stripe Customer Portal link for payment methods, invoices, and cancellation. Stripe webhook events are signature-verified and deduplicated before credits or entitlements are granted.
Structured 402 Payment Flow#
When the account cannot reserve another managed call, the API returns HTTP 402 Payment Required before opening a provider session:
{
"detail": {
"code": "managed_minutes_exhausted",
"message": "Add managed minutes to start this call.",
"minutes_remaining": 0,
"checkout_endpoint": "/v1/billing/checkout"
}
}Treat detail.code, not the English message, as the programmatic branch. Create a server-authored Checkout Session through POST /v1/billing/checkout, open the returned checkout_url, and poll GET /v1/billing/checkout/{session_id} until it reports paid. Then retry the original call request. Do not retry a 402 in a tight loop and do not collect card data yourself.
The public clients expose the same flow:
const checkout = await supafone.labs.billing.checkout({
sku: "sf_voice_minutes_400_v1"
});
console.log(checkout.checkout_url);checkout = supafone.labs.billing.checkout(sku="sf_voice_minutes_400_v1")
print(checkout["checkout_url"])supafone account checkout --sku sf_voice_minutes_400_v1The CLI also recognizes a structured 402, requests a Checkout link, and returns it under data.payment while preserving the original error status and usage detail. MCP uses start_billing_checkout followed by get_billing_checkout.
Stripe Checkout Metadata#
Stripe grants are controlled by checkout metadata:
{
"plan_key": "developer",
"included_minutes": "300",
"credits_minutes": "400"
}Rules:
plan_keysupportsdeveloper,growth, andscale.- Subscription checkout grants
included_minutes, or the plan default. - One-time credit packs use
credits_minuteswhen present. invoice.paidrenewals grant the subscription minutes again.- If an account exists for the email, credits land on the account balance.
- Otherwise credits land on the newest active key, or a new
sl_live_...key is
issued.
Number Billing#
The safe default is the shared pool:
{
"default_strategy": "default_pool",
"default_pool_price_monthly": 0
}Dedicated and premium numbers are paid number-month choices:
{
"dedicated_number_price_monthly": 3,
"premium_number_price_monthly": 3
}Product flows should make number purchases explicit. Do not silently upgrade a shared-pool user to a dedicated or premium number.
For SDK and MCP callers, the first paid-number request returns a hosted checkout_url. After Stripe reports paid, repeat the purchase with the billing_checkout_session_id. Supafone claims the single-use entitlement, provisions the carrier number, then consumes the entitlement. A retry returns the already-provisioned number rather than buying another one.