Docs

Checkout

How apps start ATM checkout, pass private session context, and reconcile payment state.

Closed beta@atmosphere-money/app-nodeSDK beta: 0.0.0-beta.2ATM API beta: 2026-0647 lexicons

Compatible with the closed-beta ATM app APIs and versioned ATM event headers. Check atm-api-version on every webhook or XRPC receiver event.

Hosted checkout

Hosted ATM checkout is the standard ATM checkout path. It lets ATM own the payment form lifecycle, wallet eligibility, processor session, receipts, proof coordination, return URLs, and fulfillment events.

Embedded ATM checkout is on the roadmap as an optional iframe or JS wrapper. Hosted checkout remains the fallback for wallet-domain rules, redirect methods, OAuth re-auth, browser quirks, and CSP failures.

Creator approval

ATM checks app-recipient approval before it creates a payment row or processor checkout session. The same boundary applies when an app registers fulfillment links for a creator's catalog records. Apps can request approval with money.atmosphere.app.requestRecipientApproval, then send the creator to the returned ATM URL to confirm.

Missing approvalCheckout returns RecipientAppApprovalRequired.
Blocked or revokedCheckout returns RecipientAppApprovalBlocked.
Material changeCheckout returns RecipientAppReapprovalRequired until the creator reviews the change.
Self paymentsWhen the app DID and recipient DID are the same account, ATM treats the relationship as self-approved.

Initiation contract

The public attested.network initiate route stays strict. ATM-specific fields are encoded in the opaque product envelope.

http
POST /xrpc/network.attested.payment.initiate
Authorization: Bearer <app service-auth jwt>
Content-Type: application/json

{
  "product": "atm.checkout.v1:<private-envelope>"
}

Checkout envelope

The ATM envelope can include public protocol refs and private checkout context. Apps should keep the raw envelope server-side.

Public refs
Product, price, entitlement, discount, and discount-code strongRefs.
Private session fields
Payer hint, return URL, cancel URL, app order id, selected options, buyer message flags, and buyer assertions.
Public-record policy
Optional checkout override for app records and public network.attested payment proofs.
json
{
  "recipient": "did:plc:creator",
  "paymentType": "shop",
  "amount": 500,
  "currency": "usd",
  "listing": {
    "$type": "com.atproto.repo.strongRef",
    "uri": "at://did:plc:creator/money.atmosphere.product/abc",
    "cid": "bafy..."
  },
  "payerDid": "did:plc:buyer",
  "returnUrl": "https://app.example/checkout/return",
  "cancelUrl": "https://app.example/product/abc",
  "metadata": {
    "appOrderId": "ord_123"
  },
  "publicRecords": {
    "appRecord": "private",
    "attestation": "private"
  }
}

Payment plan

Before ATM creates a processor session, it resolves one private payment plan. The plan freezes the routing mode, tax snapshot, payment-method policy, reporting category, fee split, public-record policy, and future allocation/settlement legs for that checkout.

RoutingDirect charge is the launch default. Marketplace-style destination charges or separate transfers are future feature-flagged modes.
Payment methodsApp/environment policy applies before Stripe eligibility. Klarna is excluded by default.
TaxATM stores tax behavior, tax code/category, liability, and invoice issuer snapshots privately.
AllocationsGross recipient amount, app fee pool, app share, and ATM share are modeled separately for future split settlement.
Portal boundaryStripe Customer Portal is only used for safe payment method update flows; amount changes, cancellations, and entitlements stay in ATM.

Public records

App dashboard defaults are frozen onto each payment when checkout starts. A checkout can override those defaults withpublicRecords. Whenattestation resolves toprivate, the payment can still complete and trigger app fulfillment events, but ATM does not write publicnetwork.attested.* records for it.

Completion

After payment, ATM sends app events and updates status. Apps should use redirects for UI continuity, not fulfillment truth.

  • Use payment.completed for fulfillment.
  • Use status polling when the buyer returns before the webhook arrives.
  • Use idempotency keys around app order creation and fulfillment.
  • Do not assume a browser return means a payment settled.
Checkout - Atmosphere Money Docs