Crear codigo
Crear un codigo promocional asociado a un usuario final.
/api/v1/codesCrea un codigo promocional unico asociado a un usuario final, usando la plantilla configurada en la campana.
Este endpoint emite un unico codigo a la vez para un externalUserId especifico. Los parametros del codigo (descuento, expiracion, prefijo, largo) se toman de la configuracion defaultCodeConfig de la campana, asi el caller externo no controla los descuentos.
Reutilizacion automatica: si el mismo usuario ya tiene un codigo activo (no canjeado, no expirado, no desactivado) para esa campana, el endpoint devuelve ese codigo existente en lugar de generar uno nuevo. Evita acumular codigos sin usar y no cuenta contra generationLimits. La respuesta trae idempotent: true cuando esto ocurre. Una vez que el usuario canjea el codigo (o expira), la proxima llamada genera uno nuevo.
Request body
| Parametro | Tipo | Descripcion |
|---|
Headers opcionales
| Parametro | Tipo | Descripcion |
|---|
Ejemplo
curl -X POST https://southgames.ai/api/v1/codes \
-H "Authorization: Bearer sg_live_xxx" \
-H "X-Org-Id: mi-empresa" \
-H "Idempotency-Key: 11111111-1111-1111-1111-111111111111" \
-H "Content-Type: application/json" \
-d '{"campaignId": "camp_123", "externalUserId": "user_123"}'
Respuesta
{
"code": "SGAB12CD34",
"discountType": "percentage",
"discountValue": 20,
"maxDiscountAmount": 25000,
"maxUses": 1,
"expiresAt": "2026-06-01T00:00:00.000Z",
"remainingGenerations": 2,
"limitPeriod": "month",
"idempotent": false
}
Status codes:
201 Created— codigo nuevo generado.200 OK— respuesta idempotente: ya existia un codigo con el mismoIdempotency-Keypara ese usuario en las ultimas 24h.
Campos:
code— codigo generado. Puede usarse inmediatamente en/api/v1/codes/redeem.maxDiscountAmount— tope absoluto del descuento. Solo relevante cuandodiscountType === "percentage".nullcuando no hay tope. La integracion debe aplicarmin(price * discountValue/100, maxDiscountAmount)al cobrar.remainingGenerations— cuantos codigos mas puede recibir este usuario en el periodo actual. Se omite si la campana no tienegenerationLimits.limitPeriod— periodo del limite (day|week|month|total). Se omite si no hay limite.idempotent—truesi la respuesta es replay de una generacion previa.
Errores
| Codigo | HTTP | Descripcion |
|---|---|---|
VALIDATION_ERROR | 400 | Falta campaignId o externalUserId |
CAMPAIGN_NOT_FOUND | 404 | Campana no existe en el org |
CAMPAIGN_INACTIVE | 400 | Campana no esta activa (status != "active") |
CAMPAIGN_NOT_CODE_REWARD | 400 | La campana entrega puntos, no codigos (rewardType !== "promo_code") |
CAMPAIGN_MISSING_CODE_CONFIG | 400 | La campana no tiene defaultCodeConfig configurado en el dashboard |
GENERATION_LIMIT_REACHED | 429 | El usuario supero generationLimits.maxPerUser del periodo |
CODE_COLLISION_RETRY_EXCEEDED | 500 | No se pudo generar un codigo unico (retry). Intenta de nuevo. |
Idempotencia
Para prevenir duplicados en reintentos de red, envia el header Idempotency-Key con un UUID v4 unico por operacion logica:
- La primera request con un key nuevo crea el codigo y retorna 201.
- Reintentos con el mismo key y el mismo
externalUserIddentro de 24h devuelven el mismo codigo con 200 yidempotent: true. - Un key diferente siempre genera un codigo nuevo (y cuenta contra
generationLimits).
Limites por usuario
Los limites se configuran en la campana (campo generationLimits en el dashboard). Si estan activos:
- Se cuenta cuantos codigos ha recibido el
externalUserIdpara esa campana en el periodo (dia/semana/mes/total). - Si supera
maxPerUser, el endpoint retorna 429. - El contador solo cuenta generaciones exitosas (no idempotentes replays).
Webhook
Se dispara el evento code.created (solo cuando hay creacion real, no en replays idempotentes) con el payload:
{
"event": "code.created",
"timestamp": "2026-04-23T18:30:00.000Z",
"data": {
"code": "SGAB12CD34",
"campaignId": "camp_123",
"externalUserId": "user_123",
"discountType": "percentage",
"discountValue": 20,
"maxDiscountAmount": 25000,
"maxUses": 1,
"expiresAt": "2026-06-01T00:00:00.000Z"
}
}
Ver Webhooks para configurar endpoints y verificar firmas.