/api/coupons
List all coupons with optional filtering (requires administrator access)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort
- JSON array with interface name and direction
["interfaceName","ASC|DESC"]
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 interface name/value pairs for filtering
{"interfaceName1":"value1","interfaceName2":value2}
filter={"name":"Summer"}
- Filter coupons with name containing
"Summer"
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={"name":"Summer"}&syncWithStripe=true
GET /api/coupons?page=2&perPage=20&filter={"q":"discount","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 toggling active status) (requires administrator access and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{ "isActive": false }
Response (200 OK):
{ "message": "Coupon updated successfully", "coupon": { "id": 1, "stripeCouponId": "Q9Wpvk4o", "name": "Welcome Discount", "couponTypeCode": "DISC", "couponTypeName": "Discount Percentage", "discountPercentage": 20, "trialDays": null, "couponDurationTypeCode": "ONCE", "couponDurationTypeName": "Once", "durationInMonths": null, "isActive": false, "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:
isActive
field can currently be modifiedisActive
to false effectively disables the coupon/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: