Cupones


¿Qué es un cupón?

Los cupones te permiten definir descuentos reutilizables que luego puedes aplicar a las suscripciones. Un cupón puede ser por porcentaje (percent_off) o por monto fijo (amount_off), y su duración determina por cuánto tiempo se aplica el descuento a la suscripción:

duration Significado
once Se aplica al ciclo vigente (una vez).
repeating Se aplica durante duration_in_months meses.
forever Se aplica a todos los cobros mientras la suscripción tenga el cupón.

El campo opcional code funciona como un código promocional público que el suscriptor o el comercio usa para redimir el cupón. Reemplaza a los campos discount_* del plan (que se mantienen solo por compatibilidad).

Listar cupones

Descripción: Lista todos los cupones del comercio.

{success} Respuesta satisfactoria code: 200

[
{
"id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f",
"code": "WELCOME10",
"name": "Bienvenida",
"percent_off": 10,
"amount_off": null,
"currency": null,
"duration": "forever",
"duration_in_months": null,
"max_redemptions": null,
"times_redeemed": 3,
"redeem_by": null,
"active": true
}
]

Obtener un cupón

Descripción: Devuelve un cupón por su id.

Crear cupón

Descripción: Crea un cupón. Debes enviar percent_off o amount_off (no ambos).

Nombre del campo Descripción Reglas
code Código público que teclea el cliente. Si lo omites, lo generamos. Único dentro de tu comercio ['nullable', 'string', 'max:64', 'unique:coupons,code']
name Nombre descriptivo, solo para que lo identifiques tú ['nullable', 'string', 'max:255']
percent_off Descuento porcentual, de 0 a 100. Obligatorio si no envías amount_off ['nullable', 'numeric', 'min:0', 'max:100', 'required_without:amount_off']
amount_off Descuento de monto fijo. Obligatorio si no envías percent_off ['nullable', 'numeric', 'min:0', 'required_without:percent_off']
currency Moneda del amount_off, en 3 letras (COP) ['nullable', 'string', 'size:3']
duration Cuánto dura el descuento: once un solo cobro, repeating durante N meses, forever siempre ['required', 'in:once,repeating,forever']
duration_in_months Meses que dura el descuento. Obligatorio cuando duration es repeating ['nullable', 'integer', 'min:1', 'required_if:duration,repeating']
max_redemptions Cuántas veces se puede redimir en total ['nullable', 'integer', 'min:1']
redeem_by Fecha límite para redimirlo ['nullable', 'date']
active Si el cupón queda activo al crearse ['sometimes', 'boolean']
office Sucursal a la que pertenece. Debe ser una de tus sucursales ['required', 'exists:offices,id']

curl -X POST\
"/api/v1/subscriptions/coupon"\
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H "Content-type: application/json" \
-d '{
    "code": "WELCOME10",
    "name": "Bienvenida",
    "percent_off": 10,
    "duration": "forever",
    "office": 1
}'

{success} Respuesta satisfactoria code: 200

{
"saved": true,
"coupon": {
"id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f",
"code": "WELCOME10",
"name": "Bienvenida",
"percent_off": 10,
"duration": "forever",
"active": true,
"times_redeemed": 0
}
}

Actualizar cupón

Descripción: Actualiza un cupón. Los campos son los mismos que en Crear cupón, y office también es obligatorio, aunque no se puede cambiar: el cupón se queda en la sucursal donde se creó.

Activar / desactivar cupón

Descripción: Activa o desactiva un cupón. Un cupón inactivo no puede redimirse.

{success} Respuesta satisfactoria code: 200

{
"updated": true,
"coupon": {
"id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f",
"code": "WELCOME10",
"active": false
}
}

Eliminar cupón

Descripción: Elimina un cupón.

{success} Respuesta satisfactoria code: 200

{
"deleted": true
}

Aplicar a una suscripción

POST /api/v1/subscriptions/subscription/{subscription}/apply-coupon

Aplica un cupón a una suscripción que ya existe. El descuento entra en los cobros recurrentes según la duración del cupón.

Nombre del campo Descripción Reglas
code Código del cupón a redimir. Debe existir en tu comercio, estar activo y no haber alcanzado su límite de redenciones ni su redeem_by ['required', 'string']

{success} Respuesta satisfactoria code: 200

{
"applied": true,
"coupon_id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f",
"discount_ends_at": "2027-01-31T00:00:00.000000Z"
}

{danger} Cupón inválido, vencido, agotado o de otro comercio code: 400

{
"applied": false,
"message": "Cupón inválido o no disponible."
}

{info} discount_ends_at viene en null cuando la duración es forever: el descuento no expira mientras la suscripción conserve el cupón.