Checkout Sessions
Checkout sessions enable merchants to build a headless catalog on their own domain and defer the paid checkout experience to the FluxStore-hosted storefront. Your backend creates a session via the API, redirects the customer to the returned URL, and the customer returns to a configured URL after payment completes or is cancelled.
Prerequisites
Before creating checkout sessions, you must configure allowed return-URL origins in your dashboard:
- Navigate to Dashboard > Configuration > API Keys > Checkout return URLs
- Add the exact origin of your storefront (e.g.,
https://shop.example.com). Origins only, paths are not part of the match - Without at least one origin configured, session creation returns
400with the message:"API checkout is not enabled for this store."
The flow
- Your backend calls Create a checkout session with the cart items, customer info, and return URLs.
- You redirect the customer to the
urlreturned in the response (or render a “Continue to checkout” button). - The customer completes payment on the FluxStore-hosted checkout.
- FluxStore redirects them to your
successUrlorcancelUrl.
Trust webhooks for state
The successUrl is a UX hint only. Always use the order.completed webhook to confirm payment and fulfill the order. The webhook payload includes checkout_session_id so you can correlate the webhook to the original session.
The URL placeholders {CHECKOUT_SESSION_ID} and {ORDER_ID} are filled in before redirecting the customer.
Idempotency
Pass an Idempotency-Key header with your create request. If the same key is used on retry:
- Prior session is
Open→ returns the same session with HTTP 200 (safe to retry) - Prior session is
Completed,Cancelled, orExpired→ returns HTTP 400 with the prior session’s ID and status; use a fresh key for a new session
Polling (optional)
For merchants who cannot run a webhook receiver, retrieve the session and check status. When status is Completed, orderId is populated.
Gifting
Gifting is opt-in per store and off by default. The store owner enables it under Store settings >
Checkout > Allow gifting. A gift object sent to a store that has not enabled it is rejected, so
check with the store owner before building against it. See Gifting for what the
feature does.
Including a gift object is what makes a session a gift; there is no separate boolean. Its presence
routes delivery, tier upgrade pricing and per-package purchase limits to recipientUsername /
recipientUuid. customer remains who pays, and who earns and spends loyalty points.
The response echoes gift back so you can reconcile which session was a gift, and carries a
warnings array of non-fatal conditions your integration should know about, since there is no
checkout UI to surface them to the buyer. gift is omitted entirely when the session is not a gift,
and warnings is an empty array when there is nothing to report. Fields FluxStore returns as null are
omitted rather than sent as null, so gift.recipientUuid is simply absent when it could not be
resolved.
| Warning | Meaning |
|---|---|
discord_actions_skipped_on_gift | A package in the cart carries a Discord role action. It was not granted to anyone, because FluxStore only holds the buyer’s linked Discord account, not the recipient’s. |
recipient_username_not_verified | This store can’t verify Minecraft usernames (offline-identity mode), so recipientUsername was not checked against Mojang. Goods delivered to a mistyped username can’t be recovered. |
Common errors
| Error message | Cause | Solution |
|---|---|---|
"API checkout is not enabled for this store." | No return-URL origins configured | Add an origin in Dashboard > Configuration > API Keys > Checkout return URLs |
"successUrl: URL origin (https://attacker.com) is not in the allow-list" | Origin mismatch | Add the origin to the dashboard allow-list |
"successUrl: URL scheme must be https" | Non-HTTPS URL (http is only allowed on localhost in development) | Use https:// |
"Idempotency-Key already used by Completed session cs_xxx" | Reused key after session completed | Use a new idempotency key |
"One or more packages are not found or inactive" | Package ID does not exist or is inactive | Verify package IDs and that they are active |
"Package '...' requires a server selection" | Package has userServerSelectionEnabled but no serverId was provided | Set serverId on the item |
"couponCode: ... (expired / exhausted / does not meet minimum)" | Coupon is invalid for this order | Retry without the coupon or use a valid one |
"The RecipientUsername field is required." | gift is present but recipientUsername is missing or empty | Supply a recipient, or drop the gift object |
"Recipient username must not contain spaces or control characters." | gift.recipientUsername failed validation. The name reaches server console commands, so this is a security rule, not formatting | Send a plain Minecraft username, 1-32 characters |
"Recipient UUID must contain only hexadecimal characters and dashes." | gift.recipientUuid is not a UUID | Send hex and dashes, or omit it and let FluxStore resolve it |
"This store does not accept gift purchases." | The store has not enabled gifting (Store settings > Checkout > Allow gifting, off by default) | Ask the store owner to enable gifting, or drop the gift object |
"'Rank 1' is already owned." | The beneficiary already holds this tiered package. On a gift the beneficiary is the recipient, not the buyer | Nothing to sell - they already have it |
"'Rank 1' cannot be purchased because 'Rank 3' is already owned, which is the same or a higher tier." | The beneficiary holds a higher tier in the same chain, so this would be a downgrade | Offer a higher tier, or a package outside that chain |
"Purchase limit reached. This package has already been purchased N time(s), and the limit is M." | The beneficiary has hit the package’s per-user or cumulative limit | Reduce the quantity, or offer a different package |
"You cannot gift a package to yourself." | gift.recipientUsername matches customer.playerUsername (case-insensitive) | Remove the gift object, or use a different recipient |
"Subscription packages cannot be gifted." | A subscription package is in items while gift is present | Remove the subscription package from the cart, or remove gift |
"The recipient username was not found. A paid Minecraft account is required to receive gifts from this store." | Store’s player identity mode is premium_required and gift.recipientUsername doesn’t resolve to a real Minecraft account | Fix the recipient’s username, or gift to a player with a paid account |