Applying Discounts to Payments
Frame Payments provides a comprehensive discount system that enables you to create flexible promotional campaigns and apply them seamlessly to customer payments. This guide explains how to set up discounts, generate customer-facing codes, and apply them at checkout.
For detailed API specifications and parameters, please refer to our Coupons API documentation and Promotion Codes API documentation.
Understanding the Discount System
Frame's discount system uses a two-tier architecture designed for flexibility and control:
- Coupons are reusable discount templates that define the discount rules, duration, and restrictions.
- Promotion Codes are the customer-facing codes generated from coupons that customers enter at checkout.
- Charge Intents accept promotion codes to automatically calculate and apply discounts.
This separation allows you to create a single discount rule (coupon) and generate multiple unique codes from it, each with its own expiration dates, usage limits, and targeting options.
Discount Workflow Overview
The process of creating and applying discounts involves three main steps:
Create a Coupon Template
- Define your discount structure (percentage or fixed amount).
- Set validity periods, usage limits, and minimum order requirements.
- Configure which products the discount applies to.
Generate Promotion Codes
- Create customer-facing codes from your coupon template.
- Set code-specific restrictions (expiration, customer targeting, first-time buyer only).
- Generate multiple codes from a single coupon for different distribution channels.
Apply Codes at Checkout
- Customers enter promotion codes when creating a charge intent.
- Frame automatically validates eligibility and calculates the discount.
- Support for stacking up to 20 codes per transaction.
Step 1: Creating a Coupon Template
Begin by creating a coupon that defines your discount structure. The coupon acts as a reusable template for generating customer-facing promotion codes.
Example: Summer Sale Coupon
curl --request POST \
--url https://api.framepayments.com/v1/coupons \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "SUMMER2025_20PCT",
"description": "Summer sale - 20% off all orders",
"discount_type": "percentage",
"discount_value": 20,
"duration": "once",
"status": "active",
"applicable_to": "all_products",
"max_redemptions": 1000,
"minimum_order_amount_cents": 5000,
"minimum_order_amount_currency": "USD",
"discount_cap_cents": 10000,
"discount_cap_currency": "USD",
"valid_from": "2025-06-01T00:00:00Z",
"valid_until": "2025-08-31T23:59:59Z",
"metadata": {
"campaign": "summer_2025"
}
}'
Configuration Options
- Discount Type: Choose
percentage(e.g., 20% off) orfixed_amount(e.g., $10 off). - Duration:
once- Applies to a single purchase only.repeating- Applies for a specified number of billing cycles (requiresduration_in_months).forever- Applies indefinitely to all eligible purchases.
- Applicable To: Restrict to
all_productsorspecific_productsusingproduct_id. - Minimum Order Amount: Set a minimum purchase requirement to qualify for the discount.
- Discount Cap: Limit the maximum discount amount (useful for percentage discounts).
- Max Redemptions: Control how many times the coupon can be used across all customers.
After creating the coupon, save the returned id - you'll need it to generate promotion codes.
Step 2: Generating Promotion Codes
Once you have a coupon template, create customer-facing promotion codes that inherit the coupon's discount rules but can have their own specific restrictions.
Creating Multiple Codes from One Coupon
You can generate multiple codes from a single coupon for different distribution channels or customer segments:
General Campaign Code
curl --request POST \
--url https://api.framepayments.com/v1/promotion_codes \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"code": "SUMMER50",
"coupon_id": "cpn_a2b43435cdd944bb8b7ac3ad0ec8b3e2",
"active": true,
"max_redemptions": 500,
"minimum_amount_cents": 5000,
"minimum_amount_currency": "USD",
"expires_at": "2025-08-31T23:59:59Z",
"metadata": {
"channel": "email_campaign"
}
}'
First-Time Customer Code
curl --request POST \
--url https://api.framepayments.com/v1/promotion_codes \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"code": "WELCOME2025",
"coupon_id": "cpn_a2b43435cdd944bb8b7ac3ad0ec8b3e2",
"active": true,
"first_time_transaction": true,
"max_redemptions": 200,
"expires_at": "2025-12-31T23:59:59Z",
"metadata": {
"channel": "signup_bonus"
}
}'
Customer Specific Code
curl --request POST \
--url https://api.framepayments.com/v1/promotion_codes \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"code": "WELCOME2025",
"coupon_id": "cpn_a2b43435cdd944bb8b7ac3ad0ec8b3e2",
"customer": "cust_1234",
"active": true,
"first_time_transaction": false,
"max_redemptions": 200,
"expires_at": "2025-12-31T23:59:59Z",
"metadata": {
"channel": "signup_bonus"
}
}'
Promotion Code Features
- Customer Targeting: Set
customerto restrict a code to a specific customer. - First-Time Buyers: Enable
first_time_transactionto limit usage to new customers only. - Independent Limits: Each code can have its own expiration date and usage limits, separate from the parent coupon.
Step 3: Applying Discounts at Checkout
When creating a charge intent, include the promotion codes in the promotion_codes array. Frame will automatically validate eligibility and apply the discounts.
Complete Charge Intent with Promotion Codes
curl --request POST \
--url https://api.framepayments.com/v1/charge_intents \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"amount": 15000,
"currency": "USD",
"description": "Order #12345 - Summer Collection",
"confirm": true,
"receipt_email": "customer@example.com",
"promotion_codes": ["SUMMER50", "WELCOME2025"],
"customer_data": {
"name": "John Doe",
"email": "john.doe@example.com"
},
"payment_method_data": {
"card_number": "4242424242424242",
"exp_month": "12",
"exp_year": "26",
"cvc": "123",
"type": "card",
"billing": {
"line_1": "456 Billing Ave",
"city": "Los Angeles",
"country": "US",
"state": "CA",
"postal_code": "90001"
}
},
"shipping": {
"line_1": "123 Main Street",
"city": "New York",
"country": "US",
"state": "NY",
"postal_code": "10001"
}
}'
In this example:
- Original amount: $150.00
- Discount applied: 20% = $30.00
- Final amount charged: $120.00
Discount Stacking and Priority
Frame supports applying up to 20 promotion codes per transaction, enabling sophisticated discount strategies.
How Discounts Are Applied
When multiple promotion codes are provided, discounts are applied in the order of their promotion_codes index.
Example: Multiple Discounts
{
"amount": 20000,
"promotion_codes": [
"SUMMER50", // 20% off
"LOYALTY10" // $5 off
]
}
Calculation:
- Original: $200.00
- After 20% discount: $160.00
- After $5 fixed discount: $155.00
- Final amount: $155.00
Validation and Error Handling
Frame automatically validates promotion codes and returns clear error messages when codes cannot be applied. You can check the eliginility of a promotion code and the application order with the validation endpoint.
Setting Appropriate Limits
Always configure limits to protect your business:
{
"max_redemptions": 1000, // Prevent unlimited budget exposure
"minimum_order_amount_cents": 5000, // Ensure profitability per transaction
"discount_cap_cents": 10000, // Cap maximum discount amount
"expires_at": "2025-08-31T23:59:59Z" // Clear campaign end date
}
Common Use Cases
Limited Time Flash Sale
Create urgency with a short validity window:
{
"name": "FLASH_SALE_24H",
"discount_type": "percentage",
"discount_value": 30,
"duration": "once",
"valid_from": "2025-07-04T00:00:00Z",
"valid_until": "2025-07-04T23:59:59Z",
"max_redemptions": 100
}
First-Time Customer Welcome Discount
Incentivize new customer acquisition:
{
"code": "WELCOME10",
"first_time_transaction": true,
"discount_type": "fixed_amount",
"discount_value": 10,
"minimum_amount_cents": 0
}
Subscription Annual Discount
Encourage annual commitments:
{
"name": "ANNUAL_SAVE20",
"discount_type": "percentage",
"discount_value": 20,
"duration": "forever",
"applicable_to": "specific_products",
"product_id": "prod_annual_subscription"
}
VIP Customer Personal Code
Reward high-value customers:
{
"code": "VIP_JOHN_50",
"customer": "cus_abc123",
"discount_type": "percentage",
"discount_value": 50,
"max_redemptions": 1,
"expires_at": "2025-12-31T23:59:59Z"
}
Cart Abandonment Recovery
Re-engage customers who didn't complete checkout:
{
"name": "COMEBACK_15",
"discount_type": "percentage",
"discount_value": 15,
"duration": "once",
"valid_from": "2025-06-01T00:00:00Z",
"valid_until": "2025-06-30T23:59:59Z",
"metadata": {
"campaign": "cart_recovery",
"trigger": "abandoned_7_days"
}
}
Real-Time Code Validation
Validate promotion codes as customers enter them (before submitting payment):
curl --request GET \
--url https://api.framepayments.com/v1/promotion_codes/:code \
--header 'Authorization: Bearer YOUR_API_KEY'
This allows you to:
- Show discount amount before payment
- Display error messages immediately
- Calculate final amount in real-time
- Improve customer experience
Quick Reference
API Endpoints
| Action | Method | Endpoint |
|---|---|---|
| Create Coupon | POST | /v1/coupons |
| Update Coupon | PATCH | /v1/coupons/:id |
| List Coupons | GET | /v1/coupons |
| Get Coupon | GET | /v1/coupons/:id |
| Create Promotion Code | POST | /v1/promotion_codes |
| Update Promotion Code | PATCH | /v1/promotion_codes/:id |
| List Promotion Codes | GET | /v1/promotion_codes |
| Get Promotion Code | GET | /v1/promotion_codes/:id |
| Create Charge Intent | POST | /v1/charge_intents |
Key Concepts
- Coupon: Reusable discount template that defines rules and restrictions
- Promotion Code: Customer-facing code generated from a coupon
- Stackable Discounts: Up to 20 codes can be applied per transaction
- Duration Types:
once(single use),repeating(multiple cycles),forever(indefinite) - Discount Types:
percentage(e.g., 20%) orfixed_amount(e.g., $10)
Status Values
Coupon Statuses:
active- Coupon can be usedinactive- Temporarily disabledarchived- Preserved but not usabledeleted- Soft deleted
Promotion Code Flags:
is_expired- Past expiration dateis_maxed_out- Reached redemption limitis_redeemable- Currently usableis_customer_specific- Restricted to one customer
Additional Resources
For detailed technical specifications and parameter references: