Plan limits and upgrade offers
What a requires_upgrade offer contains, every reason it can carry, how to hand the confirm_url to a person, and what still works when a plan has lapsed.
On a builder plan or the no-card trial, a call your plan does not cover is refused before any work runs, and the refusal is an upgrade offer: why the call stopped, the next plan and what it costs, and a link a person opens to confirm it. Nothing ran and nothing was charged.
01
Where the offer appears
- Over MCP, the offer is the tool result itself, a normal result rather than an error, with
status: "requires_upgrade". It is built that way so your client hands it to you instead of burying it. - Over REST, the offer rides on a 402 as
error.upgrade, witherror.codeset toPLAN_REQUIRED,PLAN_LIMIT_REACHEDorDATA_CREDITS_EXHAUSTED.
{
"status": "requires_upgrade",
"reason": "limit_reached",
"message": "This organization has reached its schedules cap on the Starter plan (10 of 10); Growth ($149/mo) raises it to 50.",
"tool": "agnt_schedules_create",
"limit": { "resource": "schedules", "used": 10, "cap": 10, "tier": "builder_starter" },
"current_tier": "builder_starter",
"upgrade": {
"tier": "builder_growth",
"name": "Growth",
"price_usd_month": 149,
"included_data_credits_usd": 90,
"unlocks": { "agents": 15, "schedules": 50 }
},
"confirm_url": "https://app.superagnt.com/confirm/<token>",
"human_step": "The call did not run: the plan's schedules cap is reached. Everything that already exists keeps working. Nothing was charged. Share the confirm_url with a person on this account: they review Growth there and confirm it. You never pay or change the plan yourself. Retry once they have confirmed."
}The plan names, prices and caps above are an example. A real offer carries the live figures, which are also on Plans and limits.
02
The fields
| Field | What it holds |
|---|---|
status | Always requires_upgrade. Check this to tell an offer from a real result. |
reason | Why the call stopped. See the table below. |
message | One sentence that names the next plan. |
tool | Over MCP, the tool that was refused. |
limit | For limit_reached: the resource, how many are used, the cap, and the tier the cap belongs to. |
data | For included_credits_insufficient and trial_grant_insufficient: what the call needs (cost_cents) and what is left (remaining_cents). |
retry_after_seconds | For rate_limited: how long to wait before retrying. |
current_tier | The plan now, or trial, or none. |
upgrade | The plan to move to: tier, name, price_usd_month, included_data_credits_usd and unlocks (the limits it raises). When the next step is Enterprise, it is tier: "enterprise" with a contact_url instead. |
trial | On the trial: phase, ends_at, days_left and data_retained_until. |
confirm_url | A link where a signed-in person reviews the plan and confirms it. null when one could not be made, or when the next step is Enterprise. |
human_step | Plain instructions written to be relayed to a person as they are. |
03
Every reason
| reason | REST code | What stopped | What to do |
|---|---|---|---|
limit_reached | PLAN_LIMIT_REACHED | A plan cap: agents, schedules, queues, databases, knowledge, database rows or storage, and the rest of the published limits. | Remove something, or have a person confirm the next plan. Everything that already exists keeps working. |
included_credits_exhausted | DATA_CREDITS_EXHAUSTED | This period's included data credits are used up. | Wait for the plan to renew, or confirm the upgrade. Non-data tools keep working. |
included_credits_insufficient | DATA_CREDITS_EXHAUSTED | This data call needs more than what is left. | Make a cheaper call, or lower max_cost_cents where the endpoint takes it, or confirm the upgrade. |
trial_grant_insufficient | DATA_CREDITS_EXHAUSTED | The trial's data credit left is less than this call costs. | Try a cheaper data call, or choose a plan. |
trial_data_grant_spent | DATA_CREDITS_EXHAUSTED | The trial's data credit is spent, so data calls are paused. | Choose a plan. Everything else works until the trial ends. |
trial_ended | PLAN_REQUIRED | The trial has ended. Agents, schedules, pipelines and data calls are paused. Nothing is deleted. | Choose a plan. It picks up where it stopped. |
trial_ineligible | PLAN_REQUIRED | This account cannot start a free trial, so nothing runs until a plan is chosen. | Choose a plan, or have a teammate invite this account into their workspace. |
plan_lapsed | PLAN_REQUIRED | The plan is no longer active. Everything is paused. Nothing is deleted. | Confirm a plan to turn it back on. |
plan_required | PLAN_REQUIRED | This account has no plan, and the call needs one. | Choose a plan. |
rate_limited | RATE_LIMITED (429) | Over the per-minute request limit. Over MCP only; a REST 429 carries no offer. | Wait retry_after_seconds and retry, or upgrade for a higher limit. See Rate limits. |
04
What to do with an offer
- Stop. Do not retry the same call: it is refused the same way until a person acts (the one exception is
rate_limited, which clears after the wait). - Relay
human_stepto the person you work for, with theconfirm_url. - Never pay, enter payment details, or change the plan yourself. The
confirm_urlopens a page onhttps://app.superagnt.comwhere a signed-in person reviews the plan and confirms it. Nothing is charged until they do. - When the person tells you they have confirmed, retry the call.
A confirm_url stays valid for about a day. If it has expired, or the offer has confirm_url: null, the person can choose the plan on the billing page in the superagnt app instead. When upgrade.tier is enterprise, share upgrade.contact_url so they can set up an Enterprise plan.
05
When everything is paused
After trial_ended, trial_ineligible or plan_lapsed, every MCP tool returns the offer except the few that show where the account stands and how to get going again: agnt_subscription_get, agnt_subscription_preview, agnt_subscription_change, agnt_credits_balance, agnt_usage_summary, agnt_usage_recent, agnt_usage_ai_recent, agnt_usage_sessions, agnt_platform_map, agnt_onboarding, agnt_tools_search, agnt_tools_list_enabled, agnt_datetime_now, and the support tools, so a paused workspace can still search the docs and ask the team for help. Over REST, /v1/credits and /v1/usage keep answering.
Nothing is deleted while paused. The trial's data_retained_until says how long the data is kept.
06
Seeing where you stand
On a workspace MCP connection, agnt_subscription_get returns the plan or trial, its per-minute rate, every limit with current usage, the included data credits left this period, the trial state, and the next plan with what it adds. To propose a change yourself, call agnt_subscription_preview for a dry run, then agnt_subscription_change with its idempotency_token. That returns a confirm_url for a person and never charges anything.
07
Other plan and billing codes
| Code | Status | What it means | What to do |
|---|---|---|---|
SUBSCRIPTION_PAST_DUE | 409 | A checkout or a confirm_url was opened while the builder plan has an unpaid invoice. The body carries error.billingPortalUrl. | Have a person update the payment method in the billing portal. That pays the open invoice and the plan comes back on its own. Do not start a second plan. |
SEAT_LIMIT_REACHED | 402 | An invite would go past the seats the plan pays for. | Add a seat, then invite again. |
DEPLOY_GATE_FAILED | 402 | Deploying an agent needs a plan, the trial or a credit package. | Choose a plan or start the trial, then deploy again. |
SUBSCRIPTION_REQUIRED | 402 | A paid surface was reached by an organization with no plan. | Choose a plan, then retry. |
TRIAL_ALREADY_USED | 409 | The managed-plan trial was already used. It is once per organization. | Subscribe instead. |
CAPABILITY_UNAVAILABLE | 409 | The workspace's database backend does not offer this feature. No plan changes it. | Do it another way, for example store the data in a table. |
PLAN_PRICE_NOT_CONFIGURED | 503 | A plan change targeted a tier that has no price set up on our side yet. | Our setup gap, not yours. Open a ticket. |