/api/coupons
List all coupons with optional filtering (requires administrator access)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort - JSON array with field name and direction
["fieldName","ASC|DESC"]
id, name, stripeCouponId, couponTypeCode, couponTypeName, discountPercentage, trialDays, couponDurationTypeCode, couponDurationTypeName, durationInMonths, isActive, createdAt, updatedAt
sort=["name","ASC"] - Sort by name in ascending order
page - Page number (1-based)
page=1 - Get the first page
perPage - Number of items per page
perPage=10 - Show 10 items per page
filter - JSON object with field name/value pairs for filtering
{"fieldName1":"value1","fieldName2":value2}
filter={"couponTypeCode":"DISC","name":"Summer"} - Filter discount coupons with name containing "Summer"
q - Global search across coupon name, Stripe coupon ID, coupon type name, and duration type nameisActive - Filter by active status (true/false)couponTypeCode - Filter by coupon type code (DISC, TRIA)couponTypeName - Filter by coupon type name (partial match)couponDurationTypeCode - Filter by duration type code (ONCE, REPE, FORE)couponDurationTypeName - Filter by duration type name (partial match)q in the filter will search across all text columns:
filter={"q":"discount","isActive":true} - Find active coupons with "discount"
in any text field
active - Filter by active status (true/false)syncWithStripe - Whether to sync with Stripe before fetching data (default: true)
Example Requests:
GET /api/coupons?page=1&perPage=10&sort=["id","ASC"]&filter={"couponTypeCode":"DISC"}&syncWithStripe=true
GET /api/coupons?page=2&perPage=20&filter={"q":"discount","isActive":true}
GET /api/coupons?filter={"couponTypeName":"Percentage","couponDurationTypeCode":"ONCE"}
GET /api/coupons?filter={"couponDurationTypeName":"Forever","isActive":true}
Response (200 OK):
{
"data": [
{
"id": 1,
"stripeCouponId": "Q9Wpvk4o",
"name": "Summer Discount",
"couponTypeCode": "DISC",
"couponTypeName": "Discount Percentage",
"discountPercentage": 20,
"trialDays": null,
"couponDurationTypeCode": "ONCE",
"couponDurationTypeName": "Once",
"durationInMonths": null,
"isActive": true,
"createdAt": "2023-07-15T14:25:00Z",
"updatedAt": null,
"timesRedeemed": 45,
"promotions": [
{
"id": 1,
"name": "Summer Sale",
"description": "20% off summer products",
"stripePromotionCodeId": "promo_1NcL5GJ8oAJtHC9rnvmaJ4Hl",
"code": "SUMMER20",
"couponId": 1,
"maxRedemptions": 100,
"redemptionCount": 45,
"validUntil": "2023-09-30T23:59:59Z",
"isActive": true,
"createdAt": "2023-07-15T14:25:00Z",
"updatedAt": null
}
]
}
// Additional coupon objects...
],
"total": 10
}
Headers:
Content-Range: coupons 0-9/10 Accept-Range: coupons Access-Control-Expose-Headers: Content-Range X-Total-Count: 10
Error Responses:
{
"message": "Administrator access required"
}
Notes:
syncWithStripe parameter ensures coupon data is synchronized with Stripe before filteringtimesRedeemed field comes from Stripe data/api/coupons/:id
Get details of a specific coupon by ID (requires administrator access)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{
"id": 1,
"stripeCouponId": "Q9Wpvk4o",
"name": "Welcome Discount",
"couponTypeCode": "DISC",
"couponTypeName": "Discount Percentage",
"discountPercentage": 20,
"trialDays": null,
"couponDurationTypeCode": "ONCE",
"couponDurationTypeName": "Once",
"durationInMonths": null,
"isActive": true,
"createdAt": "2023-01-15T08:30:00Z",
"updatedAt": null,
"timesRedeemed": 45,
"promotions": [
{
"id": 1,
"name": "Summer Promo",
"description": "Summer promotion code",
"stripePromotionCodeId": "promo_1NcL5GJ8oAJtHC9rnvmaJ4Hl",
"code": "SUMMER20",
"couponId": 1,
"maxRedemptions": 100,
"redemptionCount": 45,
"validUntil": "2023-09-30T23:59:59Z",
"isActive": true,
"createdAt": "2023-07-15T14:25:00Z",
"updatedAt": null
}
]
}
Error Responses:
{
"message": "Administrator access required"
}
{
"message": "Invalid coupon ID"
}
{
"message": "Coupon not found"
}
Notes:
timesRedeemed field reflects the current usage from Stripe/api/coupons/metadata
Get metadata about coupon types and duration types (requires administrator access)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{
"couponTypes": [
{
"code": "DISC",
"name": "Discount Percentage"
},
{
"code": "TRIA",
"name": "Free Trial"
}
],
"durationTypes": [
{
"code": "ONCE",
"name": "Once",
"value": "once"
},
{
"code": "REPE",
"name": "Repeating",
"value": "repeating"
},
{
"code": "FORE",
"name": "Forever",
"value": "forever"
}
]
}
Error Responses:
{
"message": "Administrator access required"
}
Notes:
value field in duration types corresponds to Stripe's duration values/api/coupons
Create a new coupon (requires administrator access and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body (Percentage Discount Coupon):
{
"name": "Back to School",
"couponType": "DISC",
"percentOff": 25,
"duration": "once"
}
Request Body (Free Trial Coupon):
{
"name": "Extended Trial",
"couponType": "TRIA",
"trialDays": 30,
"duration": "once"
}
Request Body (Repeating Discount):
{
"name": "Three Month Discount",
"couponType": "DISC",
"percentOff": 10,
"duration": "repeating",
"durationInMonths": 3
}
Response (201 Created):
{
"message": "Coupon created successfully",
"coupon": {
"id": 3,
"stripeCouponId": "coupon_1234567890",
"name": "Back to School",
"couponTypeCode": "DISC",
"couponTypeName": "Discount Percentage",
"discountPercentage": 25,
"trialDays": null,
"couponDurationTypeCode": "ONCE",
"couponDurationTypeName": "Once",
"durationInMonths": null,
"isActive": true,
"createdAt": "2023-07-15T14:25:00Z",
"updatedAt": null
}
}
Error Responses:
{
"message": "Administrator access required"
}
{
"message": "Missing required fields: name, couponType, and duration are required"
}
{
"message": "Invalid coupon type. Must be either DISC (discount percentage) or TRIA (free trial)"
}
{
"message": "Percentage discount coupons require percentOff value"
}
{
"message": "Free trial coupons require trialDays value"
}
{
"message": "Invalid duration. Must be once, repeating, or forever"
}
{
"message": "durationInMonths is required for repeating coupons"
}
{
"message": "Failed to create coupon",
"error": "Error creating coupon in Stripe"
}
Notes:
/api/coupons/validate
Validate a coupon code (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Request Body:
{
"couponCode": "SUMMER20"
}
Response (200 OK) - Valid Coupon:
{
"valid": true,
"couponDetails": {
"type": "DISC",
"name": "Summer Discount",
"discountPercentage": 20,
"trialDays": null
}
}
Response (200 OK) - Valid Trial Coupon:
{
"valid": true,
"couponDetails": {
"type": "TRIA",
"name": "Extended Trial",
"discountPercentage": null,
"trialDays": 30
}
}
Response (200 OK) - Invalid Coupon:
{
"valid": false,
"message": "Coupon code is invalid or expired"
}
Response (200 OK) - Maximum Uses Reached:
{
"valid": false,
"message": "This coupon code has reached its maximum number of uses"
}
Error Responses:
{
"message": "Authentication required"
}
{
"message": "Coupon code is required"
}
{
"message": "Failed to validate coupon",
"error": "Error message from service"
}
Notes:
/api/coupons/:id
Update a coupon (currently only supports updating the name) (requires administrator access and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{
"name": "Updated Coupon Name"
}
Response (200 OK):
{
"message": "Coupon updated successfully",
"coupon": {
"id": 1,
"stripeCouponId": "Q9Wpvk4o",
"name": "Updated Coupon Name",
"couponTypeCode": "DISC",
"couponTypeName": "Discount Percentage",
"discountPercentage": 20,
"trialDays": null,
"couponDurationTypeCode": "ONCE",
"couponDurationTypeName": "Once",
"durationInMonths": null,
"isActive": true,
"createdAt": "2023-01-15T08:30:00Z",
"updatedAt": "2023-07-15T16:45:00Z"
}
}
Error Responses:
{
"message": "Administrator access required"
}
{
"message": "Invalid coupon ID"
}
{
"message": "No update parameters provided"
}
{
"message": "Coupon not found"
}
Notes:
name field can currently be modifiedisActive status is managed by Stripe and cannot be updated via API/api/coupons/:id
Delete a coupon (requires administrator access and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Response (200 OK):
{
"message": "Coupon deleted successfully"
}
Error Responses:
{
"message": "Administrator access required"
}
{
"message": "Invalid coupon ID"
}
{
"message": "Coupon not found"
}
{
"message": "Cannot delete coupon with linked promotions. Delete the promotions first."
}
Notes: