Skip to main content

Get All Coupons

Retrieve all coupons sorted by creation date (newest first). Requires admin authentication.

Authentication

Requires Clerk authentication with admin role. Protected by protectRoute and adminOnly middleware.

Response

coupons
array
Array of coupon objects
coupons[]._id
string
MongoDB ObjectId
coupons[].code
string
Coupon code (uppercase, unique)
coupons[].discountType
string
Type of discount: “percentage” or “fixed”
coupons[].discountValue
number
Discount value (1-100 for percentage, any positive number for fixed)
coupons[].expiresAt
string
ISO 8601 expiration date (null if no expiration)
coupons[].isActive
boolean
Whether the coupon is active
coupons[].usedBy
array
Array of user IDs who have used this coupon
coupons[].createdAt
string
ISO 8601 timestamp
coupons[].updatedAt
string
ISO 8601 timestamp
curl -X GET https://api.example.com/api/admin/coupons \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "coupons": [
    {
      "_id": "507f1f77bcf86cd799439011",
      "code": "SUMMER2026",
      "discountType": "percentage",
      "discountValue": 20,
      "expiresAt": "2026-08-31T23:59:59.000Z",
      "isActive": true,
      "usedBy": [
        "507f191e810c19729de860ea"
      ],
      "createdAt": "2026-03-01T10:00:00.000Z",
      "updatedAt": "2026-03-04T12:30:00.000Z"
    },
    {
      "_id": "507f1f77bcf86cd799439012",
      "code": "FIXED5K",
      "discountType": "fixed",
      "discountValue": 5000,
      "expiresAt": null,
      "isActive": true,
      "usedBy": [],
      "createdAt": "2026-02-15T08:00:00.000Z",
      "updatedAt": "2026-02-15T08:00:00.000Z"
    }
  ]
}

Create Coupon

Create a new discount coupon with validation rules.

Authentication

Requires Clerk authentication with admin role.

Request

code
string
required
Coupon code. Will be converted to uppercase and trimmed. Must be unique.
discountType
string
required
Type of discount:
  • percentage - Percentage discount (1-100)
  • fixed - Fixed amount discount
discountValue
number
required
Discount value. Must be:
  • 1-100 for percentage discounts
  • Any positive number >= 1 for fixed discounts
expiresAt
string
ISO 8601 expiration date. Optional - if not provided, coupon never expires.

Response

coupon
object
The created coupon object
curl -X POST https://api.example.com/api/admin/coupons \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "WELCOME10",
    "discountType": "percentage",
    "discountValue": 10,
    "expiresAt": "2026-12-31T23:59:59.000Z"
  }'
{
  "coupon": {
    "_id": "507f1f77bcf86cd799439013",
    "code": "WELCOME10",
    "discountType": "percentage",
    "discountValue": 10,
    "expiresAt": "2026-12-31T23:59:59.000Z",
    "isActive": true,
    "usedBy": [],
    "createdAt": "2026-03-04T15:00:00.000Z",
    "updatedAt": "2026-03-04T15:00:00.000Z"
  }
}

Error Responses

{
  "error": "code, discountType y discountValue son requeridos."
}

Update Coupon

Update an existing coupon. All fields are optional.

Authentication

Requires Clerk authentication with admin role.

Path Parameters

id
string
required
MongoDB ObjectId of the coupon to update

Request

code
string
Updated coupon code (will be uppercase and trimmed)
discountType
string
Updated discount type: “percentage” or “fixed”
discountValue
number
Updated discount value (validated based on discount type)
expiresAt
string
Updated expiration date (ISO 8601)
isActive
boolean
Updated active status

Response

coupon
object
The updated coupon object
curl -X PATCH https://api.example.com/api/admin/coupons/507f1f77bcf86cd799439013 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "isActive": false
  }'
{
  "coupon": {
    "_id": "507f1f77bcf86cd799439013",
    "code": "WELCOME10",
    "discountType": "percentage",
    "discountValue": 10,
    "expiresAt": "2026-12-31T23:59:59.000Z",
    "isActive": false,
    "usedBy": [],
    "createdAt": "2026-03-04T15:00:00.000Z",
    "updatedAt": "2026-03-04T16:00:00.000Z"
  }
}

Error Responses

{
  "error": "El porcentaje debe estar entre 1 y 100."
}

Delete Coupon

Permanently delete a coupon.

Authentication

Requires Clerk authentication with admin role.

Path Parameters

id
string
required
MongoDB ObjectId of the coupon to delete

Response

message
string
Success message
curl -X DELETE https://api.example.com/api/admin/coupons/507f1f77bcf86cd799439013 \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "message": "Cupón eliminado correctamente."
}

Coupon Validation

For customer-facing coupon validation, see the public endpoint:
  • POST /api/coupons/validate - Validate and calculate discount (requires user authentication)
Validation checks:
  • Coupon exists and is active
  • Not expired (expiresAt is null or in the future)
  • User hasn’t already used the coupon (tracked in usedBy array)
  • If firstOrderOnly is set, user must have no completed orders
The discount amount is calculated based on:
  • Percentage: min(round(subtotal * discountValue / 100), subtotal)
  • Fixed: min(discountValue, subtotal)

Build docs developers (and LLMs) love