Applying Coupons
Available via: API only (private key)
Overview
You can apply a discount coupon to a payment before the customer completes it with the SDK. Coupons are created in your Merchant Dashboard — see Creating & Managing Coupons — and there are two kinds:
- One-time coupons — apply only to one-time payments.
- Subscription coupons — apply only to subscriptions (created from a subscription offer).
In both cases, the coupon is applied to a payment that you created beforehand, and before the customer pays. The discounted amount is what gets charged.
Applying/removing a coupon is a server-to-server operation (private key). The customer enters a code in your SDK checkout UI, your frontend sends it to your backend, and your backend applies it via the API. You can then show the discounted total (read it back with the public-key endpoint below) before the SDK confirms the payment.
How It Works
- Create the payment on your backend (private key) and get back a
paymentId:- One-time payment → see Server-to-Server Payments.
- Subscription (from a subscription offer) → see Initiating a Subscription.
- Apply the coupon to that
paymentIdfrom your backend (private key). - Confirm the payment with the SDK
CardElement— the customer is charged the discounted amount.
The coupon must be applied while the payment is still pending (before it is confirmed). Once the customer has paid, the coupon can no longer be changed.
Automatic Routing by Coupon Type
You don't tell the API which coupon system to use — it is routed automatically from the coupon's type and the nature of the payment:
- a one-time coupon applies to a one-time payment,
- a subscription coupon applies to a subscription's first payment.
Applying a coupon to the wrong kind of payment (a one-time coupon on a subscription payment, or vice-versa) returns an error.
Endpoints
The apply/remove endpoints are server-to-server and use your private key (X-Inflow-Api-Key). The read endpoint is public-key, so your frontend can display the discounted total.
Apply a coupon (private key)
curl -X POST https://api.inflowpay.xyz/api/server/payment/{paymentId}/coupon \
-H "X-Inflow-Api-Key: inflow_prod_your_key" \
-H "Content-Type: application/json" \
-d '{ "code": "SAVE10" }'
This endpoint is reserved for server-to-server integration only. Never expose your private key in frontend code.
Response:
{
"paymentId": "pay_abc123",
"paymentType": "ONE_TIME",
"status": "INITIATION",
"amount": 31500,
"amountTaxesIncluded": 37800,
"currency": "EUR",
"couponDiscountInCents": 3500,
"coupon": {
"code": "SAVE10",
"discountType": "PERCENTAGE",
"discountAmountInCents": 3500,
"finalAmountInCents": 31500
}
}paymentType—ONE_TIMEorSUBSCRIPTION(auto-detected from the payment).amount— amount excluding tax;amountTaxesIncluded— the total the customer is charged.coupon— the applied coupon, ornullwhen none is applied.
Remove a coupon (private key)
curl -X DELETE https://api.inflowpay.xyz/api/server/payment/{paymentId}/coupon \
-H "X-Inflow-Api-Key: inflow_prod_your_key"Returns the same payload as Apply, with coupon: null and the amount restored.
Read the current payment (public key)
Your frontend can read the (discounted) payment to display it — this is public-key and safe in the browser:
curl https://api.inflowpay.xyz/sdk/payment/{paymentId} \
-H "X-Inflow-Public-Key: inflow_pub_your_key"Use this to show the current paymentType, discounted amount, and applied coupon.
Example: One-Time Payment
// 1. Backend — create a one-time payment (private key).
// See: /docs/server-to-server-payments
const { id: paymentId } = await createOneTimePayment(/* ... */);
// 2. Backend — apply a one-time coupon (private key).
const res = await fetch(
`https://api.inflowpay.xyz/api/server/payment/${paymentId}/coupon`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Inflow-Api-Key': process.env.INFLOW_PRIVATE_KEY,
},
body: JSON.stringify({ code: 'SAVE10' }),
},
);
const pricing = await res.json();
// pricing.paymentType === 'ONE_TIME'
// pricing.amountTaxesIncluded → discounted total to return to your frontend
// 3. Confirm with the SDK CardElement using the same paymentId
// (charges the discounted amount).Example: Subscription Payment
// 1. Backend — initiate a subscription from an offer (private key).
// See: /docs/initiating-a-subscription
const paymentId = await initiateSubscriptionAndGetPaymentId(offerId /* ... */);
// 2. Backend — apply a subscription coupon (private key). Same endpoint:
// the API routes it to the subscription coupon system automatically.
const res = await fetch(
`https://api.inflowpay.xyz/api/server/payment/${paymentId}/coupon`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Inflow-Api-Key': process.env.INFLOW_PRIVATE_KEY,
},
body: JSON.stringify({ code: 'WELCOME25' }),
},
);
const pricing = await res.json();
// pricing.paymentType === 'SUBSCRIPTION'
// 3. Confirm with the SDK CardElement using the same paymentId
// (charges the discounted first payment).The coupon code can be the coupon's own code or a promotion code attached to a subscription coupon — see Creating & Managing Coupons.
These coupon endpoints are also available in the API reference.