Skip to navigation

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

Within limits Cap reached 80% 100% of minutes 100% of AI replies Your request Plan check Request proceeds 403 BILLING_ERRORmetadata: limit, current, tier Usage recorded:call minutes, AI replies Thresholds In-app warning Overage, up to the ceiling Agent stops replying on text channels

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, and several features are refused. See Without an active subscription.

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 cannot be subscribed to until it is marked available there. 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.
kindsubscription_required when the refusal is because the workspace has no active subscription. See Without an active subscription.

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 planTu prueba gratuita terminó (o no hay un plan activo). Elige un plan en Ajustes → Plan para continuar.

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 a paid plan does not include it, they return 403 BILLING_ERROR with metadata.tier and a message such as La función «Analítica avanzada» no está disponible en el plan Starter. Sube de plan para usarla. All current plans include these features, so on a paid plan these gates refuse nobody today. A workspace without an active subscription is refused by all of them, with a different response: see Without an active subscription.

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

features also still carries objectionHandlers and escalationRules. Since 2026-09-15 neither gates anything: the plan check on saving objectionHandlers was removed, and escalationRules was retired from the API. Ignore both flags when deciding what your integration may do.

The one feature that differs by plan is custom cloned voices. Assigning a cloned voice to an agent outside Enterprise returns 403 BILLING_ERROR: La clonación de voz es parte del plan Enterprise. Actualiza tu plan para usar una voz propia.

Without an active subscription

A workspace has an active subscription while its status is active, trialing or past_due (a card being retried is still active). When the trial ends without a plan, or the plan is cancelled or finally unpaid, GET /api/billing/limits reports tier: "none" and the rules below apply until a plan is chosen in Settings → Plan. Nothing is deleted.

What is refused

Features that do work for the workspace, or that push its data somewhere else, need a subscription:

FeatureRefused without a subscriptionStill available
Outbound webhooksEvery POST and PATCH under /api/webhooks: creating, updating, rotating the secret, test, replay, retry, enable and disable. Deliveries are canceled.Every GET under /api/webhooks (webhooks, event types, delivery log and delivery detail), DELETE /api/webhooks/{webhookId}
AnalyticsReads under /api/analytics, including conversation analytics, /api/analytics/analysis/*, KPIs and event readsPOST /api/analytics/events and /events/batch, GET /api/dashboard
ReportsPOST /api/reports, GET /api/reports/typesNone
ExportsPOST /api/exports with type: "analytics"Every other export type, and reading and downloading existing exports
MCP serversPOST /api/mcp-servers, PATCH /api/mcp-servers/{mcpServerId}, POST /api/agents/{agentId}/mcp-serversListing and reading servers, DELETE /api/mcp-servers/{mcpServerId}, DELETE /api/agents/{agentId}/mcp-servers/{mcpServerId}
The MCP serverEvery request (JSON-RPC error -32003)None
A/B testsEvery operation under /api/agents/{agentId}/ab-testsNone
CampaignsPATCH /api/campaigns/{campaignId} with maxRetryAttempts above 0Every other campaign change
Live call monitor (dashboard)Calls in progress are not shownGET /api/calls/concurrency, which every workspace can read on every plan

Objection handlers are no longer gated (2026-09-15). Saving a non-empty objectionHandlers on an agent used to be refused without an active subscription. Every paid tier already allowed it, so in practice the gate only ever caught unsubscribed workspaces — and what it blocked was a customer supplying their own answers instead of ours, which is the same capability either way. It is gone: every plan can save its own objection answers. escalationRules, which was listed here alongside it, was retired from the API on the same day.

Creating agents, campaigns, contacts, knowledge files, connected apps and phone numbers is also refused, because every count limit is 0 (see Resource caps), and so are calls and AI replies.

The REST routes answer 403 with BILLING_ERROR. metadata.kind is subscription_required, which tells this refusal apart from a plan that lacks a feature. The message names the feature, for example for webhooks:

{
"error": {
"code": "BILLING_ERROR",
"message": "«Webhooks salientes» requiere una suscripción activa. Este espacio de trabajo no tiene un plan activo: elige uno en Ajustes → Plan para continuar. Tus datos siguen disponibles para consultar y exportar.",
"metadata": { "tier": "none", "kind": "subscription_required" }
}
}

The feature names in the message are Webhooks salientes, Analítica avanzada, Reportes personalizados, Exportación de analítica, Servidores MCP, Pruebas A/B and Reintentos automáticos de llamada. Branch on metadata.kind, not on the message. (Manejo de objeciones and Reglas de escalamiento used to appear here; neither is refused any more.)

The MCP server answers 403 with a JSON-RPC error instead:

{
"jsonrpc": "2.0",
"error": {
"code": -32003,
"message": "Este espacio de trabajo no tiene una suscripción activa, así que el gateway MCP no está disponible. Actívala en Ajustes → Plan."
},
"id": null
}

Webhook deliveries are paused

While there is no subscription, events are not delivered to any webhook. Each delivery is canceled before it is sent and shows in the delivery log with status: canceled and last_error: subscription_inactive. A canceled delivery is not a failure: it is not retried, does not count toward the automatic disabling of the webhook and leaves is_active unchanged. Events that happen during that time are not sent later on their own, but they are kept for 30 days: once the workspace subscribes again, POST /api/webhooks/{webhookId}/replay re-sends them. New events are delivered again, with no change to the webhook, as soon as the workspace has an active subscription.

What stays available, and why

Your data belongs to you whether or not you pay. Without a subscription you can still:

  • read contacts, calls, conversations, transcripts, the audit log and the agent action ledger;
  • export that data (calls, contacts, conversations, agent_actions, audit_log) and download exports;
  • remove configuration that holds a credential or points outside Jelliu: delete webhooks, MCP servers and MCP server assignments;
  • use erasure and compliance endpoints, manage API keys, and use the billing routes to choose a plan.

The line is drawn so that stopping payment never traps data inside Jelliu: what is refused is new work and new outbound traffic, never access to, portability of, or removal of what the workspace already has.

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, a plan feature gate, or a feature that needs an active subscription (metadata.kind: "subscription_required").
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.