Skip to content

Plans and licence keys

The sidecar enforces the Free limits itself and reads a licence key for the paid tiers. Nothing here phones home: the key is verified offline, and a payment that policy allows is never blocked by an outage on our side. Prices and what each tier includes: Pricing.

Free With a key
Agents under agents: 2 Pro 10, Team unlimited
Governed payments per calendar month (UTC) 1,000, then new payments are refused until the month rolls over from the key; never stopped (overage is billed)
Everything else included included

What counts. A governed payment is a request the sidecar did payment work for: it signed, or it asked a human. Refusals (denied) and dry runs never count, so an agent cannot use up your month by being refused. A payment that was handed back for approval and then retried with it counts once (the superseded row does not count; the retry does). Nothing counts while signer: mock: the sandbox is unlimited.

Over the agent limit. spendctl start refuses to start and names the agents, so a third agent is never silently denied in production.

At the cap. The sidecar answers like any other refusal (402, spendctl_denied) with the reason plan_events_exceeded, which names the reset date. It logs one warning at 80 % and one at the cap. spendctl budget, spendctl license and the dashboard show the month’s count.

Terminal window
spendctl license set SPENDCTL-... # stored in .spendctl/license.key (0600, git-ignored)
spendctl license # tier, organisation, expiry, this month's usage
spendctl license remove

SPENDCTL_LICENSE_KEY in the environment takes precedence over the file, which suits containers and CI. Restart the sidecar after changing the key. Keep the key out of spendctl.yaml: policy files are meant to be committed.

A key that does not verify (typo, tampering, unknown signing key) is reported at startup and the sidecar runs as Free. A key expires 30 days after its paid-through date; inside those 30 days the sidecar keeps the paid limits and warns once a day, afterwards it runs as Free.

Keys are issued when the control plane launches; founding members get theirs by email.

A sidecar without a key sends nothing to us. A sidecar with a key (from 0.3) checks in with the control plane at start and once a day, with exactly five values: a random sidecar id it generated (.spendctl/sidecar.id), its version, the month, this month’s governed-payment count and the number of agents in spendctl.yaml. No agent names, hosts, bodies, prompts or network addresses.

The answer can renew the key before it expires (written to .spendctl/license.key when the key came from there; with SPENDCTL_LICENSE_KEY you are told to update the variable) or mark it revoked, after which the sidecar runs with the Free limits and says why. The check-in never sits on the payment path: when the control plane is unreachable the sidecar keeps its current limits, warns once a day and retries. SPENDCTL_CHECKIN=off switches it off; spendctl license shows the last and the next one. The privacy policy lists the same five values.

The spendctl Discord is open to everyone: discord.gg/XpraJzK8E4. Ask in #support, show what you built in #showcase, talk protocols in #x402-and-mpp. Pro, Team and founding members get the member channels, including the founding channel with the maintainer. Security issues go to security@spendctl.dev, never to a channel.