Skip to content
AutoPay Agent

Developers

AutoPay Agent documentation

Non-custodial recurring payments on Solana. Merchants create plans and payment links. Subscribers sign one transaction that pays the first period and approves a capped SPL allowance. A billing agent then pulls each renewal on schedule, straight from the subscriber's token account to the merchant's wallet.

How it works

  1. Checkout. The server builds an unsigned v0 transaction: create the merchant's token account if missing, TransferChecked for the first period (skipped during a trial), ApproveChecked(delegate = billing agent, amount = cap), and a memo. The subscriber's wallet signs and sends it, and the server verifies it on-chain before the subscription is created.
  2. Shared approval. An SPL token account holds exactly one delegate and one amount, and approve replaces it rather than adding to it. So the cap a subscriber signs includes the remaining allowance of their other live AutoPay subscriptions in the same token. Each subscription keeps its own share in the database.
  3. Renewals. Every 30 seconds the worker picks up due subscriptions. It checks the token account on-chain (owner, mint, delegate, delegated amount, balance, frozen), then the agent signs one TransferChecked as delegate for exactly one period's price, with a fresh reference key and a memo autopay:v1|renew|…. Preflight simulation rejects anything that would fail, at no cost.
  4. No double charges. A charge is recorded as pending with its signature before confirmation. If the worker restarts, it resolves the pending signature before ever sending another transfer.
  5. Billing dates advance from the scheduled date, not the retry date. Monthly plans keep their anchor day (Jan 31 → Feb 28 → Mar 31).

Trust model

Non-custodial. Funds never sit with AutoPay Agent; every payment is one wallet-to-wallet transaction. The billing agent (EzTWj52AYoEphjYJrKZumLyqfhNiqBuNDXiNjDsgomQR) is an ordinary keypair held by our worker. It pays network fees for renewals.

What a subscriber risks. At most the remaining approved amount of one token. The agent cannot touch SOL, NFTs or other tokens, and a revoke takes effect on-chain immediately. The honest caveat: SPL delegation does not restrict the destination, so the cap is enforced by the token program but the merchant destination and the once-per-period rule are enforced by our worker. Pick caps you are comfortable with. Removing this assumption is the first roadmap item: a subscription program with a PDA delegate.

Cancel any time. Canceling on /account stops charges immediately, and the same click offers a transaction that reduces or revokes the on-chain approval. Any wallet's revoke tool works too.

Billing rules & failure codes

Each plan sets retryAttempts (0–10), retryHours between attempts, onFinalFailure (cancel | pause | past_due) and remindHours (reminder before each charge, with an early balance/approval check). Both sides get every failure with its reason: in-app, by email if configured, and as a charge.failed webhook. Platform-side failures (RPC outage, agent out of SOL) are deferred and never count as an attempt.

insufficient_balanceThe wallet did not hold enough tokens for this charge.
allowance_insufficientThe remaining approved allowance is lower than the charge. Re-approve to continue.
delegate_changedThe approval was revoked or replaced by another app. Re-approve to continue.
token_account_missingThe token account no longer exists.
account_frozenThe token account is frozen by the token issuer.
agent_unfundedThe billing agent is out of SOL for network fees (not your fault — it will retry automatically).
networkThe Solana network or RPC did not respond (it will retry automatically).
tx_failedThe charge transaction failed on-chain.
unknownThe charge could not be completed.

REST API

Base URL https://autopayagent.online. Authenticate with a secret key from Dashboard → Developers: Authorization: Bearer apk_live_…. Keys are stored hashed and shown once. Amounts are decimal strings in token units ("29.5"); responses include both amountRaw (base units) and amount. Rate limit: 600 requests/minute per key.

POST/api/v1/checkoutsCreate a one-time checkout {token, amount, title?, redirectUrl?, email?, metadata?} → id, url, solanaPayUrl, reference
GET/api/v1/checkouts/:idCheckout status (pending | paid | expired), payer, signature, metadata
GET/api/v1/plansList plans with live subscriber counts
POST/api/v1/plansCreate a plan {name, token, amount, intervalUnit, intervalCount, trialDays, allowanceCycles, retryAttempts, retryHours, onFinalFailure, remindHours}
PATCH/api/v1/plans/:idUpdate copy, billing rules or status (price/token/interval are immutable)
GET/api/v1/payment-linksList payment links (one-time + one subscribe link per plan)
POST/api/v1/payment-linksCreate a one-time link {title, token, amount, description?, redirectUrl?}
GET/api/v1/subscriptionsList subscriptions (?status=active|trialing|past_due|paused|completed|canceled, ?plan_id=)
GET/api/v1/subscriptions/:idOne subscription with its payment attempts
POST/api/v1/subscriptions/:id/cancelCancel now; no further charges
GET/api/v1/paymentsPayment history (?status=, ?limit=, ?format=csv)
GET/api/v1/overviewMRR, live subscribers, 30-day volume, failed charges, upcoming charges
GET/api/v1/notificationsWorkspace notices
GET/api/v1/webhooksRecent webhook deliveries; POST sends a signed test.ping
curl -X POST https://autopayagent.online/api/v1/plans \
  -H "Authorization: Bearer $AUTOPAY_KEY" -H "content-type: application/json" \
  -d '{"name":"Pro","token":"USDC","amount":"29","intervalUnit":"month",
       "trialDays":7,"retryAttempts":3,"retryHours":24,"onFinalFailure":"pause"}'

# share the plan's subscribe link (GET /api/v1/payment-links → kind "subscription")
# or send customers to https://autopayagent.online/subscribe/<plan slug>

Webhooks

Set an https URL under Dashboard → Developers. Deliveries are JSON { id, type, created, data } with headers AutoPay-Event, AutoPay-Event-Id and AutoPay-Signature: t=<unix>,v1=<hex>, where v1 = HMAC-SHA256(secret, `${t}.${rawBody}`). Non-2xx responses are retried after 1m, 5m, 30m, 2h, 6h, 12h and 24h. Handle events idempotently by id.

checkout.paidA one-time checkout was paid and verified on-chain
subscription.createdCheckout signed: first period paid (or trial started) and allowance approved
subscription.renewedA renewal charge landed
subscription.reminderA charge is coming up (plan.remindHours before); includes at_risk
charge.failedA charge failed; failure.code, attempt, next_retry_at or final
subscription.past_due / .paused / .canceledFinal billing-rule outcome or a manual cancel
subscription.completedAll approved cycles were paid; the subscriber must approve more
subscription.extended / .reactivatedThe subscriber approved more cycles (and reactivated)
import crypto from 'node:crypto';
export function verify(rawBody, header, secret) {
  const [, t, v1] = /t=(\d+),v1=([0-9a-f]{64})/.exec(header || '') || [];
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const want = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(v1));
}

Solana Pay & reference keys

Every checkout gets a unique reference public key, added as a read-only account to the payment's transfer instruction. The QR code is a Solana Pay transaction request (solana:https://autopayagent.online/api/solana-pay/<checkout id>): the wallet fetches the exact transaction, including the optional platform fee split, from the server. The worker finds payments with getSignaturesForAddress(reference) and checks recipient, mint, amount and fee before marking the checkout paid. So a phone payment is confirmed even if the browser tab is closed. Checkouts expire after 30 minutes.

Roadmap

Not built yet.

  • On-chain subscription program · Next

    Replace the shared agent delegate with a per-subscription PDA that can only pay the approved merchant, at most once per period, enforced by the program itself.

  • Pay in any token · Planned

    Subscribers pay in SOL or any SPL token; a Jupiter route swaps to the merchant's settlement stablecoin inside the same charge.

  • Usage-based billing · Planned

    Metered plans: report usage over the API, the agent charges the computed amount within the approved cap.

  • Token-2022 stablecoins · Planned

    PYUSD, USDG and other Token-2022 assets, including transfer-fee aware accounting.

  • Invoices & tax exports · Exploring

    PDF invoices and receipts, VAT/GST fields, and accounting exports beyond CSV.

  • Teams & SDKs · Exploring

    Multiple members per merchant workspace with roles, plus TypeScript/Python SDKs and an embeddable checkout.