Reglas de reembolso
Un agente de soporte puede reembolsar un cargo de Stripe, abonar saldo a favor de un cliente de Stripe o reembolsar un pedido de Shopify. Cada petición pasa por el gateway de acciones que alojas tú, que lee los hechos reales en Stripe o en Shopify y pregunta a Burnbound. Burnbound decide con la política del agente y sus reglas propias: deja pasar, deniega o retiene hasta que decida una persona. Aquí tienes los hechos que puede leer una regla, sus condiciones, las plantillas ya hechas y las tres acciones.
¿De dónde salen los hechos de un reembolso?
El agente solo nombra el cargo o el pedido y, si quiere, un importe y un motivo. Todo lo demás lo lee tu gateway de acciones en el proveedor, con tu propia clave:
- Stripe: el cargo (cuándo se creó, su importe, lo ya reembolsado, si está en disputa), su cliente y los cargos del cliente de los últimos 90 días.
- Shopify: el pedido (cuándo se creó, su importe, lo ya reembolsado, sus disputas), su cliente y los pedidos del cliente de los últimos 90 días.
El gateway manda a Burnbound los hechos, nunca la clave. Tu clave de Stripe y tu token de Shopify se quedan en el gateway. Burnbound calcula las antigüedades y la parte reembolsada en el momento de decidir, con su propio reloj y no con el del gateway; el historial de 90 días lo cuenta el gateway al leerlo.
¿Qué hechos ve la política?
| Hecho | Qué es | Condición |
|---|---|---|
| Antigüedad del cargo | Días enteros desde el cargo (o el pedido de Shopify) hasta la decisión, redondeando hacia abajo | refundOriginalAgeDays |
| Parte reembolsada | (Lo ya reembolsado + este reembolso) / el importe original, de 0 a 1, con 4 decimales, redondeando hacia arriba | refundFraction |
| En disputa | El cargo de Stripe está en disputa, o el pedido de Shopify tiene una disputa | refundDisputed |
| Antigüedad del cliente | Días enteros desde el alta del cliente hasta la decisión, redondeando hacia abajo | refundCustomerAgeDays |
| Reembolsos del cliente (90 d) | Los cargos o pedidos del cliente de los últimos 90 días que ya tuvieron reembolso: cuántos y cuánto en USD | refundCustomerCount90d, refundCustomerUsd90d |
| Motivo | El motivo con el que lo pidió el agente: duplicate, fraudulent, requested_by_customer o ninguno |
refundReason |
Reembolsar entero un cargo que nunca se había reembolsado da una parte de 1. La mitad da 0,5.
El historial del cliente funciona igual en Stripe y en Shopify:
- Cuenta los cargos (o pedidos) del cliente creados en los 90 días anteriores a la lectura del gateway que ya llevan algún reembolso. El reembolso que se decide no entra, pero el cargo que se reembolsa sí cuenta si ya tenía un reembolso parcial.
- Cuenta cargos, no reembolsos: un cargo reembolsado en dos veces cuenta una sola.
- Solo cuenta la moneda del reembolso; los cargos en otras monedas quedan fuera. Los USD salen con el mismo tipo de cambio del reembolso, redondeando hacia arriba.
- El gateway lee una página de 100 cargos o pedidos. Si el cliente tiene más, el historial queda truncado: las cifras son mínimos.
Un hecho es desconocido cuando el gateway no lo envió: una compra como invitado sin cliente, un cliente de Stripe borrado (sin antigüedad), una lectura que falló, un gateway antiguo o una clave que no puede leer clientes.
¿Qué condiciones puede usar una regla?
Se ponen en el when de una regla, junto a cualquier otra condición (mira ¿Qué son las reglas propias?).
| Condición | Admite | Valores |
|---|---|---|
refundOriginalAgeDays |
Un rango: gt, gte, lt, lte |
Días enteros, de 0 a 1 000 000 |
refundFraction |
Un rango: gt, gte, lt, lte |
Un número de 0 a 1, con 4 decimales como mucho |
refundCustomerAgeDays |
Un rango: gt, gte, lt, lte |
Días enteros, de 0 a 1 000 000 |
refundCustomerCount90d |
Un rango: gt, gte, lt, lte |
Una cuenta entera, de 0 a 1 000 000 |
refundCustomerUsd90d |
Un rango: gt, gte, lt, lte |
USD como cadena decimal, igual que amountUsd ("250") |
refundDisputed |
true o false |
|
refundReason |
Un valor o una lista | duplicate, fraudulent, requested_by_customer, none |
Un rango necesita al menos un límite. Una lista casa con cualquiera de sus valores. none es un reembolso que el agente pidió sin motivo; un reembolso de Shopify nunca lleva motivo, así que siempre es none.
Por ejemplo, un archivo de reglas para la auditoría de reembolsos que retiene un reembolso grande a un cliente que repite, y cualquier reembolso sin motivo:
[
{
"id": "repeat-customer-review",
"when": {
"refundCustomerCount90d": { "gte": 3 },
"refundFraction": { "gte": 0.5 }
},
"then": { "action": "require_approval" }
},
{
"id": "refund-needs-reason",
"when": { "refundReason": "none" },
"then": { "action": "require_approval" }
}
]
¿Qué pasa si falta un dato?
| El pago | La condición |
|---|---|
| No es un reembolso | No casa nunca |
| Es un reembolso y el hecho se conoce | Compara |
| Es un reembolso y el hecho falta | Casa: la rama restrictiva |
| Tiene el historial truncado | refundCustomerCount90d y refundCustomerUsd90d casan |
Que falte un dato nunca deja pasar un reembolso: un deny sobre él deniega y una retención retiene. Un historial truncado es un mínimo: si lo leído ya llega al límite, la condición se cumple; si no llega, el total real no se sabe, así que también se cumple. El motivo nunca falta: sin motivo es none.
Por eso importan los permisos de la clave. Si tu clave de Stripe no puede leer clientes, la antigüedad de todos es desconocida, y una regla sobre refundCustomerAgeDays toma la rama restrictiva en cada reembolso con cliente. El gateway lo avisa una vez, en el primer reembolso.
Como cualquier regla propia, una regla de reembolso solo restringe. deny gana a require_approval, que gana a dejar pasar, y ninguna regla deja pasar un reembolso que rechacen los topes del agente.
Los reembolsos decididos antes del 3 de noviembre de 2026 se guardaron sin estos hechos. La simulación no los cuenta para una regla de reembolso, y el panel avisa de que la regla podría bloquear más de lo que se ve.
¿Qué son las plantillas de política y los packs?
Una plantilla convierte unos pocos parámetros en reglas propias normales. Un pack son varias plantillas que se aplican juntas. Sus reglas se llaman tpl-<plantilla>, cuentan para las reglas de tu plan y se pasan de aplicar a observar, o se borran, como cualquier otra.
Las plantillas de reembolso:
| Plantilla | En el panel | Qué escribe | Por defecto |
|---|---|---|---|
refund-amount-approval |
Aprobación de reembolsos grandes | Retiene un reembolso por encima de un importe | 100 USD |
refund-customer-monthly-limit |
Reembolsos por cliente y mes | Un tope de reembolsos por cliente y mes natural en UTC (un reembolso sin cliente cuenta por cargo o pedido); el siguiente se deniega | 1 |
refund-old-charge-approval |
Aprobación de reembolsos de cargos antiguos | Retiene el reembolso de un cargo con más de unos días (refundOriginalAgeDays) |
30 días |
refund-disputed-deny |
Sin reembolsos de cargos en disputa | Deniega el reembolso de un cargo en disputa (refundDisputed) |
|
refund-new-customer-full-approval |
Aprobación de reembolsos completos a clientes nuevos | Retiene un reembolso completo (refundFraction desde 1) a un cliente con menos de unos días |
7 días |
refund-repeat-customer-approval |
Aprobación para clientes que repiten reembolso | Retiene el reembolso a un cliente con esos cargos reembolsados en 90 días (refundCustomerCount90d) |
2 |
refund-daily-cap |
Tope diario de reembolsos | Un tope en USD sobre todos los reembolsos de un día UTC: por agente en las reglas de un agente, de todos juntos en las de un subequipo o de la organización | 500 USD |
El pack de reembolsos de soporte (support-refunds, «Agente de soporte con reembolsos» en el panel) aplica las cuatro primeras: los reembolsos grandes y los de cargos antiguos esperan a una persona, un reembolso por cliente al mes y ninguno de un cargo en disputa.
Las plantillas de importe, por cliente y diaria nombran los métodos de reembolso (action.stripe.refund y action.shopify.refund), así que nunca tocan los demás pagos del agente. Los reembolsos de Stripe y de Shopify suman a los mismos topes. Una regla aplicada antes de que existieran los reembolsos de Shopify solo nombra Stripe: borra sus reglas y vuelve a aplicar la plantilla para que cubra Shopify. Las demás plantillas leen hechos de reembolso, que solo tienen los reembolsos. Ninguna plantilla cubre los abonos de Stripe.
¿Cómo aplico una plantilla desde el panel?
- Abre el agente y activa el método de reembolso en su pestaña Red, en Métodos de pago. En cuanto la política guardada permite
action.stripe.refund, esa misma pestaña te ofrece el pack de reembolsos de soporte. - O abre Reglas · reglas propias. La galería Reglas nuevas del catálogo lista todas las plantillas y los packs; Reembolsos los filtra.
- Elige una y ajusta sus valores. Escoge Aplica (deniega o retiene) u Observación (solo lo apunta en la auditoría).
- Previsualizar enseña las reglas que escribe y qué habría hecho cada una con los pagos de los últimos 30 días. No se guarda nada.
- Aplicar escribe todas sus reglas en una sola versión de la política, todo o nada.
Las reglas de subequipo y de organización tienen la misma galería, y todas las plantillas de reembolso y el pack sirven también ahí, en Team y Business. Para cambiar reglas hace falta ser owner o admin.
Una plantilla se aplica una vez por agente, subequipo u organización: si la aplicas otra vez, el panel responde «Ya aplicada» con las reglas que ya están. La aprobación de cargos antiguos, la denegación en disputa y la aprobación de clientes que repiten se abren en el formulario de Reembolsos protegidos. Las demás plantillas de reembolso no tienen formulario de edición: para cambiar un valor, borra sus reglas y vuelve a aplicar la plantilla. Si no caben en tu plan, no se escribe nada y el panel te dice cuántos huecos faltan: en Free caben 3 reglas propias y el pack escribe 4.
Para una condición que el catálogo no cubre (el motivo, una comparación libre), usa Reembolsos protegidos en las reglas propias del agente: una condición de reembolso por regla (el hecho, cómo se compara y el valor; la parte reembolsada como porcentaje de 0 a 100) y luego denegar el reembolso o retenerlo hasta que se apruebe. Por la API, una regla puede juntar varias condiciones.
La API que hay detrás de la galería es GET /v1/policy-templates para el catálogo y POST /v1/agents/:agentId/rules/from-template (y también /v1/org/teams/:teamId/rules/from-template y /v1/org/rules/from-template) con { "packId": "support-refunds", "mode": "observe", "dryRun": true }. Leer el catálogo admite cualquier rol con sesión o una org key; aplicar una plantilla, también con dryRun, exige una sesión de owner o admin.
¿Qué acciones puede hacer un agente de soporte?
| Herramienta MCP | Método | Qué lee el gateway | Reglas |
|---|---|---|---|
stripe_refund |
action.stripe.refund |
El cargo: moneda, cliente, modo live y lo que queda por reembolsar; luego el cliente y su historial | Las condiciones de reembolso |
stripe_credit |
action.stripe.credit |
El cliente: la moneda de su saldo, el modo live y su antigüedad. El abono va a su saldo a favor y se aplica a sus próximas facturas | creditCustomerAgeDays |
shopify_refund |
action.shopify.refund |
El pedido: moneda de presentación, lo que queda por reembolsar en su pago, sus disputas y si es un pedido de prueba; luego la antigüedad del cliente y sus pedidos reembolsados en 90 días | Las condiciones de reembolso |
En un reembolso, la moneda, el cliente y lo que queda por reembolsar salen siempre del proveedor, nunca del agente; el agente solo puede pedir un importe hasta ahí. En un abono, el agente nombra el cliente y el importe; la moneda es la del saldo del cliente, o la del agente solo si el cliente aún no tiene ninguna (otra distinta es currency_mismatch). Un reembolso por encima de lo que queda por reembolsar se rechaza antes de preguntar a Burnbound (amount_exceeds_refundable).
Un abono no es un reembolso: las condiciones de reembolso nunca casan con él. Su hecho propio es la antigüedad del cliente, creditCustomerAgeDays, un rango de días enteros con la misma regla para un valor desconocido. Un reembolso de Shopify devuelve el dinero al pago original del pedido, sin reponer inventario.
Las tres vienen desactivadas. Se activan por agente con allowMethods (los Métodos de pago de la pestaña Red). Cada una cuenta como gasto para los topes del agente, pasa por las mismas aprobaciones y se ejecuta una sola vez por idempotencyKey. Una acción retenida vuelve como pending_approval; quien la aprueba ve los hechos del reembolso en el panel, en Slack o en el email. Una vez aprobada, el agente manda la misma petición con la misma idempotencyKey.
Las herramientas MCP llegan al gateway en BURNBOUND_GATEWAY_URL. Cada campo y cada código de error están en la referencia de las herramientas MCP.
¿Qué permisos necesitan las claves?
La clave de Stripe es una clave restringida (rk_…) con solo:
| Recurso | Permiso |
|---|---|
| Charges | Read |
| Customers | Read (Write para los abonos) |
| PaymentIntents | Read |
| Refunds | Write |
Los abonos necesitan Customers en Write, porque las transacciones de saldo del cliente se crean y se listan dentro de Customers. Una clave secreta completa funciona, pero el gateway avisa.
El token de Shopify es el token de acceso a la Admin API de una app personalizada creada en el admin de tu tienda (shpat_…), con solo los permisos read_orders, write_orders y read_customers. Sin read_customers, la antigüedad y el historial del cliente llegan a Burnbound como desconocidos.
El gateway activa cada acción solo si su proveedor está configurado. Una clave de Stripe activa los reembolsos y los abonos; SHOPIFY_SHOP_DOMAIN y SHOPIFY_ADMIN_TOKEN activan los reembolsos de Shopify. Una acción sin su proveedor responde action_not_configured.
¿Cómo muevo dinero real?
Empieza en el modo test de Stripe y en una tienda de desarrollo de Shopify. El modo live necesita GATEWAY_ALLOW_LIVE=1 en el gateway:
- Stripe: el gateway no arranca con una clave live si no está puesto.
- Shopify: un token no dice si mueve dinero real. Si no está puesto, el gateway solo reembolsa en una tienda de desarrollo, lo comprueba en cada petición y, si no lo es, responde
live_not_allowed.
¿Cómo pruebo las reglas antes?
La auditoría de reembolsos repasa en tu máquina tus reembolsos de Stripe de los últimos días con el pack de reembolsos de soporte, o con tu propio archivo de reglas. Construye los hechos igual que el gateway y te dice cuántos reembolsos se habrían denegado o retenido, y por qué regla. No se manda nada a Burnbound.
En Burnbound, aplica primero el pack en modo Observación: las decisiones apuntan lo que habrían hecho las reglas, sin bloquear nada.
¿Dónde configuro el gateway?
- Pon en marcha el gateway en 5 minutos: la credencial del gateway, la clave restringida y un despliegue en Render, Railway, Fly.io o Docker Compose, desde el asistente del panel.
- Gateway de acciones (reembolsos de Stripe): el flujo completo, desde la petición del agente hasta el reembolso registrado.