Tres notificaciones de reembolso de la App Store llegan después de que Apple decide, y REFUND_REVERSED devuelve la venta
Apple envía cuatro mensajes de reembolso a través de App Store Server Notifications V2, y la mayoría de las apps gestionan solo dos. REFUND te indica que revoques, REFUND_DECLINED significa conservar la venta, y REFUND_REVERSED devuelve la venta y te pide restaurar lo que retiraste. Esto es lo que requiere cada uno.

Puntos clave
- Apple envía cuatro mensajes relacionados con reembolsos a través de App Store Server Notifications V2. CONSUMPTION_REQUEST solicita tus pruebas, y REFUND, REFUND_DECLINED y REFUND_REVERSED informan del resultado después de que Apple ya ha decidido.
- Una notificación REFUND significa que la App Store reembolsó la transacción. Incluye revocationDate y revocationReason, y es tu señal para revocar el derecho vinculado a esa única transacción, no todas las compras de ese producto.
- revocationReason tiene dos valores. 1 significa que el reembolso se concedió por un problema con tu producto, y 0 significa que se concedió por otro motivo. El valor de problema es una señal de calidad que conviene registrar y analizar por tendencias.
- REFUND_DECLINED significa que Apple rechazó el reembolso del cliente. Conservas la venta y no cambias nada, lo cual solo es seguro si no revocaste el acceso antes de que la decisión fuera definitiva.
- REFUND_REVERSED significa que Apple revirtió un reembolso que había concedido antes, normalmente después de que el cliente lo disputa. Los campos de revocación desaparecen de la transacción, y la propia instrucción de Apple es que si revocaste contenido, debes restablecerlo.
- Responde a las cuatro notificaciones con HTTP 200. Si tu servidor estuvo caído y se perdió una, el endpoint Get Refund History te permite buscar transacciones reembolsadas por id de transacción y reconciliar.
- Un reembolso de un periodo de suscripción pasado no siempre significa que el acceso deba terminar. Si un periodo pagado más reciente sigue activo, revocar sobre la transacción antigua deja sin servicio a un cliente que está al día.
Apple decide tu reembolso, y luego sigue hablando. Una vez fijado el resultado, la App Store envía a tu servidor una de tres notificaciones de reembolso de la App Store, y cada una pide una acción distinta. Un REFUND dice que el dinero se fue y que deberías retirar el acceso. Un REFUND_DECLINED dice que el cliente perdió la solicitud y que conservas la venta. Un REFUND_REVERSED dice que Apple deshizo un reembolso que ya había concedido, así que la venta vuelve a ser tuya y debes devolver lo que hubieras retirado. La mayoría de las apps implementan la primera e ignoran en silencio las otras dos. Así es como un cliente que paga acaba bloqueado de algo por lo que pagó.
Estas tres son distintas de CONSUMPTION_REQUEST, el único mensaje de reembolso que te pide responder. Las notificaciones posteriores a la decisión no buscan un debate. Quieren un HTTP 200 y el cambio correcto en el acceso del cliente. Esto es lo que significa cada una, los campos exactos que llevan los datos, y dónde se escapa el dinero cuando las gestionas mal.
Las cuatro notificaciones de reembolso, y cuál espera respuesta
App Store Server Notifications V2 es un único flujo. Lo apuntas a una URL y Apple le envía todos los tipos de notificación, así que ya recibes los cuatro mensajes de reembolso, los gestiones o no. Cuatro de los tipos tienen que ver con reembolsos, y solo uno es una pregunta.
| Notificación | Lo que Apple te dice | Tu acción | Respuesta esperada |
|---|---|---|---|
| CONSUMPTION_REQUEST | Un cliente pidió un reembolso y Apple quiere tus datos | Send Consumption Information en un plazo de 12 horas | Sí, datos reales |
| REFUND | La App Store reembolsó la transacción | Revoca el derecho de esa transacción | No, HTTP 200 |
| REFUND_DECLINED | La App Store rechazó el reembolso | Conserva el acceso, no cambies nada | No, HTTP 200 |
| REFUND_REVERSED | Apple revirtió un reembolso que había concedido | Restablece el contenido que revocaste | No, HTTP 200 |
Qué te dice realmente una notificación REFUND
REFUND se dispara cuando la App Store ha reembolsado con éxito una transacción a un cliente. Se aplica a todos los tipos de compra: un consumible, un no consumible, una suscripción de renovación automática y una suscripción sin renovación. La transacción firmada dentro de la notificación ahora lleva dos campos que no tenía antes del reembolso, y esos dos campos lo explican todo.
revocationDate y revocationReason llevan los datos
revocationDate es la hora UNIX, en milisegundos, en que la App Store reembolsó la transacción o la revocó. revocationReason te indica la categoría del reembolso, y toma exactamente dos valores.
| revocationReason | Significado de Apple | Cómo interpretarlo |
|---|---|---|
| 1 | El reembolso se concedió por un problema con el producto | Una señal de calidad o de entrega. Regístralo, analiza su tendencia y busca un patrón en un producto o una compilación |
| 0 | El reembolso se concedió por otro motivo | Un reembolso normal. Revoca el derecho y sigue adelante |
La presencia de un revocationDate en una transacción es en sí misma la alerta. Si consultas una transacción más tarde y tiene un revocationDate, esa compra ha sido reembolsada, con notificación o sin ella. Lee el motivo junto a él para que una oleada de reembolsos de valor 1 en un solo lanzamiento no se te pase como ruido.
Revoca por transacción, no por producto
La trampa aquí es revocar demasiado. Un REFUND nombra una transacción. No te dice que desactives todas las compras que el cliente haya hecho de ese id de producto. La propia recomendación de Apple es comprobar qué acceso conserva aún el cliente antes de cortar nada, porque los derechos se solapan. El caso clásico es una suscripción: un reembolso recae en la renovación del mes pasado mientras la renovación de este mes está activa y totalmente pagada. Revoca sobre el producto y acabas de cortar a un cliente actual que paga por un reembolso de un periodo que ya terminó.
REFUND_DECLINED significa que ya ganaste, así que no lo deshagas
REFUND_DECLINED llega cuando la App Store rechazó la solicitud de reembolso del cliente. El cliente pidió, Apple dijo no, y conservas la venta. A primera vista no hay nada que hacer, y ese es el punto. El error que expone esta notificación es otro: revocar el acceso antes de tiempo.
Si tu código reacciona al CONSUMPTION_REQUEST retirando el acceso del cliente antes de que Apple resuelva, un REFUND_DECLINED es el momento en que esa decisión estalla. Apple se quedó con tu dinero, y tú bloqueaste a un cliente cuyo reembolso fue denegado. Ese cliente ahora paga por un producto que no puede usar, abre un ticket de soporte y lo recuerda. La solución es una regla, no una función: revoca en REFUND, nunca en la solicitud. REFUND_DECLINED es simplemente Apple confirmando que una revocación temprana habría sido la decisión equivocada.
REFUND_REVERSED es la notificación que te devuelve el dinero
REFUND_REVERSED es la que casi nadie gestiona, y es la que te devuelve dinero. Apple la envía cuando revierte un reembolso que había concedido antes, normalmente después de que el cliente disputa ese reembolso. Los campos de revocación que un REFUND añadió a la transacción se eliminan de nuevo, así que la compra vuelve a figurar como pagada. Apple resume el trabajo del desarrollador en una línea: si tu app revocó contenido o servicios a raíz del reembolso relacionado, debe restablecerlos. Se aplica a cualquier tipo de compra, desde un consumible hasta una suscripción de renovación automática.
El problema de las semanas después
La pregunta real que plantean los desarrolladores, en los propios foros de Apple, es el momento. Un REFUND_REVERSED puede llegar semanas después del REFUND original, mucho después de que un periodo de suscripción haya expirado. ¿Restauras el acceso entonces? Restablece lo que la transacción concede realmente, acotado a lo que esa transacción cubre. Para un consumible o un no consumible, vuelve a activar el desbloqueo. Para un periodo de suscripción que ya ha transcurrido, no estás repartiendo tiempo nuevo, estás corrigiendo el registro para que el historial del cliente sea preciso y cualquier derecho que siga siendo válido vuelva a activarse. Restaura la transacción concreta, y tu lógica de solapamiento decide qué está activo en ese momento.

Dónde está el dinero en hacer esto bien
Cada una de estas notificaciones se corresponde con una cifra real, y el coste de gestionarla mal no es solo el precio de la venta.
REFUND: deja de pagar por atender a un cliente reembolsado
El precio de la venta desaparece en el momento en que llega REFUND. Lo que aún puedes controlar es el coste de seguir prestando el servicio. Cada hora que un derecho reembolsado sigue activo, sigues gastando en lo que el cliente ya no paga: cómputo, llamadas a la API del modelo, almacenamiento y cualquier pago a creadores o socios ligado a su uso. Revocar sin demora en REFUND detiene ese contador. Ignorar la notificación significa que financias un producto para alguien a quien la tienda ya resarció.
REFUND_DECLINED: no conviertas una victoria en un reembolso de buena voluntad
Cuando revocas antes de tiempo y el reembolso se rechaza después, conservaste la venta sobre el papel y la perdiste en la práctica. El cliente que pagó no puede usar el producto, así que heredas una conversación de soporte y, a menudo, un reembolso discrecional para arreglarlo. Eso es pagar dos veces por una venta que nunca estuvo en peligro. Gestionar REFUND_DECLINED correctamente no cuesta nada, que es justo por lo que dejar el acceso intacto hasta REFUND es la regla más barata que puedes adoptar.
REFUND_REVERSED: la peor combinación es que el cliente pierda su dinero y su acceso a la vez
Ignora REFUND_REVERSED y llegas al peor resultado posible. Te han pagado, y el cliente no tiene nada. Ya contactó una vez con su banco para revertir el reembolso, y una persona bloqueada de un producto por el que ahora se le cobra es una persona con probabilidad de contactar con el banco una segunda vez. Esa siguiente disputa puede convertirse en un contracargo de tarjeta, que es definitivo por parte del banco y cuesta más de lo que jamás costó la venta. Restablecer el acceso en cuanto llega REFUND_REVERSED es el seguro más barato de todo el flujo de reembolsos.
Qué implementar
La gestión es pequeña una vez que el modelo es correcto. Indexa los derechos por el id de transacción para que cada notificación apunte a una compra. En CONSUMPTION_REQUEST, envía tus datos en menos de 12 horas. En REFUND, revoca esa transacción. En REFUND_DECLINED, no hagas nada. En REFUND_REVERSED, restablece. Devuelve HTTP 200 rápido en todas ellas y realiza el cambio de acceso a tu propio ritmo.
Para el hueco que dejan las notificaciones, usa el endpoint Get Refund History. Si tu servidor estuvo caído durante una interrupción y se perdió un REFUND, llama a la búsqueda de reembolsos de la App Store Server API para un id de transacción, en /inApps/v2/refund/lookup/{transactionId}, y lee las transacciones firmadas con su revocationDate y revocationReason. Reconcilia una transacción a la vez y pagina por las compras reembolsadas de un cliente, de modo que un webhook perdido no se convierta en un derecho mal configurado de forma permanente.
Esta es la parte que RefundHalt ejecuta por ti. Escucha los cuatro tipos, revoca en REFUND, mantiene el acceso intacto en REFUND_DECLINED, y restablece automáticamente en REFUND_REVERSED, cada uno indexado a la transacción exacta. Un reembolso revertido no se queda en una cola mientras un cliente que paga sigue bloqueado, y uno rechazado nunca dispara una revocación que tendrías que deshacer.
Preguntas frecuentes
- ¿Cuál es la diferencia entre REFUND y REFUND_REVERSED?
- REFUND significa que la App Store reembolsó una transacción y deberías revocar ese derecho, mientras que REFUND_REVERSED significa que Apple deshizo un reembolso que había concedido y deberías restablecer el contenido que revocaste. Las dos forman un par: una compra puede pasar a REFUND y luego, si se revoca la disputa del cliente, a REFUND_REVERSED. Indexa tus cambios de acceso por el id de transacción para que cada notificación actúe sobre la compra correcta.
- ¿Necesito enviar algo de vuelta ante una notificación REFUND?
- No. Respondes a REFUND, REFUND_DECLINED y REFUND_REVERSED con un HTTP 200 y sin cuerpo. Solo CONSUMPTION_REQUEST te pide enviar datos, y lo hace a través del endpoint Send Consumption Information en un plazo de 12 horas. Las otras tres son Apple informando de una decisión, no haciendo una pregunta.
- ¿Qué debo hacer cuando recibo una notificación REFUND_DECLINED?
- No cambia nada, porque el reembolso del cliente fue denegado y conservas la venta. La única forma en que REFUND_DECLINED genera trabajo es si revocaste el acceso antes de tiempo, antes de que Apple resolviera. Revoca en REFUND en lugar de en el CONSUMPTION_REQUEST, y un REFUND_DECLINED se convierte en una confirmación de que el acceso se dejó intacto correctamente.
- ¿Debo restaurar el acceso cuando REFUND_REVERSED llega semanas después del reembolso?
- Sí, restablece el derecho que concede esa transacción concreta. Apple indica que si tu app revocó contenido a raíz del reembolso relacionado, debe restablecerlo. Para un consumible o no consumible, vuelve a activar el desbloqueo. Para un periodo de suscripción que ya ha expirado estás corrigiendo el registro, no concediendo tiempo nuevo, así que tu lógica de solapamiento sigue decidiendo qué está activo en ese momento.
- ¿Cómo capturo una notificación de reembolso que mi servidor se perdió?
- Usa el endpoint Get Refund History de la App Store Server API, que busca las transacciones reembolsadas de un cliente por id de transacción en /inApps/v2/refund/lookup/{transactionId}. Devuelve transacciones firmadas con revocationDate y revocationReason, así que tras una interrupción puedes reconciliar el acceso sin esperar a una notificación que ya se disparó. Gestiona un id de transacción por llamada y pagina por las compras reembolsadas del cliente.
Fuentes y lecturas adicionales
RefundHalt
El piloto automático de reembolsos para App Store y Google Play
Seguir leyendo
Cada solicitud de reembolso de Apple llega ahora con un motivo, y consumptionRequestReason es cómo lo lees
Desde la WWDC24, cada CONSUMPTION_REQUEST de Apple incluye un consumptionRequestReason, el motivo declarado por el propio cliente para pedir el reembolso. Hay cinco valores, desde UNINTENDED_PURCHASE hasta LEGAL, y cada uno debería cambiar lo que devuelves dentro de tu ventana de 12 hours. Aquí tienes cómo leer cada uno.
La revisión de contracargos de Google Play te da 24 horas para defenderte, esto es lo que debes enviar
Cuando un banco revierte un cargo de Google Play, Google envía a tu servidor una PendingRefundReviewNotification e inicia un reloj de 24 horas. Respóndela a través de la ReviewRefund API con una preferencia de reembolso y pruebas de consumo reales, o la disputa se decide sin ti. Aquí está todo el flujo, campo por campo.