Billing and usage

Read your plan, consumption and limits from the API, and handle the errors plan limits return.
View as Markdown

Every Jelliu workspace runs on a plan. Plans do not differ by which features they unlock: every product capability is available on every paid plan, with one exception (custom cloned voices, Enterprise only). Plans differ by how much you can use: call minutes, AI replies on text channels, agents, campaigns, contacts, phone numbers, concurrent calls, knowledge base size and connected apps.

This page shows how to read that from the API so your integration can check headroom before it acts, and how to handle the responses when a limit is reached.

How it works

Limits are checked at two moments:

  • When you create something that counts against the plan (an agent, a campaign, contacts, a knowledge file, a connected app, a phone number). If the cap is reached, creation fails with 403 BILLING_ERROR.
  • When the platform consumes something (a call is placed or answered, an agent replies on a text channel). If the allowance is used up, the call is refused or the agent does not reply.

Endpoints

MethodPathReturnsKey needed
GET/api/billing/subscriptionPlan, status and periodread
GET/api/billing/usageMinutes and AI replies used in the current windowfull
GET/api/billing/limitsEvery limit and feature flag of the planfull
GET/api/billing/ai-usageWeekly credits for the in-product AI assistant and prompt generatorread
GET/api/billing/invoicesThe 24 most recent invoicesfull
GET/api/billing/chargesThe 24 most recent chargesfull
GET/api/billing/payment-methodsSaved cardsfull

Usage, limits, invoices, charges and payment methods are financial information, restricted to workspace administrators and the billing role. For an API key that means the full scope; a read or write key receives 403 with This operation requires an API key with the 'full' scope. See API keys.

All /api/billing routes share a limit of 15 requests per minute per workspace. Read limits once and cache them rather than calling before every operation.

Get the subscription

GET /api/billing/subscription

curl -sS "https://api.jelliu.co/api/billing/subscription" \
-H "Authorization: Bearer $JELLIU_API_KEY"
{
"data": {
"subscription": {
"tier": "growth",
"status": "active",
"current_period_end": "2026-10-03T14:12:09.000Z",
"cancel_at_period_end": false,
"trial_end": null,
"max_agents": 5,
"max_concurrent_calls": 10,
"included_minutes": 620
}
}
}
FieldDescription
tierstarter, growth, business or enterprise.
statusactive, trialing or past_due. Other states are not active, and the response is { "subscription": null }.
current_period_endEnd of the current billing period.
cancel_at_period_endtrue if the plan was cancelled and ends at current_period_end.
trial_endEnd of the trial, or null.
max_agents, max_concurrent_calls, included_minutesBase plan values. For the effective agent limit including add-ons, read /api/billing/limits.

Get usage

GET /api/billing/usage

curl -sS "https://api.jelliu.co/api/billing/usage" \
-H "Authorization: Bearer $JELLIU_API_KEY"
{
"data": {
"minutesUsed": 512,
"includedMinutes": 620,
"bonusMinutes": 0,
"overageMinutes": 0,
"overageCostCents": 0,
"usagePercentage": 82.58,
"isTrialing": false,
"trialMinutesLeft": 0,
"alertTriggered": true,
"chatMessagesUsed": 2210,
"includedChatMessages": 4000,
"chatUsagePercentage": 55.25,
"channels": ["voice", "whatsapp", "webchat", "email"],
"excludedMetrics": []
}
}
FieldDescription
minutesUsedCall minutes consumed in the current usage window.
includedMinutesMinutes included in the plan for the window. During a trial, the trial allowance.
bonusMinutesRemaining minutes from purchased minute packs. They sit on top of the included minutes.
overageMinutesMinutes beyond included plus bonus minutes. Always 0 during a trial.
overageCostCentsThe overage minutes priced at your plan’s overage rate, in US cents.
usagePercentageminutesUsed over included plus bonus minutes, as a percentage (can exceed 100).
isTrialing, trialMinutesLeftTrial state and the minutes left in it.
alertTriggeredtrue once usage reaches 80% of included plus bonus minutes.
chatMessagesUsedAI replies sent on text channels in the window.
includedChatMessagesThe plan’s AI reply allowance. -1 means unlimited.
chatUsagePercentage0 to 100, or 0 when the allowance is unlimited.
channelsChannels available on the plan.

Without an active plan, every number is 0 and channels is ["voice"]. The response is cached for up to 30 seconds.

Get limits

GET /api/billing/limits returns the effective limits for the workspace, including purchased agent add-ons, and the plan’s feature flags. It is cached for up to 5 minutes (Cache-Control: private, max-age=300), so a plan change can take that long to show.

{
"data": {
"tier": "growth",
"maxAgents": 5,
"maxConcurrentCalls": 10,
"includedMinutes": 620,
"maxContacts": 2000,
"maxCampaigns": 3,
"maxKnowledgeFiles": 25,
"maxKnowledgeBytes": 52428800,
"maxTeamMembers": 10,
"maxConnectors": 5,
"maxMcpServersPerAgent": 3,
"audioRetentionDays": 30,
"maxIntegrations": 9999,
"maxPhoneNumbers": 3,
"includedChatMessages": 4000,
"channels": ["voice", "whatsapp", "webchat", "email"],
"features": {
"voiceCloning": false,
"advancedDashboard": true,
"abTesting": true,
"reportExport": true,
"customReports": true,
"webhook": true,
"mcpGateway": true,
"transcriptRetentionDays": 30
}
}
}

The example shows a subset of features; the real object has more flags. A negative value (-1) means unlimited. Very large values such as 9999 are also effectively unlimited.

When the workspace has no active plan (the trial ended, the plan was cancelled, or it never subscribed), tier is "none", every count limit is 0 and channels is empty. The workspace can still use the dashboard and choose a plan, but it cannot create resources, place calls or get AI replies.

Plan limits

The limits in effect when this page was written. Read /api/billing/limits for the values that apply to your workspace; they are the ones Jelliu enforces.

LimitStarterGrowthBusinessEnterprise
Agents2512By contract
Concurrent calls31025By contract
Call minutes included per month2006201,400By contract
AI replies on text channels per month1,2004,0009,000Unlimited
Active campaigns13UnlimitedUnlimited
Contacts5002,00020,000By contract
Knowledge files525100By contract
Knowledge base size10 MB50 MB200 MBUnlimited
Connected apps2510Unlimited
MCP servers per agent1310Unlimited
Phone numbers1310By contract
Team members5102020
Transcript retention7 days30 days90 daysUnlimited
Call audio retention7 days30 days90 daysKept until you delete it

Agent add-ons raise the agent limit on Starter, Growth and Business; maxAgents in /api/billing/limits already includes them.

How consumption works

Call minutes

  • Included minutes are a monthly allowance. On an annual plan, the usage window is the current month inside the annual period, so minutes reset every month.
  • Minute packs add bonus minutes on top of the plan’s included minutes.
  • Past included plus bonus minutes, calls continue as overage, billed automatically to the card on file.
  • Overage has a ceiling. On Starter, Growth and Business, calls are refused once usage reaches the included minutes plus purchased pack minutes plus half of the included minutes again (for example, 300 minutes on a 200-minute plan with no packs). Buying a minute pack or upgrading raises the ceiling; otherwise it resets with the next usage window. Enterprise has no ceiling.
  • Trials are capped at 15 minutes of calls and never generate overage. A single call is also cut off when the trial minutes run out.

AI replies on text channels

  • Each AI reply on WhatsApp, email, web chat, Instagram or Messenger counts against includedChatMessages. A reply is counted only after it is actually produced for delivery, so failed sends do not consume allowance.
  • The allowance is not billed per message and has no overage. When it is used up, the agent stops replying on text channels until the window renews or the plan is upgraded. Voice calls are not affected.
  • Separately, WhatsApp and email have a daily per-workspace send cap as a safety limit. See WhatsApp and Email.

Notifications

The workspace receives in-app notifications at 80% and 100% of both call minutes and AI replies, and when calls are paused at the overage ceiling. There is no webhook for usage thresholds yet: usage.threshold_reached appears in the event catalog but is not sent. Poll /api/billing/usage if you need to react programmatically.

Handling limit errors

Plan limits return BILLING_ERROR. The HTTP status is 403 for most limits and 402 for phone numbers and for plan changes without a payment method. Branch on error.code, and use metadata to show the user what happened.

Resource caps

Creating an agent, campaign, contact, knowledge file, connected app or MCP server assignment beyond the plan’s cap:

{
"error": {
"code": "BILLING_ERROR",
"message": "Agent limit reached (5 agents on the growth plan). Upgrade your plan in Settings → Plan or purchase agent add-ons.",
"metadata": { "limit": 5, "current": 5, "tier": "growth" }
}
}

A bulk contact import that would cross the cap is rejected as a whole, and reports the batch size:

{
"error": {
"code": "BILLING_ERROR",
"message": "Import of 800 contacts would exceed the plan limit (2000 contacts on the growth plan; currently 1500). Reduce the batch or upgrade your plan in Settings → Plan.",
"metadata": { "limit": 2000, "current": 1500, "batch": 800, "tier": "growth" }
}
}
metadata keyMeaning
limitThe plan’s cap.
currentHow many exist now.
batchItems in the rejected request, when more than one.
tierThe workspace’s plan, or none.

Messages you may see, verbatim:

Limitmessage
AgentsAgent limit reached (… agents on the … plan). Upgrade your plan in Settings → Plan or purchase agent add-ons.
CampaignsCampaign limit reached (… campaigns on the … plan). Upgrade your plan in Settings → Plan.
ContactsContact limit reached (… contacts on the … plan). Upgrade your plan in Settings → Plan.
Knowledge filesKnowledge file limit reached (… files on the … plan). Upgrade your plan in Settings → Plan for more files.
Knowledge sizeKnowledge base size limit reached (… MB on the … plan). Upgrade your plan in Settings → Plan for more.
Connected appsConnected apps limit reached (… on the … plan). Upgrade your plan in Settings → Plan for more.
No active planYour free trial has ended (or no plan is active). Choose a plan in Settings → Plan to continue.

Calls refused

POST /api/calls is refused with 403 BILLING_ERROR when the workspace has no active plan, the trial minutes are used up, or the overage ceiling is reached:

{
"error": {
"code": "BILLING_ERROR",
"message": "You have used all your trial minutes. Upgrade to a paid plan in Settings → Plan to keep calling.",
"metadata": { "tier": "starter" }
}
}

This route returns the same message for an exhausted trial and for a paid plan that reached its overage ceiling. Do not rely on the wording: check /api/billing/usage (isTrialing, minutesUsed, includedMinutes, bonusMinutes) to tell the cases apart.

Campaign calls are checked the same way before each dial. Concurrency is separate: exceeding the plan’s concurrent calls returns 429 MAX_CONCURRENT_CALLS_REACHED and is safe to retry. See Errors.

AI replies exhausted

When the AI reply allowance is used up, the agent does not answer on text channels. The workspace gets an in-app notification, and the error recorded for the conversation is in Spanish, as it is shown to the workspace owner:

  • With a plan: Llegaste al límite mensual de mensajes de IA (… mensajes del plan …). Sube de plan en Ajustes → Plan.
  • Without a plan: Tu plan no está activo, así que la IA no está respondiendo en este canal. Elige un plan en Ajustes → Plan para volver a activarla.

Visitors on the web chat widget never see this text; the widget shows its own neutral message.

Phone numbers

Adding a phone number beyond maxPhoneNumbers returns 402 BILLING_ERROR:

{
"error": {
"code": "BILLING_ERROR",
"message": "Your growth plan allows up to 3 phone numbers and this workspace already has 3. Assign an existing number to this agent under Numbers, or upgrade your plan.",
"metadata": { "tier": "growth" }
}
}

The wording depends on the path (provisioning, bringing your own number, or when the plan still allows buying add-on numbers), so rely on the code and status. See Phone numbers.

Feature gates

A few routes check a plan feature flag. When the plan does not include it, they return 403 BILLING_ERROR with metadata.tier and a message such as Advanced analytics is not available on the none plan. Upgrade your plan to use it. All current plans include these features:

Feature flagRoutes
advancedDashboard/api/analytics/* (the lightweight /api/dashboard is not gated)
customReportsPOST /api/reports, GET /api/reports/types
reportExportPOST /api/exports
webhook/api/webhooks management (deliveries to existing webhooks are never stopped by a plan change)
abTesting/api/agents/{agentId}/ab-tests
mcpGatewayThe MCP server (JSON-RPC error -32003)

The one feature that differs by plan is custom cloned voices. Assigning a cloned voice to an agent outside Enterprise returns 403 BILLING_ERROR: Custom cloned voices are an Enterprise feature (not available on the … plan). Upgrade to use a cloned brand voice.

In-product AI credits

The dashboard’s AI assistant and prompt generator have their own weekly budget, separate from agent replies. GET /api/billing/ai-usage returns it in credits (1 credit is 1,000 tokens):

{
"data": {
"weekStart": "2026-09-14",
"resetsAt": "2026-09-21T00:00:00.000Z",
"ask_ai": { "used": 41, "limit": 660, "remaining": 619 },
"prompt_gen": { "used": 12, "limit": 248, "remaining": 236 }
}
}

limit and remaining are -1 when unlimited. When a budget is used up, those features return 429 AI_WEEKLY_CAP_REACHED with metadata.kind, metadata.tier, metadata.weekStart and metadata.limitTokens. Your agents keep working.

Invoices and charges

GET /api/billing/invoices and GET /api/billing/charges return the 24 most recent items, newest first. Amounts are in the smallest currency unit (cents).

Invoice fieldCharge field
id, number, status, amountDue, amountPaid, currency, created, hostedInvoiceUrl, invoicePdfid, amount, currency, status, description, created, receiptUrl

Both return [] if the workspace has no billing account yet. Responses are sent with Cache-Control: no-store.

Changing the plan and buying add-ons

Choosing or changing a plan, buying minute packs, agent add-ons or extra phone numbers, and managing cards are done in the dashboard under Settings → Plan. These operations are restricted to the workspace owner and the billing role, are not available through the MCP server, and several of them hand off to a hosted payment page that a person must complete. Do not automate them from an integration.

A good integration pattern: read /api/billing/limits once when your integration starts (and again after any BILLING_ERROR), check /api/billing/usage before launching a large campaign, and surface BILLING_ERROR messages to an administrator with a link to Settings → Plan rather than retrying.

Errors

StatusCodeWhen
402BILLING_ERRORPhone number cap reached, or a plan change without a payment method (Add a payment method before changing your plan.).
403BILLING_ERRORA resource cap, a refused call, or a plan feature gate.
403FORBIDDENThe key lacks the full scope for usage, limits, invoices, charges or payment methods.
429MAX_CONCURRENT_CALLS_REACHEDThe plan’s concurrent call limit. Retry later.
429AI_WEEKLY_CAP_REACHEDThe weekly in-product AI budget is used up.
429RATE_LIMIT_EXCEEDEDMore than 15 requests per minute on /api/billing. Honor Retry-After.

BILLING_ERROR is not retryable: the same request fails until the plan, the usage window or the resource count changes.