Start
Plans and output
What Anonymous, Free, Trial and Pro each include, what separates a preview from store-ready output, what spends cloud credits, and how account_status explains a refusal.
Two independent things decide what a call does: your plan, which says whether you may produce store-ready output at all, and your cloud credits, which pay for rendering on our hardware. Neither substitutes for the other, and confusing them is why a refusal sometimes reads as the wrong problem.
#What each plan includes
| Anonymous | Free | Trial | Pro | |
|---|---|---|---|---|
| Signed in | No | Yes | Yes, first 7 days | Yes |
| Cloud credits | none | 80 / month | at least 466 one-time | 2,000 / month |
| Editable projects | — | 2 | 2 | Unlimited |
| Preview rendering | 3 hosted strips per 30 days, up to 5 panels | Yes | Yes | Yes |
| Store-ready output | No | No | Yes | Yes |
| Look history and held versions | No | No | Yes | Yes |
| Duplicate a project | No | No | Yes | Yes |
| Publish a persistent preview | No | No | Yes | Yes |
| Collaborators per project | — | 0 | 1 | 1 |
| Price | — | €0 | €0 for 7 days | €9 / month or €90 / year |
Every new eligible account starts with seven days of Pro. No card is collected and the trial never charges automatically.
The trial keeps Free's two-project limit deliberately — it is the one Pro capability a trial does not get, so that day eight cannot strand a third project above the cap. Unused trial cloud credits survive expiry; Pro capabilities do not.
Monthly refills top the balance up to your plan's allowance rather than stacking on top of it.
#Preview versus store-ready
A preview renders at roughly a quarter resolution, comes back inline, and is open on every plan and on a signed-out local install. It is never watermarked and it covers the complete screenshot set — you can design the whole strip before you decide to pay for anything.
Store-ready output is anything you could actually ship:
- a full-resolution
render_striporrender_project; - every form of
emit_bundle, including one that only re-zips panels somebody already rendered.
Store-ready output needs an active Pro trial or Pro, on ShotOps Cloud and on your own machine alike. The decision belongs to the server, is taken from a single entitlement read, and happens before a cloud credit is reserved, before the renderer starts, before a screenshot is read and before a file is written. A refused call costs nothing and leaves nothing behind.
#Durable Hosted production
The entitlement decision is the same on both doors; execution is not. Local preview and production
rendering finish in the original tool call. Hosted previews do too, while a paid Hosted
full-resolution render_strip, render_project or rendering form
of emit_bundle becomes a durable operation.
Keep the operation id from that response. production_operation reads persisted
progress with action: "get", requests cooperative cancellation with action: "cancel", and returns
the terminal render or bundle with fresh delivery grants through action: "result". Those reads do
not spend cloud credits; the originating operation owns the one reservation and settlement. A
disconnected client does not cancel it, and collecting it does not render it again.
A full-resolution panel takes a few seconds, so an eight-panel bundle runs well over a minute. Each
action: "get" reports how many of your panels are finished — progress.panelsCompleted of
progress.panelsTotal — with progress.estimatedRemainingSeconds as a rough estimate of the
rendering left, and a plain sentence beside the structured result for your agent to relay. The
progress.completed and progress.total counters are internal scheduling items, not panels.
A compose-only emit_bundle({ panels }) is still store-ready output and still needs the entitlement.
It remains immediate and spends no render cloud credits because it only packages panels that already
exist.
#What spends cloud credits
| Action | Cost | Free / month | Trial, once | Pro / month |
|---|---|---|---|---|
| Hosted preview panel | 1 credit | 80 | 466 | 2,000 |
| Hosted full-resolution panel | 4 credits | 20 | 116 | 500 |
| AI model tokens | 1 credit per 250 billable tokens | — | — | — |
The three right-hand columns are what an allowance buys if you spend it only on rendering. AI draws on the same balance, so they are ceilings rather than a second allowance.
Nothing else costs cloud credits. Reading, saving and deleting existing projects, looks and
assets is free regardless of balance. account_status is free by design — it
spends no cloud credit and consumes no anonymous preview attempt, which is what makes it safe to
call before every expensive job.
The ledger keeps finer internal units so AI usage can be debited exactly. Every surface you can see converts them to the cloud credits above; internal units are never presented as credits.
#Local rendering and hosted cloud credits
The same render can be free on one door and charged on the other, because cloud credits pay for our hardware, not for permission.
| Your computer | ShotOps Cloud | |
|---|---|---|
| Preview render | free, no account, no metering, on any plan | 1 credit per panel |
| Full-resolution render | costs no credits | 4 credits per panel |
emit_bundle | costs no credits | credits only if it renders |
| Entitlement for store-ready output | active Pro trial or Pro | active Pro trial or Pro |
The last row is the one to read: the plan requirement is identical on both doors. Running locally makes the compute yours, not the product free.
The one local operation that does spend cloud credits is refine_project, because
it asks our servers to run each AI pass even though the rendering stays with you.
#When a trial ends or a payment fails
When a trial ends without a choice, the account is in a choice required state: pick Pro or Free in the app, and the tools work again. That is not the same as being on Free, and the refusal says so.
When a renewal payment fails, Pro capabilities continue for a 7-day grace period while the payment is retried.
Refund terms are at Refunds.
#Reading account_status
account_status is the one call that explains a refusal without triggering one. It
reports the connection, the plan, the trial, the cloud credits, whether store-ready output is
available, and a single machine-readable nextStep.
{
"connection": "hosted",
"authenticated": true,
"plan": "free",
"entitlementStatus": "active",
"credits": { "remaining": 24, "cap": 80, "refillAt": "2026-09-01T00:00:00.000Z" },
"preview": { "mode": "credits", "previewPanelCredits": 1, "fullPanelCredits": 4 },
"production": {
"capability": "production.export",
"available": false,
"reason": "plan_required",
"requiredPlan": "pro"
},
"nextStep": "upgrade",
"message": "Store-ready output — full-resolution panels and screenshot bundles — needs an active Pro trial or Pro…"
}
preview.mode is unmetered on a local connection, anonymous_limit on a signed-out hosted one
(with the attempts, window and panel cap alongside it), and credits otherwise.
When production.available is false, production.reason names which of these it is:
reason | nextStep | What it means | What to do |
|---|---|---|---|
authentication_required | sign_in | No account on this connection. | Sign in, or set a token for CI. Previewing still works. |
plan_required | upgrade | Signed in, on Free. | Start the trial or upgrade. |
trial_choice_required | choose_plan | The trial ended and nobody has chosen yet. | Pick Pro or Free in the app, then call again. |
limit_reached | upgrade | A plan limit, not a credit balance. | Upgrade. |
billing_unavailable | retry | ShotOps could not read the billing status. | Try again shortly. |
Four more conditions never appear in production at all, because they happen somewhere else
entirely. Do not read them as plan problems:
- Out of cloud credits. A hosted render is refused with
Not enough ShotOps cloud credits, the exact cost, your remaining balance and the next refill date. Your plan is fine; the balance is not. See Out of cloud credits. - Anonymous preview exhausted. A signed-out hosted connection has used its 3 strips for this 30-day window. The refusal names the date the next free preview is available. Signing in ends it immediately.
- Revoked or unknown token. A hosted request with a bad bearer token gets a
401before any tool runs, so there is noaccount_statusresult to read. Create a new token. - Missing Chromium. A local render fails because Playwright's browser is not installed. Nothing
to do with your account: run
npx playwright install chromium. See Chromium is missing.
More symptoms, and what each refusal actually says, are in Troubleshooting.