Skip to main content

POST /api/v1/apps/:appUuid/payment-providers/stripe/checkout-sessions

Mollie is the recommended provider for new integrations. Stripe remains

available for apps that use Stripe billing. For Mollie checkout sessions, see POST /api/v1/apps/:appUuid/payment-providers/mollie/checkout-sessions.

Creates a new checkout sessions resource.

This endpoint documentation is generated from the current Fastify route implementation and should be treated as the implementation-level contract for this version of the API.

Source route file: src/api/routes/external/private/bearer/apps/payment-providers/stripe/checkout-sessions/post.ts

Request Method​

POST

Base URL​

https://api.userdocks.local:5000

Endpoint​

/api/v1/apps/:appUuid/payment-providers/stripe/checkout-sessions

Path Variables​

VariableTypeRequiredDescription
appUuidstringtruePath variable from route pattern.

Query Parameters​

No query parameters.

HTTP Headers​

VariableTypeRequiredDescription
AuthorizationstringtrueBearer token in the form Bearer <jwt>.
Content-TypestringtrueUse application/json for JSON request bodies.

Request Body​

Schema reference: createCheckoutSessionSchema

{
"tenantUuid": "11111111-1111-1111-1111-111111111111",
"productUuid": "22222222-2222-2222-2222-222222222222",
"unitAmount": 10000,
"currency": "EUR",
"taxRateId": "txr_12345",
"quantity": 1,
"mode": "subscription",
"description": "Growth subscription",
"descriptionUnused": "Starter credit",
"recurringInterval": "month",
"recurringIntervalCount": 1,
"billingAddressCollection": true,
"shippingAddressCollection": false,
"successUrl": "https://app.example.com/success",
"cancelUrl": "https://app.example.com/cancel",
"termsOfServiceUrl": "https://app.example.com/terms",
"collectTermsOfServiceConsent": true,
"isTaxIdCollectionEnabled": true,
"isTaxIdCollectionRequired": false
}

description is optional. For Stripe checkout sessions in payment or setup mode, it is copied to the generated Stripe invoice description (shown as the invoice memo in Stripe). For subscriptions it becomes the recurring invoice line description. descriptionUnused is optional and is used only for the unused-time credit line of a Stripe upgrade. Both fields are limited to 500 characters and do not change the checkout-session response.

Successful Response​

Success status code(s): 200.

{
"kind": "checkoutSessions",
"totalItems": 1,
"itemsLength": 1,
"items": [
{
"createdCheckoutSession": {
"id": 1,
"uuid": "csrow_11111111-1111-1111-1111-111111111111",
"appUuid": "app_11111111-1111-1111-1111-111111111111",
"paymentProviderUuid": "pp_11111111-1111-1111-1111-111111111111",
"sessionId": "cs_test_12345",
"nextActionUrl": "https://checkout.stripe.com/pay/cs_test_12345",
"userUuid": "user_11111111-1111-1111-1111-111111111111",
"tenantUuid": "tenant_11111111-1111-1111-1111-111111111111",
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z",
"deletedAt": null
},
"nextAction": {
"url": "https://checkout.stripe.com/pay/cs_test_12345"
}
}
]
}

Subscription upgrades​

Stripe receives inline price_data tied to the existing provider product. A Userdocks ProductPrice is not created. Amounts are positive minor-unit integers (10000 is EUR 100.00); currencies are normalized to uppercase. Inline subscriptions require recurringInterval, and recurringIntervalCount defaults to 1. Deprecated productPriceUuid and priceId inputs still use the legacy provider price.

When mode is subscription and the requested same-currency price is more expensive than the tenant's current price, this endpoint updates the existing Stripe subscription item and invoices the prorated difference immediately. The new price is pending until that invoice is paid.

For an immediately paid invoice, nextAction.url is the configured successUrl. If authentication or payment retry is required, it is the Stripe hosted invoice URL. In the latter case the old Stripe price and Userdocks plan period remain active. A failed or expired pending update creates no plan-period history. Cross-currency plan comparisons are rejected.

Matching billing cadences keep their anchor. Stripe applies its normal billing anchor reset when the recurring cadence changes. See Subscription upgrades and plan history.

When description or descriptionUnused is supplied, the upgrade must retain the current billing cadence. Userdocks preserves Stripe's Unused time on ... after ... and Remaining time on ... after ... wording while replacing the product-name portion. The recurring description is also applied to future billing-cycle invoice lines. While payment or authentication is pending, the response links to the hosted invoice; retrying the identical request reuses that invoice.

Error Responses​

HTTP StatusExample Error
401{"errors":[{"validation":"error","code":"[E4010]","message":"Unauthorized Token"}]}
403{"errors":[{"validation":"error","code":"[E4030]","message":"App Is Disabled"}]}
400{"errors":[{"validation":"error","code":"[E4000]","message":"Bad Request / validation error"}]}
500{"errors":[{"validation":"error","code":"[E0000]","message":"Internal Server Error"}]}

Example​

const url = `https://api.userdocks.local:5000/api/v1/apps/appUuid-value/payment-providers/stripe/checkout-sessions`;

const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: 'Bearer <jwt>',
'Content-Type': 'application/json',
},
body: '{"tenantUuid":"11111111-1111-1111-1111-111111111111","productUuid":"22222222-2222-2222-2222-222222222222","unitAmount":10000,"currency":"EUR","taxRateId":"txr_12345","quantity":1,"mode":"payment","description":"September service invoice","billingAddressCollection":true,"shippingAddressCollection":false,"successUrl":"https://app.example.com/success","cancelUrl":"https://app.example.com/cancel","collectTermsOfServiceConsent":true}',
});
const data = await response.json();
console.log(response.status, data);

Named discounts​

Supply the root-level discount with { "name": "Partner deal", "amount": 1000, "duration": "once" } or duration "forever". Amounts use the price currency's minor units and reduce the product line once, regardless of quantity. The original price and named reduction remain visible on the invoice. Discounts must be smaller than the product line subtotal; setup sessions and charges below the provider minimum are rejected.

See Named billing discounts for renewal behavior, per-line invoice examples, tax handling, and midterm upgrade calculations.