Si alguna vez has trabajado con el flujo de reembolsos de Apple, probablemente hayas visto mencionada en la documentación la ventana de respuesta de 12 horas. Lo que no siempre queda claro es cómo responder realmente.
El CONSUMPTION_REQUEST es una notificación; la respuesta es una llamada a una API distinta, con su propia clave y un cuerpo que ha cambiado de forma dos veces desde 2021. Ya cubrimos qué contiene la notificación en sí hace un tiempo. Esta es la parte que viene después, cuando realmente tienes que responderla.
Puntos clave
Es una sola solicitud PUT a la App Store Server API. Ese es todo el mecanismo.
Cada solicitud se firma con un JWT generado a partir de tu clave de compras dentro de la app (in-app purchase key); los tokens de más de 60 minutos son rechazados.
El cuerpo de la v2 tiene cinco campos, tres de ellos obligatorios.
Apple responde 202 y nada más. La decisión sobre el reembolso llega después, como una notificación aparte.
Doce horas desde el momento en que llega la notificación, y puedes reenviar dentro de esa ventana.
¿Qué es una Apple Consumption Request?
Una Apple consumption request es, detrás de la jerga técnica, una pregunta. Un cliente le pidió a Apple que le devolviera su dinero, y antes de responderle, Apple se dirige a tu servidor y pregunta: ¿esta persona recibió lo que pagó y llegó a usarlo?
Apple combina lo que le digas con información que ya tiene, como la frecuencia con la que este cliente pide reembolsos, y toma la decisión por su cuenta.
La gente se equivoca constantemente en ese último punto. Tú no apruebas ni rechazas nada; solo entregas datos.
El CONSUMPTION_REQUEST que envía Apple llega a la URL del servidor que configuraste en App Store Connect, como una notificación de servidor versión 2.
En 2021 solo se activaba para consumibles. Las suscripciones se agregaron en 2024, y en diciembre de 2025 Apple publicó la versión 2 del endpoint, cuya documentación indica que cubre todos los tipos de producto, incluidas las compras no consumibles y las suscripciones que no se renuevan automáticamente. La página de referencia de notificaciones todavía menciona solo los dos originales; yo me fiaría de la página más reciente y lo construiría para los cuatro.
Y ya que hablo de nombres: la gente busca "Apple refund API" y en realidad no existe algo así, no como una cosa separada. Esta llamada forma parte de la App Store Server API.
Qué necesitas antes de poder enviar la información
Tres de estos cuatro elementos no se pueden improvisar, así que lee esto antes de tu primera solicitud, no después.
El primero es una clave, específicamente una in-app purchase key, creada en App Store Connect dentro de Users and Access. Apple te entrega un archivo .p8 exactamente una vez; también necesitarás su key ID y tu issuer ID.
Segundo, alguna forma de pasar de un transaction ID (lo que te da Apple) a una persona en tu base de datos (lo que necesitas). La forma limpia de hacerlo es con appAccountToken, configurado en el momento de la compra, que luego vuelve a aparecer en cada notificación relacionada con esa transacción.
Si ese término es nuevo para ti, lee primero por qué appAccountToken importa para la defensa ante reembolsos, porque sin esa relación, el resto de este artículo es puramente teórico.
Tercero, y este es el que no se puede arreglar a las 2 a. m.: el consentimiento.
La documentación de Apple dice sin rodeos que, si el cliente no ha aceptado que compartas estos datos, simplemente no respondes. También dice, en un lenguaje más legal, que lo que cuenta como consentimiento válido depende de dónde operes y que ellos no pueden asesorarte al respecto.
Lo habitual es incluir una cláusula de aceptación (opt-in) en tus términos, y esta debe existir antes de que aparezca la solicitud.
El cuarto es el transaction ID en sí, que solo obtienes cuando llega la notificación y verificas la firma de Apple.
Cómo enviar información de consumo paso a paso
La mayoría de las personas que buscan "send consumption information apple" terminan en la página de referencia de Apple, que enumera los campos y luego se detiene de manera bastante abrupta. Aquí está la secuencia en la práctica.
Empieza por verificar que la notificación sea real. El signedPayload es un JWS; la App Store Server Library de Apple lo verifica y devuelve la transacción decodificada, incluidos el transactionId y el appAccountToken.
Busca la compra en tu sistema. Lo que necesitas saber: ¿lo entregamos?, ¿aproximadamente qué fracción se ha usado?, ¿vio una muestra o una prueba antes?, y ¿qué preferiríamos que hiciera Apple?
Ahora el token. Header: alg es ES256, kid es tu key ID, typ es JWT. Payload: iss es tu issuer ID, iat es el momento actual, exp es como máximo 60 minutos después, aud es el string literal appstoreconnect-v1, y bid es tu bundle ID. La guía de Apple para generar JSON Web Tokens tiene el formato exacto, aunque la librería ya construye esto por ti.
Envíalo con PUT. La URL de producción es https://api.storekit.apple.com/inApps/v2/transactions/consumption/{transactionId}, con el JWT como token Bearer en el encabezado Authorization, y un cuerpo similar a este:
{
"customerConsented": true,
"deliveryStatus": "DELIVERED",
"consumptionPercentage": 94000,
"sampleContentProvided": false,
"refundPreference": "DECLINE"
}
Apple responde 202 Accepted, y eso es todo lo que obtienes. Registra la hora, el cuerpo y el transaction ID, porque dentro de un mes alguien preguntará qué le dijimos a Apple sobre este caso.
Después esperas. La decisión llega como una notificación REFUND o REFUND_DECLINED. Si es REFUND, retira el contenido o el entitlement ese mismo día.
Así que si te has estado preguntando cómo enviar información de consumo que Apple realmente use, eso es todo: una solicitud, cinco campos, dentro de la ventana de tiempo.
Apple también te permite enviar un payload actualizado dentro de esas 12 horas, así que si la primera llamada salió con información incompleta, envía una segunda.
Hay algunas cosas que los nombres de los campos no te dicen. consumptionPercentage está expresado en miliunidades, algo que suele confundir a la gente: 94000 significa 94 por ciento, 100000 significa el total, y debe ser 0 si deliveryStatus es cualquier valor distinto de DELIVERED.
Las opciones de "no entregado" son UNDELIVERED_QUALITY_ISSUE, UNDELIVERED_WRONG_ITEM, UNDELIVERED_SERVER_OUTAGE y UNDELIVERED_OTHER.
refundPreference es opcional y admite los valores GRANT_FULL, GRANT_PRORATED o DECLINE; para GRANT_PRORATED en una suscripción autorrenovable, omite el porcentaje y Apple lo calcula a partir del tiempo restante.
La Send Consumption Information tiene la lista completa de errores.
Qué significan los códigos de respuesta
Solo hay una respuesta buena, 202. Todo lo demás es Apple diciéndote qué hiciste mal, normalmente señalándolo con su nombre específico.
Los códigos 400 son los más útiles, ya que el cuerpo de la respuesta nombra el error.
ConsumptionPercentageOutOfRangeError casi siempre significa que alguien envió 94 en lugar de 94000.
UndeliveredConsumptionPercentageNonZeroError significa que dijiste que el artículo nunca llegó y, al mismo tiempo, afirmaste que se usó parcialmente.
InvalidCustomerConsentedError se explica por sí solo.
Un 401 tiene que ver con el token: clave incorrecta, una expiración de más de una hora, un bundle ID que no coincide, o un reloj del servidor desfasado lo suficiente como para que iat parezca estar en el futuro.
Un 404 significa que no se encontró el transaction ID, y mi primera pregunta siempre es si una transacción de sandbox se envió a la URL de producción (o al revés).
429 es el límite de velocidad (rate limit) (50 solicitudes por segundo por app en producción, una décima parte de eso en el sandbox); lee el encabezado Retry-After antes de reintentar.
500 es un problema del lado de Apple; vuelve a intentarlo más tarde.
Cómo probarlo en el sandbox
Probar esto es más fácil de lo que parece, con una salvedad.
Coloca una URL de servidor de sandbox en App Store Connect, inicia sesión con una Apple Account de sandbox, compra algo, luego abre la hoja de reembolso de tu app (beginRefundRequest) y envía una solicitud.
La guía de Apple para probar solicitudes de reembolso explica cómo se comporta el entorno de prueba: elige cualquier motivo y el reembolso se aprueba automáticamente; elige Other y escribe DECLINE y se rechaza; escribe GRANT_PRORATED para uno prorrateado.
La salvedad está en esas reglas: el sandbox decide según lo que escribiste en la hoja, no según lo que envió tu servidor, así que no puede decirte si tus datos realmente convencen a Apple de algo.
Lo que sí puede probar es la infraestructura: que la notificación llega, que tu PUT a api.storekit-sandbox.apple.com responde 202, y que REFUND o REFUND_DECLINED se gestionan cuando aparecen.
Además, el sandbox no envía correos de reembolso, así que no esperes uno.
Automatización de reembolsos de Apple: cuándo dejar de hacerlo a mano
Hecho a mano, este trabajo consiste en que alguien esté pendiente de una alerta a toda hora, ejecute una consulta y envíe cinco campos antes de que se agote un reloj de 12 horas.
Funciona bien con un puñado de solicitudes de reembolso de Apple al mes. Funciona considerablemente peor el primer fin de semana largo en que nadie está revisando.
Para automatizar las solicitudes de reembolso de Apple, tomas todo lo anterior y quitas a la persona de en medio: la notificación llega, tus reglas convierten los datos de entrega y uso en un payload, la llamada sale en cuestión de minutos, la decisión queda registrada contra el caso, y un REFUND activa una revocación.
Construir eso no es un proyecto enorme; mantenerse al día con los cambios de Apple después (el cambio de v1 a v2, por ejemplo) es la parte que en silencio sigue costando.
Si prefieres no hacerlo tú mismo, repasamos los servicios creados para esto en nuestra comparación de herramientas de gestión de reembolsos de Apple, incluyendo dónde encaja Refund Sensor y dónde no.
Hay algo que siempre cuestiono cuando sale el tema: la automatización de reembolsos de Apple cambia qué tan confiablemente respondes, no quién decide. Nada en esta API le da al desarrollador la última palabra.
Conclusión
La llamada en sí es pequeña: un token firmado, un PUT, cinco campos, un 202 para registrar.
Lo que hace que esto funcione o falle ocurre en otro lugar: en el consentimiento que ya está en tus términos, en un appAccountToken en cada compra, en registros de uso que puedes consultar en segundos, y en algo que se despierte a las 3 a. m. cuando llegue la notificación.
Resuelve eso y esto deja de ser una carrera contra el reloj para convertirse en algo que tu servidor simplemente hace.
Preguntas frecuentes
Es un endpoint de la App Store Server API que se usa para responder a un CONSUMPTION_REQUEST. Envías una solicitud PUT con los detalles de consumo y Apple responde con 202 Accepted.
Tienes 12 horas desde que llega el CONSUMPTION_REQUEST. Apple permite enviar un payload actualizado dentro de esa misma ventana de 12 horas.
Sí. Apple te permite enviar un payload actualizado dentro de la ventana de 12 horas. Esto es útil cuando el primer envío quedó incompleto.
No. Un 202 Accepted solo significa que Apple recibió tu información. El resultado llega después, como una notificación REFUND o REFUND_DECLINED.
Sí. El campo customerConsented es obligatorio al enviar información de consumo. Si el cliente no ha dado su consentimiento, la documentación de Apple indica que no debes responder.



