Skip to content
Fluxer API

Billing

These routes start a premium purchase on Stripe and receive Stripe's events. Checkout finishes on Stripe's pages, so the checkout routes return a URL for the browser to open. Entitlement state and subscription self-service are on Premium.

The checkout routes only work while billing is on, and the webhook only works while Stripe and its webhook secret are set up. Both checkout routes are user-only, so a bot token gets 403 ACCESS_DENIED.

The checkout routes and the billing portal route return this object. Open url in the browser.

FieldTypeDescription
urlstringThe URL to open in the browser
{
"url": "https://checkout.example.com/c/pay/cs_test_9f8e7d6c5b4a"
}

Premium state returns this object as billing.refund_eligibility. Self-hosted instances have no self-service refunds and always return the values below.

FieldTypeDescription
eligiblebooleanAlways false
reason?stringAlways feature_unavailable
invoice_id?stringAlways null
invoice_amount_paid_cents?integerAlways null
currency?stringAlways null
paid_at?ISO8601 timestampAlways null
refund_window_expires_at?ISO8601 timestampAlways null
cooldown_expires_at?ISO8601 timestampAlways null
cancels_subscriptionbooleanAlways false
provider?stringAlways null

The acknowledgement Receive Stripe webhook returns.

FieldTypeDescription
receivedbooleanAlways true
POST/v1/stripe/checkout/subscription

Creates a recurring premium checkout session and returns a redirect URL object.

If the account already has an active or trialing subscription and price_id is the price for the other billing cycle, Fluxer schedules the switch for the end of the current period and creates no checkout session. It clears a pending cancellation, sends User Update and returns the web app's premium callback URL.

FieldTypeDescription
price_idstringStripe price ID of a monthly or yearly premium plan (1-256 characters)
country_code?1stringTwo-letter country code that picks the price catalog (2 characters)
client_geoip_country_code?stringTwo-letter country code the client detected, saved with the purchase (2 characters)
eu_withdrawal_waiver_accepted?booleanWhether the user accepted the EU withdrawal waiver for digital content
payment_method?2stringEither card, pix or upi (default card)
is_business?booleanWhether to require a billing address for tax invoicing (default false)

1 Fluxer uses this only when it can't find the request's country. With prices set in environment config, a price in a currency other than USD or EUR needs it.

2 With prices set in environment config, pix needs a BRL price and upi needs an INR price. Prices saved in the instance billing settings accept only card.

StatusBodyCondition
200redirect URL objectThe session was created or the billing cycle change was scheduled
400error responseSTRIPE_INVALID_PRODUCT for an unknown price
400error responseSTRIPE_INVALID_PRODUCT_CONFIGURATION for a gift price, a wrong catalog or a bad payment_method
400error responseUNCLAIMED_ACCOUNT_CANNOT_MAKE_PURCHASES for an unclaimed account
400error responseSTRIPE_ERROR when Stripe rejects the request
403error responsePURCHASE_EMAIL_VERIFICATION_REQUIRED for an unverified email address
403error responsePREMIUM_PURCHASE_BLOCKED with a reason in the table below

A PREMIUM_PURCHASE_BLOCKED error has a top-level reason field. For existing_subscription, it also has subscription_status with the status of that subscription.

ReasonCondition
purchase_disabledPurchases are disabled for the account
lifetimeThe account has lifetime premium
existing_subscriptionThe customer already has a subscription that is active, trialing, past_due, unpaid, incomplete or paused

Premium changes only after Receive Stripe webhook gets the matching event.

The rate limit is 3 requests per minute, on the stripe:checkout:subscription bucket.

POST/v1/stripe/checkout/gift

Creates a one-time premium gift checkout session and returns a redirect URL object. The account checks from Create subscription checkout apply, but lifetime premium or an existing subscription doesn't block a gift.

FieldTypeDescription
price_idstringStripe price ID of a gift (1-256 characters)
country_code?1stringTwo-letter country code that picks the price catalog (2 characters)
client_geoip_country_code?stringTwo-letter country code the client detected, saved with the purchase (2 characters)
eu_withdrawal_waiver_accepted?booleanWhether the user accepted the EU withdrawal waiver for digital content
is_business?booleanWhether to require a billing address for tax invoicing (default false)
payment_method?stringIgnored by this route (card, pix or upi)

1 Fluxer uses this only when it can't find the request's country. With prices set in environment config, a price in a currency other than USD or EUR needs it.

StatusBodyCondition
200redirect URL objectThe session was created
400error responseSTRIPE_INVALID_PRODUCT for an unknown price
400error responseSTRIPE_INVALID_PRODUCT_CONFIGURATION for a recurring price or a wrong catalog
400error responseUNCLAIMED_ACCOUNT_CANNOT_MAKE_PURCHASES for an unclaimed account
400error responseSTRIPE_ERROR when Stripe rejects the request
403error responsePURCHASE_EMAIL_VERIFICATION_REQUIRED for an unverified email address
403error responsePREMIUM_PURCHASE_BLOCKED with reason set to purchase_disabled

The gift shows up in List current user gifts after Stripe confirms the payment.

The rate limit is 3 requests per minute, on the stripe:checkout:gift bucket.

POST/v1/stripe/webhookUnauthenticated

Accepts a signed Stripe event and returns a webhook received object. Stripe signs the raw body, and a proxy that changes the body breaks the signature.

FieldTypeDescription
Stripe-SignaturestringStripe signature over the raw request body
StatusBodyCondition
200webhook received objectThe event was verified and queued
400error responseSTRIPE_WEBHOOK_SIGNATURE_MISSING without the header, STRIPE_WEBHOOK_NOT_AVAILABLE when the Stripe client is not set up
401error responseSTRIPE_WEBHOOK_SIGNATURE_INVALID when the signature does not verify
500error responseThe event could not be queued

Fluxer returns 200 before it processes the event and processes an event Stripe sends twice only once. It sends User Update for any account change the event causes.

The rate limit is 300 requests per minute, on the stripe:webhook bucket.