Todos los artículos
Deep dive8 min de lectura

Cuando se reembolsa o revierte un cargo de una compra en Google Play, la Voided Purchases API es como te enteras

Google Play anula una compra de forma silenciosa cuando se reembolsa o se revierte el cargo. La Voided Purchases API es la lista de esos pedidos, para que puedas revocar el acceso. Aqui tienes cada campo, la ventana de 30 dias, la opcion de revocar que oculta pedidos y lo que cuesta.

Un telefono inteligente junto a un libro de cuentas de papel, un candado de laton cerrado y una moneda que se aleja deslizandose, que ilustran la Voided Purchases API de Google Play que informa de los pedidos reembolsados y con cargo revertido

Puntos clave

  • La Voided Purchases API, el metodo purchases.voidedpurchases.list, devuelve los pedidos que Google Play cancelo, reembolso o cuyo cargo se revirtio, para que puedas construir un sistema de revocacion que corte el acceso a lo que el cliente ya no posee.
  • Solo aparecen los pedidos revocados. Un reembolso emitido por el desarrollador sin la opcion de revocar es invisible para esta API, asi que si quieres retirar el acceso, tienes que reembolsar con la revocacion activada.
  • La ventana es de 30 dias. startTime no puede ser anterior a hace 30 dias, asi que un servidor que permanece caido mas de un mes pierde esos pedidos anulados para siempre. Consulta con una programacion regular.
  • voidedSource te dice quien anulo el pedido: 0 es el usuario, 1 es el desarrollador, 2 es Google. voidedReason te dice por que, desde 0 Other hasta 7 Chargeback y 8 Unacknowledged_purchase.
  • Las Real-time developer notifications envian una VoidedPurchaseNotification en el momento en que se anula una compra, pero tratala como una senal. Llama a la Voided Purchases API para obtener la lista autorizada antes de revocar.
  • Identifica las renovaciones de suscripcion por orderId, no por purchaseToken. Un solo purchaseToken cubre todas las renovaciones de una suscripcion, asi que el token por si solo no puede distinguir dos renovaciones.
  • Las cuotas son 6,000 consultas al dia y 30 consultas en cualquier ventana de 30 segundos, asi que recorre los resultados por paginas con el token de continuacion y consulta por ventana de tiempo, nunca una llamada por pedido.

Un reembolso en Google Play no llama a tu puerta. El dinero se mueve, el cliente mantiene la app abierta y, a menos que vayas a buscar, nada cambia de tu lado. La Voided Purchases API es donde vas a buscar. Te entrega una lista de pedidos que fueron cancelados, reembolsados o con el cargo revertido, para que puedas revocar el acceso a lo que el cliente ya no pago. Apunta un trabajo programado hacia ella, lee la lista, corta el derecho de uso. Ese es todo el ciclo.

Hay una trampa que hace tropezar a la mayoria de los equipos, y no esta en el codigo. Solo aparecen aqui los pedidos que fueron revocados. Si reembolsas una compra en la Play Console sin marcar la opcion de revocar, ese pedido nunca llega a esta API, y tu trabajo se ejecuta limpio mientras un cliente reembolsado conserva todo lo que le vendiste. Esta entrada recorre la API campo por campo, los numeros que la limitan y por donde se escapa el dinero cuando la omites.

Que devuelve realmente la Voided Purchases API

La API responde a una sola pregunta: que pedidos de esta app se anularon recientemente. Una anulacion cubre tres resultados que terminan todos con el cliente recuperando su dinero. Una cancelacion, un reembolso o un cargo revertido. Se aplica a productos integrados de un solo pago y a las suscripciones, y eliges el alcance con un solo parametro. Pon type en 0 y obtienes solo las compras de productos integrados anuladas, que es el valor predeterminado. Ponlo en 1 y obtienes las compras integradas anuladas y las compras de suscripcion anuladas juntas.

Cada entrada de la lista es un objeto de compra anulada. Los campos son pocos y todos y cada uno importan.

Los campos de una compra anulada

CampoQue contiene
orderIdEl id de pedido que identifica de forma unica una compra de un solo pago, una compra de suscripcion o una unica renovacion de suscripcion. Esta es tu clave de union
purchaseTokenEl token que identifica una compra de un solo pago o una suscripcion. No distingue las renovaciones, asi que usa orderId para esas
purchaseTimeMillisCuando se realizo la compra, en milisegundos desde la epoca
voidedTimeMillisCuando se cancelo, reembolso o revirtio el cargo de la compra, en milisegundos desde la epoca
voidedSourceQuien inicio la anulacion: 0 usuario, 1 desarrollador, 2 Google
voidedReasonPor que se anulo la compra, un entero de 0 a 8
voidedQuantityLa cantidad anulada de un reembolso parcial basado en cantidad, devuelta solo cuando includeQuantityBasedPartialRefund es true

Lee voidedReason antes de actuar

voidedReason es el campo que convierte una lista en bruto en una decision. Un reembolso por arrepentimiento del comprador y un cargo revertido por el banco caen ambos en la misma lista, pero no son el mismo evento, y los precios de agosto hacen que uno de ellos sea caro. Aqui esta el conjunto completo.

voidedReasonEtiquetaQue significa para ti
0OtherNo se asigno ninguna categoria. Revoca y sigue adelante
1RemorseEl comprador cambio de opinion. Un reembolso ordinario
2Not_receivedEl cliente dice que nunca recibio el producto. Vale la pena revisar tu entrega
3DefectiveEl producto no funciono. Una senal de calidad, registrala
4Accidental_purchaseUna compra no intencionada, a menudo un dispositivo compartido
5FraudGoogle marco la transaccion como fraudulenta
6Friendly_fraudUn cargo revertido en el que el titular legitimo de la tarjeta disputa un cargo que el mismo hizo
7ChargebackEl banco del cliente revirtio el pago. Definitivo con el banco, y ahora se te factura a ti
8Unacknowledged_purchaseGoogle reembolso automaticamente una compra que tu app nunca confirmo

La ventana de 30 dias es la trampa que vacia tu lista

La Voided Purchases API solo puede mostrar las compras anuladas de los ultimos 30 dias. El parametro startTime tiene como valor predeterminado la hora actual menos 30 dias, y no se puede fijar antes de eso. endTime tiene como predeterminado ahora. Asi que el endpoint es una ventana movil de un mes, no un archivo.

La consecuencia es contundente. Si tu trabajo de consulta se rompe y nadie se da cuenta durante cinco semanas, las anulaciones de la primera semana han caducado en la API. No hay ninguna llamada que las traiga de vuelta. No revocaras esos pedidos, y ni siquiera sabras que existieron a menos que los hayas capturado de alguna otra forma. La API es una red de seguridad con un agujero del tamano de tu peor caida de servicio.

La opcion de revocar decide si un pedido siquiera aparece

Esta es la razon mas comun por la que un equipo reporta que la API esta rota. Solo se devuelven los pedidos revocados. Los reembolsos iniciados por el usuario, las cancelaciones, los cargos revertidos y los reembolsos iniciados por Google siempre se revocan, asi que siempre aparecen. Un reembolso iniciado por el desarrollador es distinto. Cuando reembolsas un pedido tu mismo, a traves de la Play Console o la Orders API, eliges si tambien lo revocas. Reembolsa sin revocar, y el pedido queda saldado con el cliente pero nunca aparece en la Voided Purchases API.

La regla que se deduce es simple. Si tu intencion es retirar el acceso, reembolsa con la opcion de revocar activada. De lo contrario, has devuelto el dinero y dejado la puerta abierta, y tu trabajo de revocacion, por bien escrito que este, no tiene nada sobre lo que actuar.

Como consultarla sin exceder la cuota

El endpoint tiene un limite de tasa, y los limites son lo bastante bajos como para que un bucle ingenuo los alcance. Tienes 6,000 consultas al dia, contadas en hora del Pacifico, y no mas de 30 consultas en cualquier periodo de 30 segundos. Ese presupuesto esta bien para la consulta por ventanas y es hostil a los disenos de una peticion por pedido.

Ventanas de consulta y el token de continuacion

maxResults tiene como valor predeterminado 1,000, que es tambien el tope. Cuando una ventana contiene mas de una pagina de anulaciones, la respuesta lleva un objeto tokenPagination con un nextPageToken. Pasa ese token de vuelta en la siguiente llamada para recorrer las paginas. Fija startTime y endTime para acotar la ventana que te interesa, avanza por las paginas hasta que se agote el token, y luego mueve la ventana. Ese patron te mantiene dentro tanto del limite de rafaga de 30 segundos como del tope diario.

Las Real-time developer notifications cierran la brecha

Consultar cada dia todavia deja hasta un dia de ceguera, y la ventana de 30 dias castiga los huecos largos. Las Real-time developer notifications eliminan el retraso. Google publica una VoidedPurchaseNotification en un tema de Cloud Pub/Sub que tu posees en el momento en que se anula una compra, y tu backend la consume en cuestion de segundos. El mensaje es pequeno.

Campo RTDNQue contiene
purchaseTokenEl token de la compra original
orderIdEl id de pedido de la transaccion anulada, uno nuevo por cada renovacion de suscripcion
productType1 para una suscripcion, 2 para una compra de un solo pago
refundType1 para un reembolso total, 2 para un reembolso parcial basado en cantidad
Una mano cerrando un candado de laton sobre una pila de recibos junto a un telefono inteligente, que ilustra la revocacion del acceso despues de que se anula una compra en Google Play

Lo que esto te cuesta en dinero

La API es fontaneria, pero la razon para conectarla es una factura. Cada anulacion de esa lista corresponde a un numero real, y dos de ellas se estan volviendo mas caras.

La factura del cargo revertido recae sobre ti a partir del 3 de agosto de 2026

A partir del 3 de agosto de 2026, Google traslada el coste de un cargo revertido al desarrollador. Pierdes el precio de la compra y pagas ademas la comision de cargo revertido del banco. Un voidedReason de 7 ya no es solo una venta perdida, es una partida con una comision adjunta. No puedes revertir un cargo revertido, es definitivo con el banco, pero puedes detener la hemorragia despues. Detectar la anulacion rapido te permite revocar el derecho de uso y, para cualquier cosa que sigas entregando, dejar de gastar en un cliente que fue reembolsado y luego revirtio el cargo.

Sigues pagando por servir a un cliente reembolsado

El precio de la compra se pierde en el momento en que aparece una anulacion. Lo que aun controlas es el coste de seguir entregando. Cada hora que un derecho de uso reembolsado sigue activo, sigues pagando por las cosas que el cliente ya no financia: computo, llamadas a la API del modelo, almacenamiento y cualquier pago a creadores o socios ligado a su uso. Un sistema de revocacion impulsado por esta API es como apagas ese contador. Omitelo, y financias el producto para personas a las que la tienda ya compenso.

El fraude amistoso es un patron que vale la pena analizar en tendencia

Un voidedReason de 5 o 6 no es algo aislado. El fraude y el fraude amistoso se agrupan por cuenta, por dispositivo y a veces por promocion. La API te da el voidedSource y el voidedReason en cada anulacion, lo que basta para analizar la tendencia del abuso por cuenta en lugar de tratar cada reversion como un coste aislado. Un cliente que revierte el cargo dos veces te esta diciendo algo que el primer reembolso no dijo.

Conectandolo a la manera de RefundHalt

El modelo es pequeno una vez que tienes todas las piezas. Escucha las VoidedPurchaseNotification en tiempo real para que nada espere un dia entero. Llama a la Voided Purchases API como fuente de verdad, con clave en orderId para que las renovaciones de suscripcion nunca se confundan. Lee voidedSource y voidedReason para que un cargo revertido se maneje distinto de un reembolso por arrepentimiento. Consulta con una programacion lo bastante ajustada como para que la ventana de 30 dias nunca muerda, y reembolsa con la opcion de revocar activada siempre que tu intencion sea cortar el acceso.

Esta es la parte que RefundHalt ejecuta por ti. Consume las notificaciones en tiempo real, concilia cada anulacion con la API, revoca el pedido exacto en lugar de todo el producto, y separa un cargo revertido del banco de un reembolso ordinario para que los caros se marquen, no se entierren. Consigues el acceso revocado en segundos y un registro de quien anulo que y por que, sin tener que montar tu mismo una tuberia de Pub/Sub y un trabajo de consulta.

Preguntas frecuentes

Por que mis pedidos reembolsados no aparecen en la Voided Purchases API?
Porque solo se devuelven los pedidos revocados. Los reembolsos de usuario, las cancelaciones, los cargos revertidos y los reembolsos iniciados por Google siempre se revocan y siempre aparecen. Un reembolso iniciado por el desarrollador solo aparece si ademas elegiste la opcion de revocar. Si reembolsaste un pedido sin revocarlo, el pedido queda saldado pero es invisible para esta API, asi que reembolsa con la revocacion activada siempre que pretendas retirar el acceso.
Hasta cuando se remonta la Voided Purchases API?
Treinta dias. El parametro startTime tiene como valor predeterminado la hora actual menos 30 dias y no se puede fijar antes de eso, asi que el endpoint es una ventana movil de un mes en lugar de un archivo. Un pedido anulado que supera los 30 dias desaparece de la API sin ninguna forma de recuperarlo, por lo que consultas con una programacion regular y lo respaldas con notificaciones en tiempo real.
Deberia usar las Real-time developer notifications o la Voided Purchases API para revocar el acceso?
Usa ambas. La VoidedPurchaseNotification llega en cuestion de segundos y te dice que mires, pero la propia guia de Google es tratarla como una senal, no como una fuente de verdad. Llama a la Voided Purchases API para confirmar el estado actual, y luego revoca. La notificacion elimina el retraso, y la API te da el voidedSource y el voidedReason autorizados sobre los que actuar.
Como distingo un cargo revertido de un reembolso ordinario en la API?
Lee el campo voidedReason. Un valor de 7 es un cargo revertido, lo que significa que el banco del cliente revirtio el pago, y 6 es fraude amistoso. Un valor de 1 es un reembolso por arrepentimiento. Esto importa porque a partir del 3 de agosto de 2026 Google traslada el precio de la compra del cargo revertido y la comision del banco al desarrollador, asi que un voidedReason de 7 te cuesta mas que un reembolso simple.
La Voided Purchases API cubre las suscripciones?
Si. Pon el parametro type en 1 para obtener tanto las compras integradas anuladas como las compras de suscripcion anuladas. El valor predeterminado, type 0, devuelve solo las compras de productos integrados. Para las suscripciones, identifica el periodo anulado exacto por orderId, porque un solo purchaseToken cubre todas las renovaciones y se genera un nuevo orderId para cada transaccion de renovacion.

Fuentes y lecturas adicionales

RefundHalt

El piloto automático de reembolsos para App Store y Google Play

Seguir leyendo

La próxima solicitud de reembolso ya está en camino.

Configura RefundHalt en el tiempo que tardas en leer otro correo de soporte sobre un reembolso que no llegaste a impugnar.