Creating the Checkout Session
Available via: API only (private key
X-Inflow-Api-Key)
Never create the session from the application. That would expose your API key and let the user modify their own identifier. The call belongs on your backend, after it has authenticated the user.
Subscription
The offer identifier goes in the path, not in the body.
POST https://api.inflowpay.xyz/api/checkout/sessions/subscription/sub_offer_xxx
X-Inflow-Api-Key: inflow_prod_your_key
Content-Type: application/json
{
"successUrl": "https://app.yourbrand.com/purchase/return",
"cancelUrl": "https://app.yourbrand.com/purchase/cancel",
"returnMode": "APP_RETURN",
"metadatas": {
"appUserId": "usr_123",
"platform": "ios"
},
"customer": {
"id": "cus_xxx",
"locked": true
}
}Create the offer first, from the Dashboard or the API — see Creating a Subscription Offer.
One-time payment
The route is POST /api/checkout/sessions/one-time-payment, with the products in the body:
curl -X POST https://api.inflowpay.xyz/api/checkout/sessions/one-time-payment \
-H "X-Inflow-Api-Key: inflow_prod_your_key" \
-H "Content-Type: application/json" \
-d '{
"currency": "EUR",
"products": [{ "name": "Lifetime access", "price": 4999, "quantity": 1 }],
"successUrl": "https://app.yourbrand.com/purchase/return",
"cancelUrl": "https://app.yourbrand.com/purchase/cancel",
"returnMode": "APP_RETURN",
"metadatas": { "appUserId": "usr_123", "platform": "ios" }
}'Both endpoints and their full field lists are documented in Checkout V2.
Response
{
"object": "checkout_session",
"id": "sess_KAriHKBIiMtyPFnmIjHor",
"status": "open",
"type": "subscription",
"checkoutUrl": "https://checkout.inflowpay.com/pay/sess_KAriHKBIiMtyPFnmIjHor",
"expiresAt": "2026-07-31T00:21:42.769Z"
}Send the buyer to checkoutUrl — see Opening the Checkout.
Key points
metadatas.appUserId is your join key
metadatas.appUserId is your join keyIt is copied as-is onto the Payment and onto the Subscription, and you will find it again in the webhook payloads. That is how you will know which user paid.
The field is
metadatas, with an "s".metadatais silently ignored. See Metadata for the accepted value types.
customer.locked: true anchors the buyer
customer.locked: true anchors the buyerIt locks the pre-filled fields on the checkout. The buyer can no longer change their email or their identity — the anchoring to your user is guaranteed server-side. Pass customer.id when you already have an Inflow customer for this user; the payment and any saved payment method stay attached to that customer even if the buyer edits what they can still edit.
Store the sessionId
sessionIdStore it in your database, associated with your user. It is your reconciliation point in Refreshing Entitlements.
returnMode chooses the final screen
returnMode chooses the final screenIt is the parameter that distinguishes the two flows described in App-to-Web Checkout:
| Value | For whom | What the buyer sees |
|---|---|---|
DEFAULT | By default | The confirmation page, unchanged |
APP_RETURN | They come from your app | "Back to the app" button + automatic redirect after 5 s |
APP_INSTALL | They come from the web, without the app | The App Store / Google Play badges + the sign-in email, without automatic redirect |
In APP_INSTALL, add appStoreUrl and playStoreUrl (https:// URLs pointing to your listings). Only one of the two is enough if you publish on a single platform; without either one, the screen asks the buyer to install an app without telling them where.
| Field | Type | Required | Description |
|---|---|---|---|
returnMode | string | No | DEFAULT, APP_RETURN, or APP_INSTALL |
appStoreUrl | string | No | https:// URL of your App Store listing — used by APP_INSTALL |
playStoreUrl | string | No | https:// URL of your Google Play listing — used by APP_INSTALL |
Where these three fields can be set
They are also configurable on the subscription offer and on the payment link from the Dashboard.
| Session type | Precedence |
|---|---|
| Subscription | What you send on the session wins; the offer acts as the fallback. Configure it once in the Dashboard and send nothing, or override per session. |
| One-time payment | No offer sits behind the session — what you send is all that applies. |
Next steps
- Opening the Checkout — send the buyer to
checkoutUrlcorrectly. - Session Customization — brand the checkout page with your colors, logo, and name.
- Trial Periods — what changes when the offer has a free trial (no
payment.*event).
Updated about 15 hours ago