Tu servidor sabe cosas que Bot Protection no sabe: que una persona confirmó su email, pagó sin disputa, o que una tarjeta tuvo un chargeback. Enviarlo fija cuánto confía Bot Protection en ese navegador en sus próximas decisiones. No cambia ninguna regla ni ningún peso: lo que hizo un navegador nunca cambia las decisiones de otro.
Identifica al visitante por el request_id que respondió /v1/decide: guárdalo con el pedido y envíalo cuando sepas el resultado, semanas o meses después. Una decisión tomada con el token del tag identifica la sesión de ese navegador; una tomada sin token no identifica ninguna, y su feedback se rechaza. El token del visitante (la cookie _kz) también sirve: envía token en lugar de request_id.
curl -s -X POST https://korzen.dev/v1/feedback \ -H "Authorization: Bearer $KORZEN_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"feedback":[{"request_id":"<the decision request_id>","outcome":"good_customer"}]}'
| Resultado | Cuándo |
|---|---|
verified_human | la persona demostró quién es: un enlace por email, un código por teléfono, una passkey |
good_customer | un pedido pagado, una suscripción renovada, sin disputa |
chargeback | un pago disputado o revertido |
fraud | descubriste que la cuenta era falsa o abusiva |
// Node: the SDK sends a UUID v7 as the Idempotency-Key, and again with each retry. await korzen.feedback([{ request_id: order.korzenRequestId, outcome: "chargeback" }]);
// Go: the same, with your own key (an order's id makes a later resend safe too). _, err := bot.Feedback(ctx, []korzen.Feedback{{RequestID: order.KorzenRequestID, Outcome: "chargeback"}}, korzen.Batch{IdempotencyKey: "chargeback-" + order.ID})
Cada pieza nombra su sesión con exactamente uno de request_id y token; un lote lleva de 1 a 1.000. La respuesta dice qué se registró: {"accepted": 1, "duplicates": 0, "rejected": 0, "errors": []}, donde cada pieza rechazada es {"index", "code", "detail"}, como forged para un request_id que no es tuyo, o no_session para uno de una decisión tomada sin token. Un cuerpo no válido es un problem 400, como los errores de decide.
Envía un Idempotency-Key con cada llamada, de 1 a 255 caracteres ASCII visibles, como hacen los SDKs con un UUID v7. La misma clave con el mismo cuerpo dentro de una hora recibe otra vez la primera respuesta, con Idempotent-Replayed: true, y nada se registra dos veces; con otro cuerpo es 422 idempotency_key_reused, y mientras la primera llamada sigue en curso, 409 idempotency_key_in_use. Así, una llamada sin respuesta, con 409, 429 o 5xx se puede reenviar sin riesgo con su clave, y los SDKs lo hacen, unas pocas veces en 5 segundos.
El feedback es opcional y gratis, y nunca cuenta como decisión. Los buenos resultados pueden elevar una decisión posterior del mismo navegador a human o human_high, también meses después, siempre que vuelva; los malos lo deshacen.