Saltar al contenido principal

Fidelización

Disponible desde 1.25.0. Las respuestas llevan Cache-Control: private, no-store. Si el programa está desactivado o la tienda está en modo coexistencia, las rutas responden 409 loyalty_unavailable. Consulta la guía de fidelización.

Rutas del cliente (sesión iniciada)​

El cliente debe tener una cuenta de puntos con el correo verificado. Si no lo tiene, las rutas responden 400 loyalty_invalid.

MétodoRutaParámetrosRespuesta
GET/loyalty/mepage (movimientos, 25 por página){ account, ledger{items[], page, total}, rewards[] }
POST/loyalty/me/redeemreward_id (por defecto points), points, idempotency (obligatorio){ coupon_code, points, balance }
POST/loyalty/me/returncoupon_codeMovimiento de devolución de puntos.
PUT/loyalty/me/birthdaybirthday (AAAA-MM-DD){ saved: true }
POST/loyalty/me/verify—{ sent: true }: envía un enlace de verificación por correo.
  • redeem crea un cupón de un solo uso (prefijo nw-) restringido al correo del cliente. No lo aplica al carrito: la tienda lo hace en el checkout.
  • La fecha de cumpleaños no puede ser futura y solo se puede cambiar una vez al año.

Ruta pública​

GET /loyalty/preview devuelve lo que la tienda muestra en el carrito: { enabled, program_name, preview, balance, verified, logged_in, min_points, rewards[], account_url, login_url, cart_message, ... }. preview son los puntos que ganaría el carrito actual. Si el programa está apagado, responde { enabled: false }.

Rutas de gestión​

MétodoRutaUso
GET/loyalty/accountsBuscar cuentas: search (correo, teléfono o nombre), level, status (active o blocked), linked (1 o 0), page, per_page (25 por defecto, máximo 100). Responde { items, total, page, per_page } dentro de data.
GET/loyalty/accounts/{id}Detalle, movimientos y recompensas.
POST/loyalty/accounts/{id}/adjustAjuste manual: points (positivo o negativo), note (obligatoria, hasta 255 caracteres) e idempotency.
POST/loyalty/accounts/{id}/redeemCanje en caja: order_id (pedido abierto del mismo correo), reward_id, points e idempotency. Aplica el cupón al pedido y recalcula el total.
POST/loyalty/accounts/{id}/returnDevolver los puntos de un cupón: coupon_code.
POST/loyalty/accounts/{id}/verifySin code: envía un código de 6 dígitos al cliente. Con code: verifica la cuenta.
PUT/loyalty/accounts/{id}/statusstatus (active o blocked) y note (obligatoria).
POST/loyalty/accounts/mergeFusionar cuentas: source_id, target_id, note.
GET/loyalty/statsfrom y to (AAAA-MM-DD, hasta 366 días). Por defecto, desde el inicio del mes.
GET, PUT/settings/loyaltyAjustes del programa.
POST/loyalty/importImportar CSV (ver abajo).
GET/loyalty/exportExportar CSV por páginas de 100: { csv, done, page }.
POST/loyalty/preview-rulesSimula cuántos puntos daría un evento: settings, context, event.
POST/loyalty/apply-expiryPrograma el vencimiento de puntos en segundo plano.

Canje en caja​

curl -X POST https://tienda.example.test/wp-json/notiwoo/v1/loyalty/accounts/58/redeem \
-H "Authorization: Bearer <token>" \
-H "X-Notiwoo-Actor: notifier:15" \
-H "Content-Type: application/json" \
-d '{"order_id": 1240, "reward_id": "points", "points": 500, "idempotency": "caja-1240-0001"}'
{ "success": true, "data": { "coupon_code": "nw-k3j9x0q2m5v8b1n4c7z6l0p9w2e5", "points": 500, "balance": 1320, "order_total": "41000.00" } }

La cabecera X-Notiwoo-Actor es opcional y registra quién hizo el canje en el historial.

Verificación por código​

El código de 6 dígitos vale 15 minutos y admite 5 intentos. Solo se puede enviar uno por minuto por cuenta; si pides otro antes, la respuesta incluye retry_after: 60.

Importar CSV​

POST /loyalty/import con csv (texto de hasta 2 MB y 5000 filas) y dry_run.

ColumnaAlias
emailuser_email, customer_email
pointspoints_balance, balance
namefirst_name + last_name
phone, referral_code—

Por defecto dry_run es true: valida y responde { valid, count, points, errors[], preview[] } sin importar nada. Envía dry_run: false para importar.

Objetos​

Cuenta: id, email, phone (formato internacional), name, user_id, email_verified_at, referral_code, level_id, birthday, balance, lifetime_earned, status, whatsapp_consent, created_at, updated_at.

Movimiento: id, type (earn, redeem, adjust, expire, restore o revert), points, remaining, expires_at, source, campaign_id, order_id, reward_id, coupon_code, note, actor, created_at.

Ajustes del programa​

GET /settings/loyalty responde { settings, log[], whatsapp_ready, currency }. log es el historial de cambios de los ajustes.

PUT /settings/loyalty recibe el objeto completo de ajustes. Si cambias el valor del punto o el modo de identificación, debes confirmarlo con confirm_point_value: true o confirm_identity_risk: true.

Grupos principales de settings:

GrupoContenido
enabled, program_nameActivación y nombre.
identityCómo se identifica al cliente: email, account o phone.
earnCuándo se ganan los puntos (completed o finalized), importe por punto, redondeo e inclusión del domicilio.
redeemValor del punto, mínimo de puntos, porcentaje máximo del pedido y vigencia del cupón.
expiryVencimiento y aviso previo.
level_settings, levels[]Niveles.
campaigns[]Campañas: purchase, first_order, signup, birthday, review, referral, multiplier y level_up.
rewards[]Recompensas: points_discount, fixed_discount, percent_discount, free_delivery y free_product.
referralReferidos.
notifyCanal de cada aviso: none, email, whatsapp o both.

Si la validación falla, responde 400 loyalty_settings con las rutas de los campos a revisar.

Errores​

CódigoHTTPCausa
loyalty_invalid400Puntos insuficientes o por debajo del mínimo, porcentaje máximo superado, recompensa no disponible, cuenta bloqueada o inexistente, código incorrecto, clave de idempotencia no válida, CSV con errores…
loyalty_settings400Ajustes no válidos.
loyalty_unavailable409Programa desactivado, operación simultánea sobre la misma cuenta o WhatsApp sin configurar.