Embed a Payment Element
Use Atlas's merchant API to create a one-time Checkout Session, then use Stripe's Payment Element on your own checkout page. This release uses the Checkout Sessions API with ui_mode: "elements", CheckoutElementsProvider, and useCheckoutElements.
Developer preview. Hosted checkout remains the default. Sandbox testing, provider configuration, and deployment are required before enabling this on a merchant website.
What is supported
For a reusable scan-to-pay page without writing code, finish business setup and open Your Atlas Pay QR on the dashboard or Connect screen. Download the QR or copy its link. Test and live codes open separate checkout.atlaspay.sh/m/test/... and /m/live/... pages. Customers enter the agreed amount in your default currency and pay through Stripe Elements, with eligible conversion choices shown before confirmation. Payment collection starts only when your Stripe account can accept charges in that mode. Customers can pay as guests or sign in with Google or email to use a saved Atlas wallet card. Already signed-in buyers see their wallet automatically. Test and live wallets stay separate. No additional Vercel key is required.
POST /api/v1/checkouts supports immediate one-time payments with either hosted or Elements UI. Both use the same server-side verification, webhook events and automatic risk decisions. Atlas wallet orders already use Elements with manual authorization; currency conversion is disabled for those orders. Subscription enrollment currently opens Stripe-hosted checkout; this endpoint does not create embedded subscriptions.
Start with API keys and checkout verification and currencies and FX. The merchant API key stays on your server. Stripe fields collect card details; your application must never receive or log card numbers or CVCs.
1. Create the session on your server
Authenticate the buyer/order in your own application. Load the price, currency and reference from your server's order record, not browser-submitted totals. Send the request below using a key with checkouts:write. Persist one idempotency key per payment attempt and reuse the exact request after a timeout.
curl https://dashboard.atlaspay.sh/api/v1/checkouts \
-H "Authorization: Bearer $ATLAS_PAY_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-1042-elements-v1' \
-d '{
"amount": 2500,
"currency": "USD",
"reference": "order-1042",
"description": "Order 1042",
"ui_mode": "elements",
"adaptive_pricing": true,
"success_url": "https://shop.example.com/payment-return",
"cancel_url": "https://shop.example.com/cart"
}'
Both URLs must have the exact HTTPS origin registered to your API key. In Elements mode, success_url becomes Stripe's return URL for redirect/verification flows. cancel_url is validated but not passed to Stripe; your page owns its back-to-cart navigation. Do not use the older ui_mode: "custom" with this API.
An open Elements session returns data.id, data.ui_mode, data.client_secret, and data.account_id, alongside the ordinary checkout fields. It has no hosted url. Persist id against the order. Pass the client secret and account ID only to the buyer authorized to pay that order, in a Cache-Control: no-store response. Never log the response body, store the secret in browser storage, or put it in a URL.
Client secrets appear only on Elements creation or an open, pending creation replay. GET /checkouts/{id}, webhook payloads and event-feed records never include them. A replay of a closed or risk-held session can have no secret: reconcile status and show the result; do not automatically create another payment.
2. Initialize Stripe for the same account and mode
Install @stripe/stripe-js and @stripe/react-stripe-js. Atlas's current implementation is checked with Stripe.js 9.10 and React Stripe.js 6.9. Get the Atlas platform's publishable key for your environment from your Atlas operator. It must match the platform that created the session and its test/live mode; your merchant's unrelated publishable key will not work. Never use a Stripe secret key here.
Download the complete React example. It contains the provider, secure payment fields, currency selector, visible quoted rate, current total, and confirmation/error handling. Supply the creation response, the matching publishable key, and a callback that asks your server to reconcile the stored checkout.
<AtlasPaymentElement
publishableKey={atlasPlatformPublishableKey}
session={authorizedCheckout}
onReconcile={refreshOrderFromYourServer}
/>
Set adaptivePricing: { allowed: true } on CheckoutElementsProvider and render CurrencySelectorElement near PaymentElement. Only Stripe's offered currencies are selectable. Read the current useCheckoutElements() result for totals and currencyOptions[].currencyConversion; switching currencies must update all amounts shown. The example handles immediate one-time payments only. Use hosted enrollment for subscription pricing, trial and renewal disclosures.
3. Confirm, then verify on your server
Call checkout.confirm({ redirect: "if_required" }). Disable repeat submissions and handle errors returned by Stripe. Redirect-based payment methods still leave the page; the registered return page must reconcile the stored checkout on your server. Do not rely solely on the React callback.
Your server reads GET /api/v1/checkouts/{id} with checkouts:read. Verify the checkout belongs to this buyer's order and match reference, original amount/currency and mode. Fulfill only when status is paid, risk_decision is allow, and fulfillment_allowed is true. A successful confirm or browser return is not proof of payment. For pending results, use verified webhooks or bounded server polling; keep fulfillment idempotent.
The original API amount stays separate from the buyer's converted presentment. Do not compare a localized Stripe.js total against the original order amount. Refund through Atlas in the original currency. See webhook verification and retries.
Deployment and acceptance
- Serve the merchant checkout over HTTPS. Register the exact merchant origin with the Atlas API key and any payment-method domains required by Stripe. Configure CSP and consent settings for Stripe.js. Do not wrap the checkout in another iframe.
- Enable appropriate payment methods and Adaptive Pricing on the correct connected account. Load Stripe.js using its official loader so authentication and fraud signals work. Stripe integration guide.
- Test currency switching, no-conversion fallback, bank authentication, declines, redirects, pending methods, expired sessions and an interrupted response replay. Exercise the existing fraud hold and refund flows.
- Verify that a checkout can never be paid by exposing another buyer's secret, that secrets are absent from logs/analytics/URLs, and that refreshing the return page cannot fulfill twice.
Atlas's trusted IP/device checks on its own wallet checkout do not automatically extend to an unrelated merchant website. Merchant sites need their own authenticated order access, anti-abuse controls and rate limits; processor risk assessment still runs on the resulting payment.
Custom checkout branding
Workspace owners can open Settings → Branding to preview and publish their logo, button color and page background on Atlas Pay QR payment pages and order checkout. The Branding plan costs USD 4.99 per month, plus applicable tax, and can be canceled in Manage billing. Access continues through the paid period after cancellation. Test and live subscriptions are separate; a test subscription cannot enable live branding.
Checkout displays the business name from Settings → Business profile alongside the uploaded logo. Test mode adds a slim orange warning strip. The editor accepts PNG, JPG and WebP logos, resizes them for checkout, and adjusts text contrast to the chosen colors. Stripe-hosted payment links and emails use Stripe's own branding settings.