Evento gamificado que una compañía monta para sus clientes. Hoy el único tipo es coupon_gen:
un sorteo en el que el cliente "agita" (endpoint events/shake) y puede ganar un cupón según
las probabilidades configuradas.
| Estado | Cómo se llega | Se puede |
|---|---|---|
pending |
Al crear el evento. | Editar (update), pasar a ready. |
ready |
set-ready: fija starts_at/ends_at y valida la configuración. |
Volver a editar sólo si sigue pending. |
running |
Automático al llegar starts_at. |
Participar (shake), pasar a finished. |
finished |
set-finished, o automático al llegar ends_at. |
— |
Sólo puede haber un evento running por compañía a la vez (EF408).
configObjeto JSON; el trait de configuración lo expone además en accesores config_*. Claves
visibles y editables:
| Clave | Descripción |
|---|---|
winner_message |
Mensaje al ganador. Admite los marcadores $1 y $2 (valor y detalle del cupón). |
already_won_message |
Mensaje cuando el cliente ya había ganado antes. |
loser_message |
Mensaje cuando no gana. |
coupon_seeds |
Semillas de los cupones a repartir (CouponSeed: max_count, win_rate, valor, mínimo de compra, ventana de disponibilidad, ...). |
random_length |
Tamaño del espacio aleatorio; junto con win_rate de cada semilla fija la probabilidad de ganar. |
expires_at |
Caducidad de los cupones generados. |
| Atributo | Tipo | Descripción |
|---|---|---|
id |
int |
|
name |
string |
Nombre del evento. |
type |
string |
Tipo de evento; hoy sólo coupon_gen. |
status |
string |
Estado del evento: pending, ready, running o finished. |
starts_at |
datetime\|null |
Inicio de la vigencia del evento. |
ends_at |
datetime\|null |
Fin de la vigencia del evento. |
config |
array |
Objeto JSON de configuración (ver tabla de claves arriba). |
created_at |
datetime\|null |
Fecha de creación. |
updated_at |
datetime\|null |
Fecha de última modificación. |
deleted_at |
datetime\|null |
Fecha de borrado lógico. |
company_id |
int |
Compañía dueña del evento (oculto en la respuesta). |
allLogs |
ApiLog> |
Registros de auditoría de la API, incluidos los internos. |
company |
Company |
Compañía dueña del evento. |
config_already_won_message |
string |
Atajo de config.already_won_message. |
config_coupon_seeds |
array\|null |
Atajo de config.coupon_seeds como lista de CouponSeed. |
config_expires_at |
datetime\|null |
Atajo de config.expires_at. |
config_loser_message |
string |
Atajo de config.loser_message. |
config_random_length |
int\|null |
Atajo de config.random_length. |
config_winner_message |
string |
Atajo de config.winner_message. |
eventData |
CompanyEventData> |
Datos internos del evento (participaciones, tickets y ganadores). |
logs |
ApiLog> |
Registros de auditoría de la API visibles. |
{
"id": 1,
"name": "Navidad",
"type": "coupon_gen",
"status": "finished",
"starts_at": "2020-12-17 20:10:53",
"ends_at": null,
"config": {
"coupon_seeds": [
{
"win_rate": 50,
"max_count": 12,
"coupon_value_e2": 5,
"coupon_min_purchase_e2": 0
},
{
"win_rate": 10,
"max_count": 5,
"coupon_value_e2": 10,
"coupon_min_purchase_e2": 0
},
{
"win_rate": 5,
"max_count": 2,
"coupon_value_e2": 20,
"coupon_min_purchase_e2": 0
},
{
"win_rate": 1,
"max_count": 1,
"coupon_value_e2": 100,
"coupon_min_purchase_e2": 0
}
],
"random_length": 100,
"winner_message": "Felicidades! Has ganado <b></b>. Usa el código <b></b>",
"expires_at": null,
"loser_message": "Keep trying",
"already_won_message": "Already won. "
},
"created_at": "2020-12-17 20:09:59",
"updated_at": "2020-12-19 15:30:57",
"deleted_at": null
}
Crear un evento
Crea un CompanyEvent en estado pending (name, type, ventana opcional
starts_at/ends_at y config).
| Método | URI | Cabeceras |
|---|---|---|
| POST | /companies/{companyId}/company-events |
Authorization |
{
"name": "required|string|max:64",
"type": "required|string|in:coupon_gen",
"starts_at": "date|after:now",
"ends_at": "date|after:starts_at|after:now",
"timezone": {
"string": true,
"regex": "/^[\+\-]([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
},
"config": {
"coupon_seeds": [
{
"max_count": "required|integer|min:1",
"coupon_value_e2": "integer|min:0",
"coupon_value_prc": "numeric|between:0.0000,1.0000",
"coupon_min_purchase_e2": "integer|min:0",
"win_rate": "required|integer|min:1",
"coupon_applies_to": "string|in:total,subtotal,base_price,service,delivery",
"winner_message": "string|max:80",
"already_won_message": "string|max:80",
"available_since": "date",
"available_until": "date"
}
],
"expires_at": "date|after:now",
"random_length": "integer|min:1",
"winner_message": "string|max:80",
"already_won_message": "string|max:80",
"loser_message": "string|max:80"
}
}
{info} Soporta: Paginación Filters Carga dinámica
Listar eventos
Devuelve los CompanyEvent de la compañía, paginados.
| Método | URI | Cabeceras |
|---|---|---|
| GET | /companies/{companyId}/company-events |
Authorization |
{info} Soporta: Carga dinámica
Ver un evento
Devuelve el CompanyEvent indicado.
| Método | URI | Cabeceras |
|---|---|---|
| GET | /companies/{companyId}/company-events/{companyEventId} |
Authorization |
Actualizar un evento
Modifica un CompanyEvent que siga en estado pending.
| Método | URI | Cabeceras |
|---|---|---|
| PATCH | /companies/{companyId}/company-events/{companyEventId} |
Authorization |
{
"name": "string|max:64",
"type": "string|in:coupon_gen",
"starts_at": "date|after:now",
"ends_at": "date|after:starts_at|after:now",
"timezone": {
"string": true,
"regex": "/^[\+\-]([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
},
"config": {
"coupon_seeds": [
{
"max_count": "required|integer|min:1",
"coupon_value_e2": "integer|min:0",
"coupon_value_prc": "numeric|between:0.0000,1.0000",
"coupon_min_purchase_e2": "integer|min:0",
"win_rate": "required|integer|min:1",
"coupon_applies_to": "string|in:total,subtotal,base_price,service,delivery",
"winner_message": "string|max:80",
"already_won_message": "string|max:80",
"available_since": "date",
"available_until": "date"
}
],
"expires_at": "date|after:now",
"random_length": "integer|min:1",
"winner_message": "string|max:80",
"already_won_message": "string|max:80",
"loser_message": "string|max:80"
}
}
| Código | HTTP | Cuándo ocurre |
|---|---|---|
EF401 |
400 | El evento no está en estado pending. |
Pasa el CompanyEvent de pending a ready, fijando starts_at/ends_at (con
timezone) y validando la configuración (semillas de cupón, probabilidades, fechas).
| Método | URI | Cabeceras |
|---|---|---|
| POST | /companies/{companyId}/company-events/{companyEventId}/set-ready |
Authorization |
{
"starts_at": "date|after:now",
"ends_at": "date|after:starts_at|after:now",
"timezone": {
"string": true,
"regex": "/^[\+\-]([0-1][0-9]|2[0-3]):[0-5][0-9]$/"
}
}
| Código | HTTP | Cuándo ocurre |
|---|---|---|
EF401 |
400 | El evento no está en estado pending. |
Pasa el CompanyEvent de running a finished; deja de aceptar participaciones.
| Método | URI | Cabeceras |
|---|---|---|
| POST | /companies/{companyId}/company-events/{companyEventId}/set-finished |
Authorization |
| Código | HTTP | Cuándo ocurre |
|---|---|---|
EF405 |
400 | El evento no está en estado running. |
"Agita" el evento running de la compañía: registra la participación del usuario y
devuelve el resultado (cupón ganado o mensaje de derrota). Si no hay ningún evento
running responde {event: "none", result: "not_found"}.
| Método | URI | Cabeceras |
|---|---|---|
| GET | /companies/{companyId}/events/shake |
Authorization |
allLogs HasMany ApiLogcompany BelongsTo CompanyeventData HasMany CompanyEventDatalogs HasMany ApiLog