Docs

Agent Payments Quickstart

Give a coding agent a secure, additive path for adding USDC subscriptions or one-time checkout to an existing site or app.

This is the stable bootstrap document for a coding agent. The agent adds Zoneless as another way to pay for what you already sell, keeps your existing billing provider working, stays in test mode, and stops at the human authorization and production secret boundaries.

How USDC subscriptions work

Recurring stablecoin billing usually fails because a wallet cannot be charged without its owner present. Zoneless solves this with a one-time on-chain approval, so a USDC subscription behaves like a card subscription.

  • You create a recurring price. Zoneless registers an on-chain plan holding the amount, the billing period, and the single wallet allowed to receive the money.
  • The customer approves once at checkout. They connect a wallet and sign an approval authorizing Zoneless to collect that exact amount, once per period, for that plan only.
  • Every later cycle is automatic. Zoneless collects the payment on schedule, creates an invoice, and sends you a webhook. The customer never signs again and does not need to be online.
  • The customer stays in control. The approval is limited to the plan terms and can be revoked. Nothing is custodial, and no one can pull a different amount or send funds elsewhere.

You do not need to hold or manage any crypto to receive these payments. Money moves from the customer's wallet to the platform wallet that setup created for you.

1Start secure setup

From the application repository, infer a clear platform name and run the command below. The Node.js CLI is only the secure bootstrap tool; it does not require the application backend itself to use Node.js.

If setup reports that local profiles already exist for a different platform, retry with --new-platform. Reuse profiles that already belong to this product.

Terminal
npx @zoneless/cli@latest agent setup \
  --platform-name "<product name>" \
  --skill payments \
  --json

2Pause for human authorization

Show the activation URL and code returned by the CLI, then wait for the human to review and approve the request. Never approve it for them. Setup provisions test and live profiles while keeping API credentials and wallet secrets out of the prompt and source tree.

The CLI binds this repository to the provisioned profiles in .zoneless/project.json and selects test by default. Build and verify with https://api-test.zoneless.com; keep mode environment-driven and leave live promotion to the human handoff.

Setup validates stored keys before reuse. If it reports credentials_invalid, run npx @zoneless/cli@latest auth reconnect --json and show the new authorization prompt to the human. For local testing, run npx @zoneless/cli@latest env sync --json; it finds an unambiguous env file, preserves unrelated values, and writes the bound test credentials without displaying them. Collecting payments needs no wallet key in your application, so do not pass --include-wallet. The synced ZONELESS_API_URL is an origin without /v1; pass it directly to @zoneless/node, which adds the API path.

3Read the installed payments skill

After approval, parse the successful JSON response and read the file at skill_path before changing application code. The CLI installs the versioned zoneless-payments skill locally and returns its exact path, so this flow does not depend on automatic skill discovery.

Follow that skill as the implementation and safety contract. Use llms.txt as an index and read resource pages such as Prices, Checkout Sessions, and Subscriptions only when implementing that resource or when blocked. Do not fetch the entire documentation set upfront.

4Classify how the app sells access

Determine whether the application already sells plans through Stripe Billing, Paddle, or similar, whether it has no recurring billing yet, or whether the human wants a single one-time payment. Identify where access is currently recorded and define the billing subject: the user, account, workspace, license, or other resource that owns one independently managed entitlement.

Preserve every existing provider. Never migrate existing subscribers, and never cancel, refund, or modify a subscription that another provider owns. Do not assume the authenticated user is the billing subject. If the entitlement ownership or provider-ID mapping is unclear, stop and ask rather than guessing.

5Add a payment method, not a plan

Mirror each existing plan with a Zoneless recurring price at the same amount and cadence, then map that price onto the existing plan record. Use the CLI for catalog setup rather than improvising raw API requests.

  • One plan, two ways to pay. Present USDC as another payment option on the plan you already sell. Do not add a duplicate plan to the pricing page or admin console.
  • One entitlement record. Write access from Zoneless into the same field the existing provider already writes, so nothing else in the application has to change.
  • One active provider per billing subject. Store a billingProvider value alongside the Zoneless subscription ID on the record that owns the entitlement. Independently billed subjects may use different providers.
  • No double billing for the same subject. Enforce on the server that a billing subject with an active subscription elsewhere cancels or reaches period end before starting a Zoneless one.

Amounts use minor units, so 2000 means 20.00 USDC. Preview with --dry-run first, then create with a retained --idempotency-key. Omit --interval for a one-time product instead of a subscription.

Terminal
npx @zoneless/cli@latest store init \
  --name "Pro" \
  --amount 2000 \
  --interval month \
  --json

6Open checkout and grant access from webhooks

For a signed-in user, create a Checkout Session server-side with mode: "subscription", the mirrored price, a success_url, and client_reference_id set to a stable application reference for the billing subject after validating access, then redirect to the returned URL. A bare payment link carries no application context. Never put the API key in browser code.

The success redirect proves only that the browser came back. Treat verified webhook events as the only source of truth, reusing the existing webhook route, preserving the raw body, verifying Zoneless-Signature, and making duplicate events safe by recording event.id.

  • checkout.session.completed — resolve the billing subject from client_reference_id, store subscription and customer, pin the provider, and grant access.
  • invoice.paid — resolve the subscription from parent.subscription_details.subscription and extend access using the invoice period.
  • invoice.payment_failed — apply the existing dunning or grace behavior rather than inventing a new one.
  • customer.subscription.updated and customer.subscription.deleted — follow status changes and revoke access at the end of the paid period.

On a Subscription, billing periods belong to items.data[*].current_period_start and items.data[*].current_period_end, not the Subscription's top level. Match the relevant item by ID or price, and use SDK-shaped fixtures in tests.

Route cancellation by provider. Zoneless subscription cancellation belongs in the application's existing billing UI, either at period end or immediately.

Server
const session = await client.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: plan.zonelessPriceId, quantity: 1 }],
  client_reference_id: billingSubject.id,
  success_url: 'https://example.com/billing/success',
});

7Configure the test webhook

Zoneless must be able to send signed events to the application's server-side webhook route. Use the deployed test URL, or expose localhost through a separate HTTPS tunnel such as ngrok or Cloudflare Tunnel. Then run the CLI command; it creates or updates the test endpoint, selects the standard subscription events, stores the one-time signing secret securely, and writes ZONELESS_WEBHOOK_SECRET to the local env file without printing it.

Restart the application after the command so it loads the synced webhook secret.

Terminal
npx @zoneless/cli@latest webhook sync \
  --url "https://YOUR-PUBLIC-HOST/api/webhooks/zoneless" \
  --preset subscriptions \
  --json

8Verify in test mode

Add focused tests that prove the existing billing path is unchanged, one billing subject never holds active subscriptions on two providers at once, independent subjects remain independent, entitlement is granted from a verified webhook rather than the redirect, SDK-shaped subscription periods are handled correctly, duplicate webhook deliveries are safe, cancellation routes to the owning provider, and no secrets reach browser code or fixtures.

Run the project's formatter, focused tests, linter, type checker, and build. Open a test Checkout Session and verify its product, amount, cadence, and return URLs. Complete one supervised test subscription with the simulated wallet (or the test_helpers complete endpoint) and verify the resulting entitlement. Distinguish static checks, unit tests, hosted-checkout verification, and completed payments in the handoff.

9Hand production setup back to the human

Report changed files, any existing-provider behavior that changed, the plans mirrored with their Zoneless price IDs, migrations, deployment commands, and the required environment-variable names. Distinguish static checks, unit tests, hosted-checkout verification, and completed end-to-end payments. Tell the human where to configure the API key and webhook secret without requesting either value.

To test a subscription end to end, the human opens hosted checkout in test mode and approves the simulated wallet. They can also complete a session with POST /v1/test_helpers/checkout/sessions/:id/complete. No Phantom, faucet, or Devnet switch is required.

Explain the live promotion explicitly: configure the separately provisioned live API key and https://api.zoneless.com in the deployment secret manager, create the live endpoint from the live Developers dashboard or with an explicitly selected live CLI profile, configure the live webhook secret, and complete one supervised subscription before enabling live traffic.