Billing and credits
Every send and call is paid from the workspace’s credit balance, and every
price, preview and report is in credits; no answer carries a money amount.
A send’s own cost is billed_credits on its status (SMS and calls; WhatsApp
sends answer null), a campaign preview shows cost_credits before you
start it, and GET /v1/campaigns/{id}/usage says what a campaign has cost.
Credits and balance
Section titled “Credits and balance”Read the balance with GET /v1/balance (any key of the workspace):
curl https://api.omniocto.com/v1/balance \ -H "Authorization: Bearer $OMNI_OCTO_API_KEY"{ "object": "balance", "credits": 1000, "paid_credits": 800, "bonus_credits": 200, "bonus_expires_at": "2026-11-01T00:00:00.000Z", "pending_credits": 12.5, "available_credits": 987.5, "suspended": false, "suspended_reason": null, "tier": 2, "has_payment_method": true, "auto_recharge_disabled": false, "plan": { "id": "…", "name": "…", "renews_at": "2026-11-01T00:00:00.000Z" }, "updated_at": "2026-10-17T10:00:00.000Z" }creditsis what the workspace holds.paid_creditsis the part you bought or were granted; it never expires.bonus_creditsis the part included with this billing period; it expires atbonus_expires_at, and is used first. Both parts arenullwhen we could not read them just now; otherwise they add up tocredits(both are 0 whencreditsis 0 or below).pending_creditsis this period’s usage that is not yet taken offcredits.available_creditsiscreditsminuspending_credits(never below 0): what you can still spend now.updated_atis when the balance was last read from the billing system: at most about 5 minutes ago, so reading it more often than that does not make it fresher. Every field: Balance.
What each channel costs
Section titled “What each channel costs”SMS and MMS
Section titled “SMS and MMS”| what | price |
|---|---|
| SMS to or from a US or Canada number on one of our numbers | 2 credits per segment |
| MMS (picture or video) to a US or Canada number | 4 credits per message |
| MMS to another +1 region (Puerto Rico, Jamaica, …) | 11.5 credits per message |
| SMS to the UK / Germany / anywhere else | 5.7 / 11.5 / 8.6 credits per segment |
| any text on a number you bring from your own carrier account | 0.1 credits per segment or message (your carrier bills the rest) |
A segment is up to 160 plain characters, or 70 when the text has an emoji or
another character outside the GSM alphabet; a longer text is split into
segments. A reply someone sends to one of our numbers costs the same as a
text to them. A send’s own cost is billed_credits on its status.
Prices, previews and reports are always in credits; no response carries a
money amount. A sender’s mode says whose carrier account it is on:
"managed" (one of ours) or "byo" (a Twilio, Telnyx or Vonage account you
brought, which also bills you separately).
Each WhatsApp message sent from your own WhatsApp Business account (the
usual case) costs 0.1 credits. Meta bills its own charges to you directly;
our credit figure does not include them, so a WhatsApp send’s
billed_credits is null.
A call’s cost so far is billed_credits on GET /v1/calls/{id}; it can still
grow for a few minutes after the call ends (speech and the call’s analysis are
billed as they finish). Per-minute prices are on Settings → Billing in the
dashboard.
A call placed from a number on your own carrier account (a Twilio account you brought, or your own SIP carrier) is not charged our phone-line minute, because your carrier bills you for that minute. It costs a platform fee of 0.1 credits per started minute instead, shown in your usage as “Calls on your own carrier: platform fee”. A call nobody answers costs no fee. The rest of the call (speech, the AI model, the call connection and recording) is billed the same as on one of our numbers, and its minutes still count toward the workspace’s daily call-minute limit.
A campaign’s cost and spending limit
Section titled “A campaign’s cost and spending limit”GET /v1/campaigns/{id}/usage says what a campaign has cost so far, by
category, with its calls’ minutes or its messages. A preview’s cost_credits
is the estimate before you start.
limits.spend_cap_credits (SMS and AI-call campaigns) caps what a campaign may
spend. When the next call would not fit, the campaign pauses with
paused_reason spend_cap and its untouched recipients stay queued. Calls
under way always finish, so a campaign can end a few calls above its cap; for
a small cap, set a low limits.max_concurrent_calls too. Raising the cap is a
person’s act: an API key can set one or lower one, but raising or removing it
on a started campaign is 403 spend_cap_raise_needs_person. Every rule:
Limits and retries.
When billing refuses a request
Section titled “When billing refuses a request”A send the balance cannot cover is
402 insufficient_credits with short_credits, and nothing is sent. A
workspace without a card, or whose subscription has lapsed, is
402 billing_not_eligible (what it means).
Add a card or credits in the dashboard under
Settings → Billing.
Usage and spend
Section titled “Usage and spend”What the credits went on, for any window, with any key of the workspace:
| route | answers |
|---|---|
GET /v1/usage | the total and the groups: by category (default), UTC day and/or label, up to two (group_by=day,category) |
GET /v1/usage/events | one row per charge, newest first, paged (limit, after) |
GET /v1/usage/export | the same rows as one CSV file |
curl "https://api.omniocto.com/v1/usage?group_by=day,category&from=2026-10-01" \ -H "Authorization: Bearer $OMNI_OCTO_API_KEY"{ "object": "usage_report", "from": "2026-10-01T00:00:00.000000Z", "to": "2026-10-29T06:00:00.000000Z", "cycle_start": "2026-10-01T00:00:00.000000Z", "cycle_end": "2026-11-01T00:00:00.000000Z", "category": null, "group_by": ["day", "category"], "total_credits": 1234.5, "events": 812, "groups": [ { "day": "2026-10-18", "category": "phone", "label": null, "credits": 96, "units": null, "unit": null, "events": 40 } ] }- The window.
fromis inclusive andtoexclusive, each an ISO 8601 date (midnight UTC) or instant, at most 400 days apart. Without them the window is the current billing cycle (cycle_start) to now: the usagepending_creditson/v1/balancecounts. A workspace with no billing period counts the last 30 days. - The same rows on all three.
/v1/usageechoes thefromandtoit read. Pass that pair to/v1/usage/eventsand/v1/usage/exportand they answer the same charges: the export’s row count equalsevents. To page through a fixed set, always passfromandto; a default window is worked out again on every page. A charge is recorded a moment before it is committed, so for a complete set for your books pass atoa few minutes in the past. - Categories.
phone(call minutes, attempts, voicemails),recording(call connection and recording),speech(speech-to-text, text-to-speech, realtime voice),ai(AI model tokens),messaging(SMS, MMS and chat channel messages),whatsapp,email,numbers(number rental) andother. Filter withcategory=. The same words as a campaign’s usage. - Labels and units.
labelsays what was charged (SMS outbound (US),AI Tokens (input)); new labels appear as we bill new things.unitsandunit(message,minute,1k_tokens, …) are filled only when you group bylabel: 3 messages and 3 minutes are not 6 of anything. - Totals. Each group’s
creditsis rounded to 4 decimals, so the groups add up tototal_creditsgive or take that rounding. A day with no usage has no group. More than 5,000 groups is400 too_many_groups: narrow the window or group by less. - One charge to its conversation. Each row of
/v1/usage/eventscarriesconversation_id(read it withGET /v1/conversations/{id}),agent_idandcampaign_id. - The export holds at most 250,000 rows; over that it is refused before
any byte (
400 export_too_large), never cut short. One export runs at a time per workspace (429 export_in_progress, retry afterRetry-After). If the connection is cut mid-file the body is incomplete: compare the row count toevents.
The get_usage MCP tool answers GET /v1/usage. Every
field: UsageReport.