Model

Configuration reference

Every option on withPaywall, paidTool, the Moove provider and the stores.

withPaywall(server, config)

optiontypedefaultwhat it does
providerPaymentProviderrequiredOpens charges, settles them, issues handles.
storeEntitlementStorerequiredWhere credits are spent from. Passed explicitly, never reached for.
argumentNamestringtollboothTokenThe tool argument the agent carries the handle back in.
copyIdstringv3Challenge copy variant. All five are measured; v3 ships.
allowstring[]noneRenderer ids permitted beyond the default. Deny-by-default otherwise.
onSettlementfn(outcome)Every settlement observation. Log underpaid loudly.
onCallfn(event)Every paid call, with a handle fingerprint — never the handle.
now() ⇒ numberDate.nowInjected clock. Must agree with the provider's.

server.paidTool(name, description, pricing, inputSchema, annotations, handler)

Argument order mirrors Cloudflare Agents’ paidTool. pricing is a sku string or { sku, cost }; cost defaults to 1 and must be a positive integer. The sku must already be sold by the provider, or registration throws. The handler receives the arguments with the handle stripped, and extra.tollbooth set to { subject, sku, cost } so a server can rate-limit per handle.

new MooveProvider(options)

all options
new MooveProvider({
  client, store, prices,
  chargeTtlMs: 60 * 60 * 1000,          // default; floor 15 minutes
  settlementPolicy: {
    toleranceFraction: 0.005,           // within 0.5%: grant in full
    minimumFraction: 0.1,               // below 10%: grant nothing
  },
  subjectTtlMs: 30 * 24 * 60 * 60 * 1000, // sliding; floor 1 hour
});
optiondefaultfloornotes
chargeTtlMs60 min15 minHow long a checkout stays payable. There is no deactivation endpoint; expiry is the only containment.
settlementPolicy.toleranceFraction0.0050Within this shortfall, grant in full. See underpayment.
settlementPolicy.minimumFraction0.10Below this fraction, grant nothing. Must leave room below the tolerance band.
subjectTtlMs30 days1 hourSliding window on a handle. See security.
pricesrequiredEverything this server sells.

new MooveClient(options)

optiondefaultnotes
apiKeyrequiredHeld here and never leaves: not logged, not attached to errors, not sent on the public read.
baseUrlhttps://api.moove.xyzThe host shown next to your key. Never guess it.
maxAttempts4Retries for 429 and 5xx only. The 4xx family is never retried.
keyedLimiter2 req/sGoverns authenticated calls, which consume the per-key budget.
publicLimiter8 req/sGoverns the keyless read, which consumes only the per-IP budget.

The limiter defaults are deliberately conservative despite measured headroom; the rate limits page says why.

Stores

storeoptionnotes
MemoryEntitlementStoreacknowledgeEphemeralRequired outside tests; the store warns otherwise. Loses paid credits on restart.
SqliteEntitlementStorepathFile path or :memory:. WAL mode; busyTimeoutMs defaults to 5000.
PostgresEntitlementStoreconnectionStringUse Neon's pooled host. max (5), maxRetries (5), retryBaseMs (250), migrate (true).

Reference server environment

variablerequirednotes
MOOVE_API_KEYyesThe server exits without it.
MOOVE_API_BASE_URLnoOnly if your key names a different host.
DATABASE_URLnoPostgres when set; SQLite otherwise. /health reports which.
TOLLBOOTH_DBnoSQLite path. Defaults to /data/tollbooth.sqlite in the HTTP entrypoint.
PORTno8080.
TOLLBOOTH_LANDING_URLnoAdvertised by GET /.
Tollbooth

A paywall layer for MCP servers. An agent calls a paid tool, a human pays, the agent retries. Every number on this page is one we measured, at the precision we measured it.