# Documentación de Rapid > Documentación de integración de Rapid, con prevención de disputas, alertas de contracargo, envío de transacciones, webhooks y captura de evidencias. Página: https://doc.rapidchargeback.com/es/ ## Con tu asistente de IA Conecta el MCP y tu asistente (Claude, Cursor, VS Code, ChatGPT) consulta esta documentación mientras programas, con los nombres de campo y los códigos de error reales, en lugar de responder de memoria. ```text https://doc.rapidchargeback.com/mcp/ ``` [Cómo configurarlo](https://doc.rapidchargeback.com/es/referencia/ferramentas-para-devs/#mcp) · [Colección de Postman](https://doc.rapidchargeback.com/es/referencia/ferramentas-para-devs/#colección-de-postman) · [llms.txt](https://doc.rapidchargeback.com/es/llms.txt) ## Los productos ### Prevención Cuando el banco emisor abre una consulta, Rapid responde con los datos del pedido para que la disputa no se abra. [Visión general](https://doc.rapidchargeback.com/es/produtos/prevencao/visao-geral/) · [Integración](https://doc.rapidchargeback.com/es/produtos/prevencao/integracao/) ### Alerta El emisor avisa de la disputa antes de que se convierta en contracargo, y respondes a tiempo para reembolsar o suspender el acceso. [Visión general](https://doc.rapidchargeback.com/es/produtos/alerta/visao-geral/) · [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/) ### Disputa Con el contracargo ya abierto, Rapid arma y presenta la defensa dentro del plazo de la red de tarjetas. [Visión general](https://doc.rapidchargeback.com/es/produtos/disputa/visao-geral/) ## Empieza aquí - [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/): Las credenciales, dónde obtenerlas y cómo enviarlas en cada canal. - [Enviar transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/): El canal de entrada que alimenta Prevención y Disputa. - [Recibir webhooks](https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/): Cómo Rapid entrega alertas y eventos en tu sistema. - [Responder una alerta](https://doc.rapidchargeback.com/es/callback/visao-geral/): El callback de estado, con los valores aceptados y el plazo de cada proveedor. - [Capturar evidencias](https://doc.rapidchargeback.com/es/canais/capture/visao-geral/): El snippet de checkout y los dos canales de eventos. - [Ejemplos canónicos](https://doc.rapidchargeback.com/es/referencia/exemplos-canonicos/): Los IDs y valores fijos usados en todos los ejemplos. --- # Primera integración > De cero a la primera alerta respondida: credenciales, webhook con firma validada, primera transacción y el callback de estado, con los comandos listos. Página: https://doc.rapidchargeback.com/es/primeira-integracao/ El camino más corto hasta la integración funcionando. Al final de esta guía tu aplicación recibe alertas con la firma validada, envía transacciones y responde alertas por la API. Cada paso apunta a la página con el detalle completo. > **¿Usas un asistente de IA?** Conecta el [MCP de la documentación](https://doc.rapidchargeback.com/es/referencia/ferramentas-para-devs/#mcp) antes de empezar: el asistente pasa a consultar estas páginas en lugar de deducir campos y códigos. ## 1. Obtén las credenciales En el panel de Rapid, en **Configuración › API**, genera el `client_id` y el `client_secret`. El secreto aparece **una sola vez**: cópialo en el momento. Si lo pierdes, genéralo de nuevo en el mismo lugar (las credenciales anteriores dejan de valer en ese mismo instante). Guarda las dos en variables de entorno, nunca en el código: ```bash export RAPID_CLIENT_ID="tu_client_id" export RAPID_CLIENT_SECRET="tu_client_secret" ``` Detalles en [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ## 2. Confirma que la credencial funciona Lista la alerta más reciente de tu empresa: ```bash curl -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts?per_page=1" ``` | Respuesta | Qué significa | |---|---| | `200` con `data` y `meta` | Credencial correcta. `data` puede venir vacío si todavía no llegó ninguna alerta | | `401 UNAUTHORIZED` | `client_id` o `client_secret` incorrecto | | `403 COMPANY_BLOCKED` | La empresa está bloqueada en Rapid: habla con soporte | ## 3. Registra el webhook En **Configuración › Webhook**, registra la URL que va a recibir los eventos. Tiene que ser **HTTPS** y una **dirección pública de internet**: el panel rechaza `http://`, `localhost` e IPs de red local. Al guardar, Rapid genera la **clave de firma** y la muestra una sola vez. Guárdala en `RAPID_WEBHOOK_SECRET`. Para recibir en tu máquina durante el desarrollo, expón el servidor local con un túnel HTTPS (ver [Buenas prácticas](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/#usa-una-dirección-pública-de-internet)). ## 4. Valida la firma Toda entrega trae `X-Webhook-Signature` y `X-Webhook-Timestamp`. Tu endpoint verifica la firma **antes** de procesar cualquier cosa. Copia el endpoint listo de tu lenguaje (Node.js, Python o PHP) en [Autenticación del webhook](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/#ejemplos). Los tres siguen las mismas reglas: - la firma se calcula sobre el **cuerpo crudo**: no lo leas como JSON antes de validar - una entrega con más de 5 minutos se rechaza (protección contra reenvío) - toda entrega que no pase recibe `401` Responde `2xx` rápido y procesa después, en una cola: Rapid espera hasta 30 segundos y, sin respuesta, lo intenta de nuevo. Usa el `alert_id` para no procesar la misma alerta dos veces. Ver [Buenas prácticas](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/). ## 5. Envía la primera transacción Si usas **Prevención** o **Disputa**, trabajan con las transacciones de venta que envías. Cada transacción indica de qué merchant (tienda, marca o vendedor) es, por el `merchant_id`. Mira los tuyos: ```bash curl -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ "https://api.rapidchargeback.com/api/v1/merchants" ``` El `id` de cada ítem de la respuesta es el `merchant_id` (ver [Listar merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/)). Con él, la transacción mínima: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/transactions \ -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "transaction_id": "cob_8f2a91c4", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_bin": "424242", "card_last4": "4242", "items": [ { "product_description": "Assinatura Premium - Mensal", "unit_price": 150.00 } ] }' ``` - El `transaction_id` es el identificador del cobro en tu gateway de pago. Es por él que un contracargo futuro encuentra la transacción: sin él la defensa sale sin historial. - La respuesta es `201` con el `id` de la transacción en Rapid: guárdalo. Si lo pierdes, puedes encontrar la transacción [por el `external_id`](https://doc.rapidchargeback.com/es/canais/transactions/consultar-transacao/#por-el-id-de-tu-sistema). - Si viene la clave `warnings`, la transacción se creó, pero faltan campos que mejoran la protección. Todos los campos en [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/). Para volumen, usa el [envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/). ## 6. Responde la primera alerta Cuando llega una alerta de **Mastercard**, tienes **24 horas** para responder. Con el `alert_id` recibido en el webhook: ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/00000000-0000-0000-0000-000000000099/status \ -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ -H "Content-Type: application/json" \ -d '{ "status": "account_suspended" }' ``` | Estado | Cuándo usarlo | |---|---| | `notfound` | La transacción no existe en tu sistema | | `account_suspended` | La transacción existe y ya está resuelta (reembolso hecho, acceso cortado) | | `other` | La transacción existe, pero todavía no está resuelta | Una alerta de **Visa** llega con el reembolso ya hecho y no tiene plazo. Ver [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/). ## Antes de ir a producción - [ ] Credenciales y clave de firma en variables de entorno o en un gestor de secretos - [ ] El webhook valida la firma y la ventana de 5 minutos, y rechaza con `401` - [ ] El webhook responde `2xx` en menos de 30 segundos y procesa en cola - [ ] El mismo `alert_id` procesado dos veces no genera efecto duplicado - [ ] Alerta de Mastercard respondida en hasta 24 horas, de forma automática o por alguien de guardia - [ ] Transacciones con `transaction_id` completo, si usas Disputa - [ ] `429` manejado esperando el `Retry-After` (ver [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/#rate-limit)) ## Próximos pasos - [Payload del webhook](https://doc.rapidchargeback.com/es/canais/webhook/payload/): todos los campos de cada evento. - [Problemas comunes](https://doc.rapidchargeback.com/es/referencia/problemas-comuns/): qué hacer cuando algo no funciona. - [Herramientas para devs](https://doc.rapidchargeback.com/es/referencia/ferramentas-para-devs/): la documentación en tu asistente de IA y la colección de Postman. --- # Prevención > Cómo Prevención cierra la disputa antes del contracargo, respondiendo al banco emisor con los datos del pedido a partir de las transacciones que ya envías. Página: https://doc.rapidchargeback.com/es/produtos/prevencao/visao-geral/ **Prevención** es la solución de Rapid para la deflexión de disputas en tiempo real. Cuando un banco emisor abre una consulta sobre una compra, Rapid responde al instante con los datos del pedido original, y la disputa no llega a convertirse en contracargo. No llamas a ningún endpoint de Prevención: funciona a partir de las transacciones que ya envías. El trabajo de integración es **enviar las transacciones con los campos correctos**, descritos en [Integración](https://doc.rapidchargeback.com/es/produtos/prevencao/integracao/). ## Cómo funciona 1. Envías tus transacciones de venta a Rapid a través de la [API de Transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/) 2. Cuando el banco emisor consulta una transacción en disputa, Rapid encuentra automáticamente la transacción correspondiente entre las que enviaste 3. Rapid responde con los datos del pedido: merchant, artículos comprados, dirección de envío y datos del comprador 4. Con eso, el banco puede cerrar la disputa antes de que se convierta en contracargo ## Tipos de protección Las dos ocurren solas. No eliges una ni otra: Rapid usa la que los datos de la transacción permitan, y las dos pueden aplicar a la misma compra. ### Reconocimiento de la compra Muestra al titular de la tarjeta, a través de su banco, los detalles del pedido: qué se compró, cuándo y a quién. Resuelve la disputa que surge porque la persona **no reconoció** el cargo. Funciona con los campos mínimos de la transacción. ### Protección contra fraude Demuestra que quien compró es el propio dueño de la tarjeta, con señales de la compra: IP, dispositivo, la cuenta del cliente en tu sistema y dirección de envío. Puede cerrar automáticamente una disputa de **fraude**. Requiere dos señales, descritas en [Integración](https://doc.rapidchargeback.com/es/produtos/prevencao/integracao/#para-la-protección-contra-fraude). --- # Integración > Qué enviar para activar Prevención: datos del merchant, campos mínimos de la transacción y los que habilitan la protección contra fraude. Página: https://doc.rapidchargeback.com/es/produtos/prevencao/integracao/ Para integrar Prevención, envías tus transacciones de venta a Rapid a través de la **API de Transacciones**. Consulta la [documentación de la API de Transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/) para los detalles completos de los endpoints. ## Datos del merchant Antes de enviar transacciones, asegúrate de que tu merchant esté registrado con la información completa. Los siguientes campos del merchant son **obligatorios** para que Prevención funcione: | Campo | Descripción | |---|---| | `name` | Nombre del merchant | | `merchant_url` | URL del sitio del merchant | | `contact_phone` | Teléfono de contacto | | `store_name` | Nombre de la tienda | ## Campos mínimos de la transacción Además de los campos obligatorios de la API de Transacciones, Prevención necesita los siguientes para funcionar: | Campo | Por qué | |---|---| | `items[]` con `product_description` | Descripción de los productos comprados. Sin ella no hay qué mostrar al banco emisor | | `order_number` | Identificación del pedido en la respuesta al banco emisor (recomendado) | ## Campos recomendados Cuantos más datos envíes, mayor la probabilidad de desviar disputas. La tabla de abajo muestra los campos recomendados y el impacto de cada uno: ### Para el reconocimiento de la compra | Campo | Impacto | |---|---| | `card_bin` | Aumenta la precisión del match con la transacción en disputa | | `auth_code` | Mejora la identificación de la transacción | | `customer.first_name` y `customer.last_name` | Ayuda al titular a reconocer la compra | | `customer.email` | Ayuda al titular a reconocer la compra | ### Para la protección contra fraude La protección contra fraude atiende disputas de **fraude**. Necesita **dos señales** de que quien compró es el dueño de la tarjeta: un identificador de la compra (el ancla) y un dato más que confirme a la persona. Para calificar una transacción, envía una de las 3 combinaciones de abajo. El ancla (`ip_address`, `device_id` o `device_fingerprint`) es **obligatoria**; junto a ella, envía **al menos un** campo de la columna de complementos. | Formato | Ancla obligatoria | Al menos uno de los complementos | |---|---|---| | **Opción 1** | `ip_address` | `customer.account_id`, `addresses` (shipping), `device_id` o `device_fingerprint` | | **Opción 2** | `device_id` | `customer.account_id`, `addresses` (shipping) o `ip_address` | | **Opción 3** | `device_fingerprint` | `customer.account_id`, `addresses` (shipping) o `ip_address` | #### Campos: formato y restricciones | Campo | Requisitos | |---|---| | `ip_address` | IP pública del comprador en el momento de la compra. Texto plano, no puede ser hash. IPv4 o IPv6 | | `device_id` | Identificador único del dispositivo (ej.: IMEI). Texto plano, mín. 15 caracteres, no puede ser hash | | `device_fingerprint` | Fingerprint derivada de atributos del dispositivo (SO, modelo, versión, etc.). Mín. 20 caracteres. Puede ser hash | | `customer.account_id` | Identificador de inicio de sesión del comprador en tu sistema (email, username). Un único valor | | `addresses` (type: shipping) | Dirección de envío completa: `street` (address1), `city`, `state` (region), `postal_code`, `country`. No puede ser dirección de tienda | > **No eliges la opción.** Envía todos los campos que tengas: Rapid usa automáticamente la combinación que tu transacción cubre. Por ejemplo, si envías `ip_address + device_id + account_id`, tu transacción califica tanto para la Opción 1 como para la Opción 2, y la combinación con más campos maximiza la probabilidad de deflexión. #### Bienes digitales: no envíes dirección de envío Si tu empresa vende **bienes digitales** (software, SaaS, streaming, ebooks, cursos online, servicios sin entrega física), **no envíes `addresses` con type `shipping`**. Las reglas de la red de tarjetas prohíben que quien vende bienes digitales informe una dirección de envío, y enviarla puede **suspender la protección contra fraude** de tu cuenta. Para bienes digitales, concéntrate en estos complementos: | Opción | Ancla | Complementos prácticos | |---|---|---| | 1 | `ip_address` | `customer.account_id`, `device_id`, `device_fingerprint` | | 2 | `device_id` | `customer.account_id`, `ip_address` | | 3 | `device_fingerprint` | `customer.account_id`, `ip_address` | `customer.account_id` e `ip_address` suelen ser los campos más naturales de capturar en e-commerce digital. ## Ejemplo de transacción completa ```json { "merchant_id": "00000000-0000-0000-0000-000000000001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "device_id": "041C226BBD5A80020040105118304404", "external_source": "shopify", "external_id": "TXN-2026-001", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00 } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com", "account_id": "joao@exemplo.com" }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ] } ``` Este ejemplo incluye todos los campos recomendados para la máxima cobertura de deflexión. --- # Alerta > Cómo Alerta te avisa de una disputa antes de que se convierta en contracargo, cómo llega la alerta a tu empresa y qué responder en cada red de tarjetas. Página: https://doc.rapidchargeback.com/es/produtos/alerta/visao-geral/ **Alerta** es la solución de Rapid para la **notificación anticipada de disputas**. (Nombre anterior: *Chargeback Alert*. La ruta de la API sigue siendo `/chargeback-alert/...`.) Cuando un titular de tarjeta abre una disputa con el banco emisor, la red (Mastercard o Visa) avisa del evento a los proveedores antes de que se convierta en un contracargo formal. Rapid recibe esas señales y te entrega la alerta a tiempo para que actúes. En los payloads y respuestas de la API, los proveedores se identifican con los slugs `ethoca_alerts` (Mastercard) y `verifi_rdr` (Visa). Lo que tienes que hacer depende de la red de tarjetas: - **Mastercard** (vía Ethoca): tienes hasta 24 horas para confirmar si vas a reembolsar, indicar que la transacción ya se resolvió o que no encontraste la transacción. Tu respuesta vuelve a Ethoca y puede evitar que la disputa se convierta en contracargo. - **Visa** (vía Verifi RDR): el adquirente ya hizo el reembolso automáticamente cuando llegó la alerta. No hay plazo de respuesta; el estado se usa solo para organización interna. ## Cómo funciona 1. El titular abre una disputa con el banco emisor 2. La red de tarjetas avisa de la disputa al proveedor (Ethoca para Mastercard, Verifi RDR para Visa) 3. El proveedor entrega la alerta a Rapid 4. Rapid asocia la alerta a tu empresa por el `descriptor` (Ethoca) o BIN+CAID (Verifi) 5. Rapid entrega la alerta a tu aplicación por webhook 6. Tu aplicación procesa la alerta y (en el caso de Ethoca) devuelve un estado por la API de callback Para recibir alertas, tu empresa necesita: - Un **webhook activo** configurado en el panel (ver [canal Webhook](https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/)) - Al menos un **descriptor registrado** (Ethoca) o **BIN+CAID** (Verifi) asociado a tu empresa ## Proveedores ### Ethoca (Mastercard) Las alertas se asocian a tu empresa por el `descriptor`, el nombre que aparece en el resumen de la tarjeta del titular. Cuando el descriptor de la alerta coincide con uno de los tuyos, la alerta se entrega. ### Verifi RDR (Visa) Las alertas se asocian por BIN + CAID. El plazo y qué responder en cada red de tarjetas están al principio de esta página; el detalle completo, en [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/). ## Próximos pasos - [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/): detalle de plazos por red de tarjetas. - [Canal Webhook](https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/): cómo configurar la entrega. - [Callback de estado](https://doc.rapidchargeback.com/es/callback/visao-geral/): cómo actualizar el estado de la alerta. --- # Reglas y plazos > Los estados de una alerta, el plazo de respuesta de cada red de tarjetas, la conversión de other a account_suspended y cuándo vence la alerta. Página: https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/ ## Estados posibles Toda alerta nace con el estado `pending` y cambia según la respuesta del cliente o el paso del tiempo. ### Estados que puedes enviar por el callback | Estado | Cuándo usarlo | |---|---| | `notfound` | La transacción no se encontró en tu sistema | | `account_suspended` | La transacción se encontró y ya está resuelta (ej.: cuenta suspendida, reembolso hecho) | | `other` | La transacción se encontró, pero todavía no está resuelta | Ver [Actualizar estado](https://doc.rapidchargeback.com/es/callback/atualizar-status/) para los detalles del endpoint. ### Estados visibles en el payload del webhook Además de los tres de arriba que envías tú, el estado de la alerta en el webhook puede aparecer como: | Estado | Significado | |---|---| | `pending` | Estado inicial de toda alerta recibida | | `expired` | Alerta de Ethoca cuyo plazo pasó sin respuesta | --- ## Plazos por proveedor ### Ethoca (Mastercard) **Plazo para responder: 24 horas** desde la recepción. - Debes enviar `notfound`, `account_suspended` u `other` por el [callback](https://doc.rapidchargeback.com/es/callback/atualizar-status/) dentro de ese plazo - Si el plazo pasa sin respuesta, la alerta pasa a `expired` automáticamente. Ethoca lo entiende como inacción y la disputa sigue su curso normal (generalmente se convierte en contracargo). **Conversión `other → account_suspended`: hasta 6 días** - Si enviaste `other` al principio porque todavía estabas investigando, puedes actualizarlo después a `account_suspended` en hasta 6 días desde la alerta original - Es la única transición permitida después de una respuesta inicial **Los estados definitivos no se pueden cambiar:** - `notfound` es definitivo - `account_suspended` es definitivo - `expired` es definitivo ### Verifi RDR (Visa) **Sin plazo obligatorio.** - El adquirente ya hizo el reembolso automáticamente antes incluso de que llegara la alerta - El estado que envías sirve solo para organización interna en el panel - Puedes enviar cualquiera de los tres estados (`notfound`, `account_suspended`, `other`) en cualquier momento --- ## Vencimiento Rapid marca las alertas de Ethoca como `expired` automáticamente después de 24 h sin respuesta. Las alertas de Verifi RDR **no vencen**: quedan disponibles en el panel indefinidamente. --- ## Reenvío Si la entrega del webhook falla, Rapid hace hasta **4 intentos** (1 inicial + 3 reintentos) con intervalos de 5, 15 y 30 minutos (ver [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/)). Si todos los intentos fallan, la alerta sigue disponible en el panel y puedes reenviarla desde ahí (ver [Reenvío manual](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/#reenvío-manual)). Las alertas reenviadas mantienen el mismo `alert_id`, por eso tu aplicación tiene que ser idempotente. --- # Disputa > Cómo Disputa arma y presenta la defensa del contracargo, qué necesita Rapid de ti y el corte de acceso en disputas por fraude. Página: https://doc.rapidchargeback.com/es/produtos/disputa/visao-geral/ **Disputa** es la solución de Rapid para la **defensa automatizada de contracargos**. Mientras [Prevención](https://doc.rapidchargeback.com/es/produtos/prevencao/visao-geral/) responde al banco para que la disputa no se abra y [Alerta](https://doc.rapidchargeback.com/es/produtos/alerta/visao-geral/) avisa antes de que se convierta en contracargo, Disputa actúa después: cuando el contracargo ya entró, Rapid arma y presenta la defensa (*second presentment*) dentro del plazo de la red de tarjetas. La defensa se construye con lo que ya envías: la transacción, las evidencias registradas y las señales capturadas en el checkout. Cuanto más material, mayor la probabilidad de ganar. ## Cómo funciona 1. **Tú** envías la transacción, con el id del cobro en el gateway, y las evidencias de la venta 2. **Gateway** registra el contracargo cuando el titular abre la disputa 3. **Gateway → Rapid** avisa a Rapid al instante, porque tu cuenta del gateway está conectada a Rapid (ver abajo) 4. **Rapid** cruza la disputa con tu transacción por el id del cobro 5. **Rapid → Tú** te avisa por webhook, si el motivo es fraude, para que cortes el acceso del comprador 6. **Rapid** evalúa el caso, arma el dossier con las evidencias y presenta la defensa 7. **Gateway → Rapid** devuelve el resultado, que aparece en el panel Tu trabajo está en los pasos 1 y 5, destacados: el material que envías antes de que todo pase y el corte de acceso. El resto es de Rapid. ## Qué necesita Rapid de ti | Qué | Por qué | Dónde | |---|---|---| | Tu cuenta del gateway de pagos conectada a Rapid | es por donde llega la disputa; sin la conexión, no aparece ninguna disputa | Panel, en **Configuración › Integraciones**: solo autorizar, sin código | | La transacción, con el id del cobro en el gateway | sin ella la disputa llega sin historial y sin evidencias | [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/) | | Evidencias que respalden la venta | son el contenido de la defensa | [Evidencia](https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/) y [Captura](https://doc.rapidchargeback.com/es/canais/capture/visao-geral/) | | Un endpoint para el corte de acceso | lo exigen las reglas de la red de tarjetas | [Webhook](https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/) | El punto que más rompe integraciones es la transacción. La disputa encuentra la transacción por el identificador del cobro en el gateway, así que el campo `transaction_id` (o `external_source` más `external_id`) tiene que llevar ese valor. Una transacción no encontrada significa una defensa sin los datos de autenticación, sin evidencias adjuntas y sin el historial del pedido. ## Corte de acceso en disputas por fraude Cuando la disputa es por fraude, las redes de tarjetas exigen que el comercio intente revocar el producto o servicio entregado y tenga un proceso para evitar la reincidencia. Para eso, Rapid dispara el evento `dispute.fraud.revoke_access` en tu webhook, con las acciones exigidas y el plazo. Es el único punto de Disputa en el que Rapid llama a tu sistema. Trátalo de forma automática si es posible: cuanto más rápido el corte, menor la pérdida. El formato está en [Payload del webhook](https://doc.rapidchargeback.com/es/canais/webhook/payload/#evento-disputefraudrevoke_access). Si la entrega falla, el pendiente aparece en el panel para que alguien de tu equipo lo confirme a mano. ## Situaciones de la disputa | Situación | Qué significa | |---|---| | `received` | llegó y está en evaluación | | `submitted` | defensa enviada al gateway, esperando el resultado | | `won` | disputa ganada | | `lost` | disputa perdida | | `accepted` | el caso no se contestó | | `needs_review` | Rapid no pudo identificar al vendedor y el equipo lo está revisando | No todo contracargo se contesta. Rapid evalúa caso por caso: cuando las reglas de la red de tarjetas no dan derecho a contestar, o cuando el material disponible no sostiene la defensa, el caso se marca como no contestado en vez de gastar el plazo en una presentación perdida. ## Requisitos de configuración - el producto **Disputa** activo en tu empresa - la cuenta de tu gateway de pagos conectada en el panel, en **Configuración › Integraciones** - un webhook activo, si quieres recibir el corte de acceso La conexión del gateway se hace en el panel, sin código: creas una clave restringida en la plataforma de pagos, la pegas en el panel y registras la dirección que el panel muestre. El soporte de Rapid acompaña este paso. ## Próximos pasos - [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/): qué enviar para que la disputa encuentre la transacción - [Visión general de evidencias](https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/): cómo registrar evidencias - [Visión general de captura](https://doc.rapidchargeback.com/es/canais/capture/visao-geral/): cómo capturar señales en el checkout - [Payload del webhook](https://doc.rapidchargeback.com/es/canais/webhook/payload/): el formato del corte de acceso --- # Listar merchants > Lista los merchants de tu empresa, paginado, con el merchant_id que crear transacción y enviar evento de captura requieren. Página: https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/ Lista los merchants (tiendas, marcas o vendedores) de tu empresa. De aquí sale el `merchant_id` que [crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/) y [enviar evento desde el servidor](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) requieren. Solo lectura: registrar y editar merchants se hace en el panel. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/merchants ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Query params Todos opcionales. | Param | Tipo | Default | Descripción | |---|---|---|---| | `page` | int (≥ 1) | `1` | Página | | `per_page` | int (1–100) | `20` | Ítems por página | | `merchant_ref` | string (hasta 100) | - | El ID del vendedor en **tu** sistema, el mismo `merchant_ref` aceptado en [crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/). Devuelve 0 o 1 ítem | | `status` | enum | - | `active` o `inactive` | La lista viene siempre paginada, en orden de registro (el más antiguo primero). Para recorrerlos todos, avanza `page` hasta que `page` llegue a `total_pages`: un merchant registrado en el camino entra al final, sin que saltes ni repitas ítems. --- ## Ejemplos ### Todos los merchants ```bash curl -G "https://api.rapidchargeback.com/api/v1/merchants" \ --data-urlencode "per_page=100" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Por el ID del vendedor en tu sistema ```bash curl -G "https://api.rapidchargeback.com/api/v1/merchants" \ --data-urlencode "merchant_ref=seller-77" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Respuesta ### Éxito ```json { "data": [ { "id": "00000000-0000-0000-0000-000000000001", "name": "Loja Exemplo", "merchant_ref": null, "status": "active", "created_at": "2026-03-10T12:00:00.000Z" } ], "meta": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 } } ``` | Campo | Descripción | |---|---| | `id` | El `merchant_id` que las otras APIs requieren | | `name` | Nombre del merchant en el panel | | `merchant_ref` | El ID del vendedor en tu sistema, cuando el merchant se creó por `merchant_ref`. `null` en los registrados por el panel | | `status` | `active` o `inactive`: la situación del registro en el panel | | `created_at` | Cuándo se registró | Son solo esos campos: los datos de contacto, dirección y términos del merchant quedan en el panel. ### Sin resultados ```json { "data": [], "meta": { "page": 1, "per_page": 20, "total": 0, "total_pages": 0 } } ``` ### Parámetro inválido (ej.: `per_page=500`) ```json { "error": { "code": "VALIDATION_ERROR", "message": "Number must be less than or equal to 100" } } ``` --- ## Notas - **Solo los merchants de tu empresa.** La empresa viene de la credencial; no hay parámetro para elegir otra. - **Una empresa bloqueada** recibe `403 COMPANY_BLOCKED`, como en las otras APIs. - **Auth, rate limit, códigos de error:** ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/) y [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/). --- # Visión general > Envía, consulta, actualiza y elimina las transacciones de venta que alimentan la Prevención y la Disputa, con Basic Auth y JSON. Página: https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/ La API de Transacciones te permite enviar, consultar, actualizar y eliminar las transacciones de venta de tu empresa en la plataforma Rapid. Las soluciones contratadas usan estas transacciones para proteger tu negocio contra disputas y contracargos. ## Cómo funciona 1. Tu aplicación envía las transacciones de venta por HTTPS a la API de Rapid 2. Rapid almacena los datos de la transacción (ítems, cliente, direcciones, pagos, reembolsos) 3. Las soluciones activas usan estos datos automáticamente cuando hace falta ## Endpoints disponibles | Método | Endpoint | Descripción | |---|---|---| | POST | `/api/v1/transactions` | Crear una transacción | | POST | `/api/v1/transactions/batch` | Crear varias transacciones (hasta 1000) | | GET | `/api/v1/transactions/:id` | Consultar una transacción | | GET | `/api/v1/transactions?external_id=` | Encontrar una transacción por el ID de tu sistema | | PATCH | `/api/v1/transactions/:id` | Actualizar una transacción | | DELETE | `/api/v1/transactions/:id` | Eliminar una transacción | ## Base URL ``` https://api.rapidchargeback.com/api/v1 ``` ## Autenticación Todas las solicitudes usan **Basic Auth** con el `client_id` y el `client_secret` generados en el panel. Cómo generarlos y enviarlos está en [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ``` Authorization: Basic base64(client_id:client_secret) ``` ## Límites | Límite | Valor | |---|---| | Solicitudes por minuto | 100 por IP | | Transacciones por solicitud (batch) | 1000 | ## Protección de inmutabilidad Las transacciones que ya fueron usadas por alguna solución (ej.: consultadas por la **Prevención**) no se pueden modificar ni eliminar. En ese caso, la API devuelve `409 Conflict`. Las transacciones que todavía no fueron usadas se pueden actualizar o eliminar libremente. --- # Crear transacción > Crea una única transacción de venta. Para crear varias transacciones a la vez, consulta la página Envío por lotes. Página: https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/ Crea una única transacción de venta. Para crear varias transacciones a la vez, consulta la página [Envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/). ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/transactions ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Campos obligatorios | Campo | Tipo | Descripción | |---|---|---| | `merchant_id` **o** `merchant_ref` | string | Informa **exactamente uno**: `merchant_id` (UUID del merchant en Rapid, debe pertenecer a tu empresa) **o** `merchant_ref` (ID del vendedor en **tu** sistema, hasta 100 caracteres, para canales/plataformas con varios vendedores). Si `merchant_ref` es desconocido, el merchant se **crea** automáticamente con `merchant_name` (opcional, hasta 255 caracteres; se ignora cuando el merchant ya existe). Enviar los dos → `422 VALIDATION_ERROR`. Tus merchants y sus `merchant_id` están en [Listar merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/). | | `external_id` | string | ID de la transacción en el sistema de origen | | `amount` | number | Monto de la transacción (debe ser positivo) | | `currency` | string | Código ISO 4217 con 3 letras mayúsculas (ej.: `USD`, `BRL`) | | `transaction_date` | string | Fecha de la transacción en formato ISO 8601 (ej.: `2026-04-01T15:30:00Z`) | | `card_last4` | string | Últimos 4 dígitos de la tarjeta (exactamente 4 dígitos numéricos) | | `items` | array | Al menos 1 ítem (ver los campos del ítem abajo) | ## Campos del ítem ### Obligatorios | Campo | Tipo | Descripción | |---|---|---| | `product_description` | string | Descripción del producto (hasta 1000 caracteres; por encima de eso la solicitud falla) | | `unit_price` | number | Precio unitario | ### Opcionales | Campo | Tipo | Descripción | |---|---|---| | `product_name` | string | Nombre del producto | | `quantity` | number | Cantidad | | `unit_of_measure` | string | Unidad de medida | | `category` | string | Categoría del producto | --- ## Campos opcionales | Campo | Tipo | Descripción | |---|---|---| | `external_source` | string | Sistema de origen (por defecto: `custom`) | | `order_number` | string | Número de pedido | | `transaction_id` | string | ID de la transacción en el gateway de pago. Ver la nota abajo | | `arn` | string | Acquirer Reference Number | | `banknet_ref` | string | Referencia Banknet (Mastercard) | | `auth_code` | string | Código de autorización | | `network` | string | Red de la tarjeta: `visa`, `mastercard`, `amex`, `discover`, `other` | | `card_bin` | string | BIN de la tarjeta (6 a 8 dígitos numéricos) | | `ip_address` | string | Dirección IP del comprador | | `clearing_datetime` | string | Fecha de compensación (ISO 8601) | | `mcc` | string | Merchant Category Code | | `eci` | string | Electronic Commerce Indicator | | `pos_entry_mode` | string | Modo de entrada POS | | `descriptor` | string | Descriptor de cobro | | `correlation_id` | string | ID de correlación | | `device_id` | string | ID del dispositivo (mín. 15 caracteres) | | `device_fingerprint` | string | Fingerprint del dispositivo (mín. 20 caracteres) | | `customer` | object | Datos del comprador (ver abajo) | | `addresses` | array | Direcciones de envío y/o de facturación (ver abajo) | | `payments` | array | Datos de pago (ver abajo) | | `refunds` | array | Datos de reembolso (ver abajo) | ### Límites de tamaño Todo campo de texto tiene un tope. Por encima de él la respuesta es `422 VALIDATION_ERROR` señalando el campo, nunca un error de servidor. | Límite | Campos | |---|---| | 1000 | `product_description` | | 255 | `descriptor`, `merchant_name`, `product_name`, `device_fingerprint`, `street`, `reason` (refund) | | 200 | `billing_name` | | 100 | `external_id`, `order_number`, `transaction_id`, `arn`, `banknet_ref`, `correlation_id`, `merchant_ref`, `device_id`, `first_name`, `last_name`, `city`, `state`, `category` | | 64 | `method_masked`, `reference_number` | | 45 | `ip_address` (cabe IPv6) | | 50 | `external_source`, `auth_code`, `account_id` | | 32 | `unit_of_measure` | | 30 | `phone`, `postal_code`, `wallet_indicator` | | 20 | `number` (dirección) | | 16 | `payment_type` | | 10 | `mcc`, `pos_entry_mode` | | 7 | `card_expiry` | | 5 | `eci` | | 2 | `cvv2_presence_indicator`, `avs_result` | `email` sigue el límite de 255 y necesita un formato válido. `currency`, `card_bin`, `card_last4`, `country` y `network` tienen formato fijo, descrito en la tabla de campos. ### Nota sobre `transaction_id` Es opcional, pero complétalo siempre que el cobro haya pasado por un gateway de pago: es por este campo que Rapid vincula un contracargo futuro a la transacción. Envía el identificador del cobro en el gateway, no tu número de pedido (ese es el `order_number`). Si usas un gateway cuyas disputas llegan a Rapid y el campo viene vacío, el contracargo igual se recibe, pero sin transacción asociada: sin historial, sin evidencia adjunta y sin los datos de autenticación, que son justamente el material de la defensa. Alternativa equivalente: enviar `external_source` con el nombre del gateway y `external_id` con el id del cobro. --- ## Objeto `customer` (todos opcionales) | Campo | Tipo | Descripción | |---|---|---| | `first_name` | string | Nombre | | `last_name` | string | Apellido | | `email` | string | Correo electrónico (formato válido) | | `billing_name` | string | Nombre en la tarjeta | | `account_id` | string | ID de la cuenta del comprador en tu sistema | | `phone` | string | Teléfono | ## Objeto `address` (dentro del array `addresses`) | Campo | Tipo | Obligatorio | Descripción | |---|---|---|---| | `type` | string | Sí | `shipping` o `billing` | | `street` | string | No | Calle | | `number` | string | No | Número | | `city` | string | No | Ciudad | | `state` | string | No | Estado/Región | | `postal_code` | string | No | Código postal | | `country` | string | No | Código de país ISO 3166-1, 2 o 3 letras mayúsculas (`BR`/`BRA`, `US`/`USA`). Se recomienda alpha-3. | ## Campos de autenticación del pago (raíz, todos opcionales) Insumos de la [protección contra fraude](https://doc.rapidchargeback.com/es/produtos/prevencao/integracao/#para-la-protección-contra-fraude) y de 3-DS. Cuanto más completes, más fuerte la deflexión y la defensa. | Campo | Tipo | Descripción | |---|---|---| | `cvv2_presence_indicator` | string | Indicador de presencia del CVV2 en la autorización | | `cvv2_result` | string | Resultado de la verificación del CVV2: `M`, `N`, `P`, `S`, `U` o `Y`, tal como vino en la respuesta de la autorización | | `avs_result` | string | Resultado del AVS (verificación de dirección) | | `cardholder_verification_approved` | boolean | 3-DS/verificación del titular aprobada | | `authentication_response_type` | string | Tipo de respuesta de la autenticación 3-DS: `attempt` (intento) o `confirm` (autenticación confirmada) | | `wallet_indicator` | string | Billetera digital usada (ej.: Apple Pay, Google Pay) | ### Cuenta del comprador (dentro de `customer`, todos opcionales) Indican si la compra la hizo una cuenta conocida, y desde cuándo existe. Son el material más fuerte de la defensa en una disputa por fraude: un comprador con una cuenta antigua y con sesión iniciada es difícil de disputar como "no lo reconozco". | Campo | Tipo | Descripción | |---|---|---| | `registered_at` | string (ISO 8601) | Cuándo se creó la cuenta del comprador en tu sistema | | `registered_at_source` | string | De dónde viene `registered_at`: `merchant_api` (registro de la cuenta en tu sistema) o `client_declared` (declaración tuya, sin ese registro) | | `account_authenticated` | boolean | El comprador tenía la sesión iniciada en la cuenta al comprar | | `account_authenticated_source` | string | Cómo lo sabes: `per_account` (verificado en esta compra) o `onboarding_flag` (regla de tu tienda, por ejemplo, toda compra exige login) | | `account_authenticated_at` | string (ISO 8601) | Cuándo fue el login | | `auth_method` | string | Cómo entró el comprador: `password`, `otp`, `2fa`, `biometric`, `oauth` u `other` | | `account_source_method` | string | De dónde vienen los datos de la cuenta: `merchant_api` o `client_declared` | | `checkout_type` | string | Cómo se hizo la compra: `guest` (sin cuenta), `authenticated` (cuenta existente, con sesión iniciada) o `registered_at_checkout` (cuenta creada durante la compra) | Un valor fuera de las listas responde `422 VALIDATION_ERROR`. ## Objeto `payment` (todos opcionales) | Campo | Tipo | Descripción | |---|---|---| | `payment_type` | string | Tipo de pago (credit, debit, pix, etc.) | | `method_masked` | string | Número enmascarado | | `matched_payment` | boolean | Si este pago fue el utilizado (por defecto: true) | | `card_bin` | string | BIN (6-8 dígitos) | | `card_last4` | string | Últimos 4 dígitos (4 dígitos numéricos) | | `installments` | integer | Número de cuotas | | `card_expiry` | string | Vencimiento (MM/YYYY) | ## Objeto `refund` | Campo | Tipo | Obligatorio | Descripción | |---|---|---|---| | `amount` | number | Sí | Monto del reembolso (positivo) | | `currency` | string | Sí | Moneda (3 letras mayúsculas, ISO 4217) | | `reference_number` | string | No | Identificador del reembolso | | `reason` | string | No | Motivo del reembolso | | `refund_datetime` | string | No | Fecha del reembolso (ISO 8601) | --- ## Validaciones - `transaction_date` debe estar en ISO 8601 con zona horaria - `currency` debe ser un código ISO 4217 (3 letras mayúsculas) - `amount` debe ser mayor que cero - `card_last4` debe tener exactamente 4 dígitos numéricos - `card_bin` debe tener de 6 a 8 dígitos numéricos - `device_id` debe tener como mínimo 15 caracteres - `device_fingerprint` debe tener como mínimo 20 caracteres - La combinación `external_source + external_id` no puede duplicar una transacción existente de tu empresa ## Warnings La API devuelve avisos (sin bloquear la creación) cuando faltan campos opcionales importantes: | Cuándo | Aviso | |---|---| | Sin `card_bin` | `card_bin missing: reduces match accuracy` | | Sin `order_number` | `order_number missing: recommended to identify the order in dispute responses` | | Sin `ip_address`, `device_id` **y** `device_fingerprint` | `ip_address, device_id and device_fingerprint missing: recommended, fraud protection relies on them` | Basta **uno** de los tres identificadores para que desaparezca el último aviso: la IP no es obligatoria. Y a propósito no hay aviso de dirección: quien vende bienes digitales no debe enviar dirección de envío (ver [protección contra fraude](https://doc.rapidchargeback.com/es/produtos/prevencao/integracao/#bienes-digitales-no-envíes-dirección-de-envío)). La clave `warnings` **solo aparece** en la respuesta cuando hay al menos un aviso. No cuentes con `warnings: []`. --- ## Ejemplo de solicitud Las credenciales vienen de variables de entorno (`RAPID_CLIENT_ID` y `RAPID_CLIENT_SECRET`), nunca escritas en el código. **cURL** ```bash curl -X POST https://api.rapidchargeback.com/api/v1/transactions \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "shopify", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00 } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com" }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ] }' ``` **Node.js** ```javascript const credenciales = Buffer.from(`${process.env.RAPID_CLIENT_ID}:${process.env.RAPID_CLIENT_SECRET}`).toString('base64') const respuesta = await fetch('https://api.rapidchargeback.com/api/v1/transactions', { method: 'POST', headers: { Authorization: `Basic ${credenciales}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ merchant_id: '00000000-0000-0000-0000-000000000001', external_source: 'shopify', external_id: 'TXN-2026-001', transaction_date: '2026-04-01T15:30:00Z', amount: 150.0, currency: 'USD', card_last4: '4242', card_bin: '424242', order_number: 'ORD-001', auth_code: 'AUTH999', network: 'visa', descriptor: 'LOJA EXEMPLO', ip_address: '203.0.113.10', items: [ { product_description: 'Assinatura Premium - Mensal', product_name: 'Plano Premium', quantity: 1, unit_price: 150.0, }, ], customer: { first_name: 'João', last_name: 'Silva', email: 'joao@exemplo.com', }, addresses: [ { type: 'shipping', street: 'Rua das Flores', number: '123', city: 'São Paulo', state: 'SP', postal_code: '01001000', country: 'BRA', }, ], }), }) const cuerpo = await respuesta.json() if (!respuesta.ok) throw new Error(`${respuesta.status} ${cuerpo.error.code}: ${cuerpo.error.message}`) console.log('Transacción creada:', cuerpo.data.id) for (const aviso of cuerpo.warnings ?? []) console.warn('Aviso:', aviso) ``` **Python** ```python import os import requests respuesta = requests.post( "https://api.rapidchargeback.com/api/v1/transactions", auth=(os.environ["RAPID_CLIENT_ID"], os.environ["RAPID_CLIENT_SECRET"]), json={ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "shopify", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00, } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com", }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA", } ], }, timeout=30, ) cuerpo = respuesta.json() if not respuesta.ok: raise RuntimeError(f"{respuesta.status_code} {cuerpo['error']['code']}: {cuerpo['error']['message']}") print("Transacción creada:", cuerpo["data"]["id"]) for aviso in cuerpo.get("warnings", []): print("Aviso:", aviso) ``` **PHP** ```php '00000000-0000-0000-0000-000000000001', 'external_source' => 'shopify', 'external_id' => 'TXN-2026-001', 'transaction_date' => '2026-04-01T15:30:00Z', 'amount' => 150.00, 'currency' => 'USD', 'card_last4' => '4242', 'card_bin' => '424242', 'order_number' => 'ORD-001', 'auth_code' => 'AUTH999', 'network' => 'visa', 'descriptor' => 'LOJA EXEMPLO', 'ip_address' => '203.0.113.10', 'items' => [ [ 'product_description' => 'Assinatura Premium - Mensal', 'product_name' => 'Plano Premium', 'quantity' => 1, 'unit_price' => 150.00, ], ], 'customer' => [ 'first_name' => 'João', 'last_name' => 'Silva', 'email' => 'joao@exemplo.com', ], 'addresses' => [ [ 'type' => 'shipping', 'street' => 'Rua das Flores', 'number' => '123', 'city' => 'São Paulo', 'state' => 'SP', 'postal_code' => '01001000', 'country' => 'BRA', ], ], ]; $ch = curl_init('https://api.rapidchargeback.com/api/v1/transactions'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_USERPWD => getenv('RAPID_CLIENT_ID') . ':' . getenv('RAPID_CLIENT_SECRET'), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode($transaccion), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $crudo = curl_exec($ch); if ($crudo === false) { throw new RuntimeException('Error de red: ' . curl_error($ch)); } $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); $cuerpo = json_decode($crudo, true); if ($status >= 400) { throw new RuntimeException("$status {$cuerpo['error']['code']}: {$cuerpo['error']['message']}"); } echo 'Transacción creada: ', $cuerpo['data']['id'], PHP_EOL; foreach ($cuerpo['warnings'] ?? [] as $aviso) { echo 'Aviso: ', $aviso, PHP_EOL; } ``` --- ## Ejemplos de respuesta ### Éxito ```json { "data": { "id": "00000000-0000-0000-0000-000000000042", "company_id": "...", "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "amount": 150.00, "currency": "USD", "transaction_date": "2026-04-01T15:30:00.000Z", "card_last4": "4242", "created_at": "2026-04-01T15:31:00.000Z", "transaction_items": [...], "transaction_customers": [...], "transaction_addresses": [...] } } ``` ### Duplicado ```json { "error": { "code": "TRANSACTION_DUPLICATE", "message": "Transaction already exists" } } ``` ### Error de validación ```json { "error": { "code": "VALIDATION_ERROR", "message": "card_last4 must be exactly 4 digits" } } ``` --- # Envío por lotes > Crea varias transacciones en una sola solicitud (hasta 1000 por llamada). Página: https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/ Crea varias transacciones en una sola solicitud (hasta 1000 por llamada). Usa el envío por lotes cuando necesitas sincronizar grandes volúmenes (ej.: carga inicial, reprocesamiento de un día entero). El procesamiento es por transacción: el éxito de una no depende del éxito de las demás. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/transactions/batch ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Cuerpo de la solicitud | Campo | Tipo | Descripción | |---|---|---| | `transactions` | array | Lista de transacciones (mín. 1, máx. 1000) | Cada ítem del array sigue el mismo schema de [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/): los mismos campos obligatorios, opcionales y anidados, y las mismas validaciones. --- ## Validaciones - El array `transactions` debe tener entre 1 y 1000 ítems. Un problema **en el envoltorio** (array ausente, vacío o con más de 1000) rechaza la solicitud entera - El cuerpo de la solicitud puede tener hasta **5 MB**, lo que cubre 1000 transacciones con todos los campos completos. Por encima de eso la respuesta es `413 PAYLOAD_TOO_LARGE` y no se crea nada: divídelo en lotes más chicos - Dentro del array, **cada transacción se valida individualmente**: campo inválido, campo obligatorio ausente, texto por encima del límite, duplicado, merchant inexistente. Todo eso se convierte en error de esa línea - Un error en una línea **no** bloquea las demás: las válidas se crean y la respuesta indica cuáles fallaron - Un duplicado dentro del propio lote (mismo `external_source` y `external_id` dos veces) crea la primera y hace fallar la segunda --- ## Ejemplo de solicitud ```bash curl -X POST https://api.rapidchargeback.com/api/v1/transactions/batch \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "transactions": [ { "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "custom", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T10:00:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "items": [{ "product_description": "Item A", "unit_price": 150.00 }] }, { "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "custom", "external_id": "TXN-2026-002", "transaction_date": "2026-04-01T11:00:00Z", "amount": 200.00, "currency": "BRL", "card_last4": "1234", "items": [{ "product_description": "Item B", "unit_price": 200.00 }] } ] }' ``` --- ## Ejemplos de respuesta El lote responde **`200`**, no `201`: en una llamada que crea algunas líneas y falla otras, el estado por sí solo no dice el resultado. Lo dice el cuerpo. Revisa siempre `failed` y `errors`, nunca solo el código HTTP. ### Resultados mixtos (200) ```json { "data": { "created": 1, "failed": 1, "results": [ { "external_id": "TXN-2026-001", "tx_id": "00000000-0000-0000-0000-000000000042", "warnings": ["card_bin missing: reduces match accuracy"] } ], "errors": [ { "index": 1, "external_id": "TXN-2026-002", "status": 409, "error": "Transaction already exists" } ] } } ``` Cada ítem en `results` contiene: - `external_id`: identifica la transacción en tu sistema. - `tx_id`: UUID generado por Rapid (guárdalo para operaciones futuras). - `warnings`: avisos de campos ausentes (no bloquean la creación). Cada ítem en `errors` contiene: - `index`: posición de la línea en el array que enviaste, empezando en cero. Es así como ubicas la línea cuando el campo inválido es justamente el `external_id`. - `external_id`: identifica qué transacción falló, o string vacío si el valor enviado no era válido. - `status`: código HTTP equivalente del error (`422` validación, `404` merchant inexistente, `409` duplicado). - `error`: mensaje descriptivo. `created + failed` es siempre el total de líneas enviadas. `results` y `errors` salen en el orden de entrada. ### Todas creadas con éxito (200) ```json { "data": { "created": 2, "failed": 0, "results": [ { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] }, { "external_id": "TXN-2026-002", "tx_id": "uuid-2", "warnings": [] } ], "errors": [] } } ``` ### Línea con un campo inválido (200) Una línea rechazada en la validación no tumba a las demás: aparece en `errors` con `status: 422`. ```json { "data": { "created": 1, "failed": 1, "results": [ { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] } ], "errors": [ { "index": 1, "external_id": "TXN-2026-002", "status": 422, "error": "Currency must be 3 uppercase letters (ISO 4217)" } ] } } ``` ### Error de validación del batch (fuera del array) Si el array `transactions` está vacío, falta o supera los 1000 ítems, se rechaza la solicitud entera: ```json { "error": { "code": "VALIDATION_ERROR", "message": "Array must contain at most 1000 element(s)" } } ``` --- ## Comportamientos del lote que vale la pena conocer - Un `merchant_ref` **desconocido crea el vendedor** (con `merchant_name`, si se envía) y no devuelve 404. - Un duplicado **dentro del mismo lote** (mismo `external_source`/`external_id` dos veces) falla en la segunda línea con `TRANSACTION_DUPLICATE`; la primera se crea. - El orden de `results` es el orden de entrada. --- # Consultar transacción > Devuelve los datos completos de una transacción, por el ID de Rapid o por el ID de tu sistema, incluyendo ítems, cliente, direcciones, pagos y reembolsos. Página: https://doc.rapidchargeback.com/es/canais/transactions/consultar-transacao/ Devuelve los datos completos de una transacción, incluyendo ítems, cliente, direcciones, pagos y reembolsos. Puedes buscar por el ID que Rapid devolvió en la creación o, si no lo guardaste, [por el ID de tu sistema](#por-el-id-de-tu-sistema). ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/transactions/:id ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Parámetro de URL | Parámetro | Tipo | Descripción | |---|---|---| | `id` | string (UUID) | ID de la transacción | --- ## Ejemplo de solicitud ```bash curl -X GET https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Ejemplos de respuesta ### Éxito ```json { "data": { "id": "00000000-0000-0000-0000-000000000042", "company_id": "00000000-0000-0000-0000-0000000000c1", "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "external_source": "shopify", "order_number": "ORD-001", "auth_code": "AUTH999", "arn": null, "network": "visa", "amount": "150.00", "currency": "USD", "transaction_date": "2026-04-01T15:30:00.000Z", "card_bin": "424242", "card_last4": "4242", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "created_at": "2026-04-01T15:31:00.000Z", "updated_at": "2026-04-01T15:31:00.000Z", "transaction_items": [ { "id": "...", "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": "150.00" } ], "transaction_customers": [ { "id": "...", "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com" } ], "transaction_addresses": [ { "id": "...", "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ], "transaction_payments": [], "transaction_refunds": [] } } ``` ### Transacción no encontrada ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` --- ## Por el ID de tu sistema Si no guardaste el `id` que Rapid devolvió en la creación, encuentra la transacción por el identificador que **tú** enviaste: `external_source` más `external_id`. Es la misma combinación que impide duplicados en la creación, así que la respuesta trae **como máximo una** transacción. ``` GET https://api.rapidchargeback.com/api/v1/transactions?external_source=shopify&external_id=TXN-2026-001 ``` | Param | Tipo | Obligatorio | Descripción | |---|---|---|---| | `external_id` | string (hasta 100) | Sí | El `external_id` enviado en la creación | | `external_source` | string (hasta 50) | No | El `external_source` enviado en la creación. Sin él, vale `custom`, el mismo valor por defecto de la creación | Esto **no** es un listado de transacciones: sin `external_id` la respuesta es `422`. Con el `id` en mano, [actualizar](https://doc.rapidchargeback.com/es/canais/transactions/atualizar-transacao/) y [eliminar](https://doc.rapidchargeback.com/es/canais/transactions/deletar-transacao/) funcionan con normalidad. ### Ejemplo ```bash curl -G "https://api.rapidchargeback.com/api/v1/transactions" \ --data-urlencode "external_source=shopify" \ --data-urlencode "external_id=TXN-2026-001" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Encontrada `200` con una lista de un ítem, en el mismo formato de la consulta por ID: ```json { "data": [ { "id": "00000000-0000-0000-0000-000000000042", "external_source": "shopify", "external_id": "TXN-2026-001", "...": "demás campos, como en la consulta por ID" } ] } ``` ### No encontrada `200` con la lista vacía. Una transacción de otra empresa también vuelve vacía: la búsqueda es siempre dentro de la tuya. ```json { "data": [] } ``` ### Sin `external_id` ```json { "error": { "code": "VALIDATION_ERROR", "message": "external_id is required" } } ``` --- # Actualizar transacción > Actualiza una transacción existente. Todos los campos son opcionales: envía solo lo que quieres cambiar. Página: https://doc.rapidchargeback.com/es/canais/transactions/atualizar-transacao/ Actualiza una transacción existente. Todos los campos son opcionales: envía solo lo que quieres cambiar. Cuando se envían child records (`items`, `addresses`, `payments`, `refunds`, `customer`), **reemplazan por completo** los registros existentes. ## Endpoint ``` PATCH https://api.rapidchargeback.com/api/v1/transactions/:id ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Parámetro de URL | Parámetro | Tipo | Descripción | |---|---|---| | `id` | string (UUID) | ID de la transacción (devuelto en el campo `id` de la respuesta de creación) | ¿No guardaste el `id`? Encuentra la transacción [por el ID de tu sistema](https://doc.rapidchargeback.com/es/canais/transactions/consultar-transacao/#por-el-id-de-tu-sistema). --- ## Campos aceptados Todos los campos aceptados por [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/) se pueden enviar aquí, todos opcionales: - Los campos enviados reemplazan el valor actual - Los campos omitidos mantienen el valor actual - Los child records enviados (`items`, `addresses`, etc.) reemplazan por completo los existentes --- ## Validaciones - Si se cambia `merchant_id`, el nuevo merchant debe pertenecer a tu empresa - Si se cambian `external_id` o `external_source`, la combinación no puede duplicar otra transacción existente - Si la transacción ya fue usada por alguna solución (ej.: consultada por la **Prevención**), la actualización se bloquea con `409 Conflict` --- ## Ejemplo de solicitud ### Actualizar solo el ARN y el auth_code ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "arn": "74537119547024600128228", "auth_code": "AUTH999" }' ``` ### Actualizar ítems (reemplaza todos los ítems existentes) ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "amount": 300.00, "items": [ { "product_description": "Plano Premium", "unit_price": 150.00 }, { "product_description": "Taxa de Setup", "unit_price": 150.00 } ] }' ``` --- ## Ejemplos de respuesta ### Éxito ```json { "data": { "id": "00000000-0000-0000-0000-000000000042", "merchant_id": "00000000-0000-0000-0000-000000000001", "amount": 300.00, "transaction_items": [ { "product_description": "Plano Premium", "unit_price": 150.00 }, { "product_description": "Taxa de Setup", "unit_price": 150.00 } ] } } ``` ### Transacción no encontrada ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` ### Transacción inmutable (ya usada por una solución) ```json { "error": { "code": "TRANSACTION_IMMUTABLE", "message": "Transaction cannot be modified: it has been used by a network event" } } ``` ### Duplicado de external_id ```json { "error": { "code": "TRANSACTION_DUPLICATE", "message": "Another transaction with this external_source/external_id already exists" } } ``` --- # Eliminar transacción > Elimina una transacción y todos sus datos relacionados (ítems, cliente, direcciones, pagos, reembolsos). Página: https://doc.rapidchargeback.com/es/canais/transactions/deletar-transacao/ Elimina una transacción y todos sus datos relacionados (ítems, cliente, direcciones, pagos, reembolsos). ## Endpoint ``` DELETE https://api.rapidchargeback.com/api/v1/transactions/:id ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Parámetro de URL | Parámetro | Tipo | Descripción | |---|---|---| | `id` | string (UUID) | ID de la transacción | ¿No guardaste el `id`? Encuentra la transacción [por el ID de tu sistema](https://doc.rapidchargeback.com/es/canais/transactions/consultar-transacao/#por-el-id-de-tu-sistema). --- ## Validaciones - Si la transacción ya fue usada por alguna solución (ej.: consultada por la **Prevención**), la eliminación se bloquea con `409 Conflict` --- ## Ejemplo de solicitud ```bash curl -X DELETE https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Ejemplos de respuesta ### Éxito ``` HTTP/1.1 204 No Content ``` Sin cuerpo en la respuesta. ### Transacción no encontrada ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` ### Transacción inmutable ```json { "error": { "code": "TRANSACTION_IMMUTABLE", "message": "Transaction cannot be modified: it has been used by a network event" } } ``` --- # Códigos de error > Los estados HTTP y los códigos de error de la API de Transacciones, con los mensajes exactos y el formato de los errores en el envío por lotes. Página: https://doc.rapidchargeback.com/es/canais/transactions/codigos-de-erro/ ## Códigos HTTP | Código | Significado | |---|---| | 200 | Éxito (GET, PATCH, batch) | | 201 | Transacción creada (POST individual) | | 204 | Transacción eliminada (DELETE) | | 401 | Credenciales ausentes o inválidas | | 403 | Empresa bloqueada | | 404 | Transacción o merchant no encontrado | | 409 | Conflicto (duplicado o transacción inmutable) | | 422 | Error de validación (campos inválidos) | | 429 | Demasiadas solicitudes (límite: 100 por minuto por IP) | | 500 | Error interno del servidor | --- ## Formato de las respuestas de error Todas las respuestas de error siguen el mismo formato: ```json { "error": { "code": "ERROR_CODE", "message": "Descripción del error" } } ``` --- ## Códigos de error posibles ### Autenticación | Código | HTTP | Mensaje | |---|---|---| | `UNAUTHORIZED` | 401 | `Missing or invalid Authorization header` | | `UNAUTHORIZED` | 401 | `Invalid Basic Auth format` | | `UNAUTHORIZED` | 401 | `Missing client_id or client_secret` | | `UNAUTHORIZED` | 401 | `Invalid credentials` | | `COMPANY_BLOCKED` | 403 | `Company is blocked` | ### Validación | Código | HTTP | Mensaje | |---|---|---| | `VALIDATION_ERROR` | 422 | Mensaje del validador (ej.: `card_last4 must be exactly 4 digits`) | ### Transacciones | Código | HTTP | Mensaje | |---|---|---| | `TRANSACTION_NOT_FOUND` | 404 | `Transaction not found` | | `TRANSACTION_DUPLICATE` | 409 | `Transaction already exists` | | `TRANSACTION_DUPLICATE` | 409 | `Another transaction with this external_source/external_id already exists` | | `TRANSACTION_IMMUTABLE` | 409 | `Transaction cannot be modified: it has been used by a network event` | | `MERCHANT_NOT_FOUND` | 404 | `Merchant not found` | ### Rate limit | Código | HTTP | Mensaje | |---|---|---| | `RATE_LIMIT_EXCEEDED` | 429 | `Rate limit exceeded, retry in X seconds` | --- ## Errores en el envío por lotes En el endpoint de batch, los errores individuales se devuelven en el array `errors` dentro de `data`, sin interrumpir el procesamiento de las demás transacciones: ```json { "data": { "created": 1, "failed": 2, "results": [ { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] } ], "errors": [ { "index": 1, "external_id": "TXN-2026-002", "status": 409, "error": "Transaction already exists" }, { "index": 2, "external_id": "TXN-2026-003", "status": 404, "error": "Merchant not found" } ] } } ``` Cada error incluye: - `external_id`: identifica qué transacción falló. - `status`: código HTTP equivalente del error. - `error`: mensaje descriptivo. --- # Buenas prácticas > Cómo enviar transacciones de forma confiable: qué enviar, formato de los datos, seguridad de las credenciales, manejo de respuestas e inmutabilidad. Página: https://doc.rapidchargeback.com/es/canais/transactions/boas-praticas/ ## Envío de datos - **Envía todos los campos disponibles.** Cuantos más datos proporciones, mayor es la eficacia de las soluciones contratadas. Campos como `card_bin`, `order_number`, `ip_address` y `addresses` son especialmente importantes. - **Usa el envío por lotes para grandes volúmenes.** En lugar de enviar una transacción por solicitud, agrupa hasta 1000 transacciones en el endpoint `/transactions/batch` para reducir la sobrecarga de red. - **Mantén `external_source` y `external_id` consistentes.** Estos campos se usan para detectar duplicados. Usa identificadores únicos y estables de tu sistema de origen. - **Envía las transacciones lo antes posible.** Cuanto más cerca del momento de la venta, mejor es la cobertura de las soluciones de prevención. ## Formato de los datos - **`transaction_date` en ISO 8601.** Usa el formato completo con zona horaria (ej.: `2026-04-01T15:30:00Z`). - **`currency` en mayúsculas.** Usa el código ISO 4217 de 3 letras mayúsculas (ej.: `USD`, `BRL`, `EUR`). - **`card_last4` como string.** Envíalo como string de exactamente 4 dígitos (ej.: `"0042"`, no `42`). - **`merchant_id` como UUID.** Usa el UUID del merchant tal como lo devuelve la API o el panel. ## Seguridad - **Nunca expongas tu `client_secret`.** Trátalo como una contraseña. No lo incluyas en código frontend, repositorios públicos ni logs. - **Usa siempre HTTPS.** Todas las solicitudes deben hacerse por HTTPS. - **Implementa reintentos con espera progresiva.** Ante un error 500 (error interno), espera antes de intentar de nuevo: 1s, 2s y luego 4s entre intentos. En el `429` no hace falta adivinar: la respuesta trae el header `Retry-After` con los segundos exactos hasta que la ventana se reinicie (ver [Rate limit](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/#rate-limit)). ## Manejo de respuestas - **Transacción única:** revisa el campo `data` para los datos de la transacción creada y `warnings` para los avisos. - **Envío por lotes:** recorre `results` (éxitos con `tx_id` y `warnings`) y `errors` (fallas con `external_id`, `status` y mensaje). - **Presta atención a los `warnings`.** No bloquean la creación, pero indican campos ausentes que afectan la eficacia de las soluciones. - **Guarda el `id` devuelto.** Lo vas a necesitar para consultar, actualizar o eliminar la transacción. ## Inmutabilidad - **Corrige los errores antes de la primera consulta.** Las transacciones usadas por las soluciones (ej.: consultadas por la **Prevención**) se vuelven inmutables. Usa PATCH para corregir datos mientras la transacción todavía no fue usada. --- # Visión general > Cómo Rapid entrega alertas y eventos en tu sistema por webhook HTTPS: registro de la URL, clave de firma y flujo de entrega. Página: https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/ Rapid entrega alertas y eventos al sistema del cliente por **webhook HTTPS POST**. Tu aplicación expone una URL, y Rapid le envía solicitudes cada vez que hay una alerta para notificar. El webhook es el mecanismo universal de entrega. Hoy dos productos usan el canal: - **Alerta**: `chargeback_alert.received`: llegó una alerta nueva. - **Disputa**: `dispute.fraud.revoke_access`: llegó una disputa por fraude y la red de la tarjeta exige cortar el acceso del titular. La URL es una sola; el campo `event` (y el header `X-Webhook-Event`) dice qué evento llegó. Cualquier producto futuro usa el mismo canal. Internamente, los proveedores se identifican por slugs en payloads y respuestas: `ethoca_alerts` (Mastercard) y `verifi_rdr` (Visa). ## Flujo resumido 1. Registras la URL de tu endpoint en el panel de Rapid; Rapid genera la clave de firma y la muestra una sola vez 2. Cuando se recibe una alerta y se asocia a tu empresa, Rapid pone la entrega en cola 3. Rapid hace un `HTTP POST` a tu URL con el payload del evento 4. Tu aplicación valida la firma del header `X-Webhook-Signature`, procesa el evento y devuelve `200` o `204` 5. Si tu aplicación devuelve un error o no responde, Rapid lo intenta de nuevo (ver [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/)) ## Configuración - Cada empresa puede tener **un webhook activo a la vez**. - La clave de firma (`secret`) la genera Rapid en el registro, se muestra **una sola vez** y se usa para validar la firma HMAC-SHA256. ¿La perdiste? Genera otra en **Configuración › API** (la anterior deja de valer al instante). - Si el webhook está inactivo, los eventos se siguen guardando y se ven en el panel, pero no se entregan. Una revocación de acceso no entregada aparece como pendiente en la disputa, para tratamiento manual. ## Próximos pasos - [Payload](https://doc.rapidchargeback.com/es/canais/webhook/payload/): estructura completa del body enviado. - [Autenticación](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/): cómo validar `X-Webhook-Signature`. - [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/): política de reintentos. - [Buenas prácticas](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/): idempotencia, timeout, respuesta rápida. --- # Payload > Los eventos que Rapid envía por webhook: headers, campos de cada cuerpo, ejemplos completos y la diferencia entre los formatos v2 y legacy. Página: https://doc.rapidchargeback.com/es/canais/webhook/payload/ Rapid envía un `HTTP POST` con `Content-Type: application/json` a la URL configurada. El cuerpo es un objeto JSON y el campo `event` (también en el header `X-Webhook-Event`) dice qué pasó. ## Eventos | Evento | Producto | Cuándo se dispara | Cuerpo | |---|---|---|---| | `chargeback_alert.received` | Alerta | Se recibió una alerta y se asoció a tu empresa | [Alerta recibida](#evento-chargeback_alertreceived) | | `dispute.fraud.revoke_access` | Disputa | Llegó una disputa por **fraude** (Visa 10.4 / Mastercard 4837) y la red de la tarjeta exige que cortes el acceso del titular | [Revocación de acceso](#evento-disputefraudrevoke_access) | La misma URL recibe todos los eventos: usa `event` (o el header) para enrutar. Si solo tratas uno de ellos, responde `200` a los demás aunque no los proceses. Hay **dos formatos**, definidos por Rapid en tu cuenta: - **`v2`**: el predeterminado para cuentas nuevas. Descrito en esta página (headers, firma, cuerpo). - **`legacy`**: cuentas migradas del sistema anterior. Mismo cuerpo y headers que el sistema antiguo, **sin firma**. Descrito en la sección [Formato legacy](#formato-legacy) al final de la página. El formato `legacy` vale **solo** para `chargeback_alert.received`: los demás eventos salen siempre en `v2`, incluso en esas cuentas. Para saber o cambiar el formato de tu cuenta, habla con el soporte de Rapid. ## Método y headers (formato `v2`) ``` POST https://tu-sistema.com/webhooks/rapid Content-Type: application/json X-Webhook-Signature: sha256= X-Webhook-Timestamp: 1790000000 X-Webhook-Event: chargeback_alert.received X-Webhook-Reference-Id: ``` - `X-Webhook-Signature`: HMAC-SHA256 de `${X-Webhook-Timestamp}.${body}` con tu clave de firma. Ver [Autenticación](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/). - `X-Webhook-Timestamp`: cuándo firmó Rapid, en segundos desde la epoch. Forma parte de la firma (anti-replay) y debe verificarse contra una ventana de tolerancia de 5 minutos. - `X-Webhook-Event`: tipo del evento (ver [Eventos](#eventos)). Úsalo para enrutar. - `X-Webhook-Reference-Id`: ID de referencia del evento: `alert_id` en `chargeback_alert.received`, `dispute_id` en `dispute.fraud.revoke_access`. Permite deduplicar sin parsear el body. > Los headers `clientid`/`clientkey` **no** se envían en el formato `v2`: lo que autentica la entrega es la firma. Siguen enviándose solo en el formato `legacy` (ver [Formato legacy](#formato-legacy)). --- ## Evento `chargeback_alert.received` ### Estructura del cuerpo | Campo | Tipo | Descripción | Obligatorio | |---|---|---|---| | `event` | string | `chargeback_alert.received` | Sí | | `alert_id` | string (UUID) | ID único de la alerta en Rapid; úsalo para llamar a los endpoints de consulta y actualización de estado | Sí | | `provider_alert_id` | string | ID de la alerta en el sistema del proveedor. Útil como referencia cruzada si tratas directamente con el soporte del proveedor | Sí | | `provider` | string | Origen de la alerta: `ethoca_alerts` o `verifi_rdr` | Sí | | `amount` | number \| null | Monto de la transacción disputada (puede venir `null` cuando el proveedor no lo informa) | Sí | | `currency` | string | Código ISO 4217 con 3 letras mayúsculas | Sí | | `card_last4` | string | Últimos 4 dígitos de la tarjeta | Sí | | `card_bin` | string | BIN de la tarjeta (6-8 dígitos) | Sí | | `transaction_date` | string | Fecha de la transacción original (ISO 8601, `"2026-04-01T00:00:00.000Z"`) | Sí | | `descriptor` | string | Nombre que aparece en el resumen del titular | Sí | | `arn` | string | Acquirer Reference Number | No | | `caid` | string | Card Acceptor ID | No | | `auth_code` | string | Código de autorización de la transacción | No | | `alert_type` | string | Tipo de alerta (ej.: `fraud`, `dispute`) | No | | `reason_code` | string | Código del motivo de la disputa | No | | `issuer` | string | Banco emisor de la tarjeta | No | | `installment_number` | number \| null | Cuota actual | No | | `installment_count` | number \| null | Total de cuotas | No | | `status` | string | Estado inicial de la alerta. Siempre `pending` al recibirla | Sí | | `received_at` | string | Cuándo Rapid recibió la alerta (ISO 8601) | Sí | | `expires_at` | string \| null | Plazo de respuesta (ISO 8601), solo para Ethoca | No | | `merchant` | object \| null | Datos del merchant asociado (ver abajo); `null` si la alerta todavía no se asoció | Sí | #### Objeto `merchant` | Campo | Tipo | Descripción | |---|---|---| | `id` | string (UUID) | ID del merchant en Rapid | | `name` | string | Nombre del merchant | --- ### Ejemplo de payload ```json { "event": "chargeback_alert.received", "alert_id": "00000000-0000-0000-0000-000000000099", "provider_alert_id": "2UBOD4MKAI42RPXEYU4UVQPS", "provider": "ethoca_alerts", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "transaction_date": "2026-04-01T00:00:00.000Z", "descriptor": "LOJA EXEMPLO", "arn": "74537119547024600128228", "caid": "123456789", "auth_code": "123456", "alert_type": "fraud", "reason_code": "4853", "issuer": "Chase Bank", "installment_number": null, "installment_count": null, "status": "pending", "received_at": "2026-04-14T10:00:00Z", "expires_at": "2026-04-15T10:00:00Z", "merchant": { "id": "00000000-0000-0000-0000-000000000001", "name": "Minha Loja" } } ``` --- ## Evento `dispute.fraud.revoke_access` Se dispara cuando Rapid recibe una disputa por **fraude**. Las redes de tarjetas exigen que el comercio intente revocar el producto o servicio entregado al titular y tenga un proceso para evitar la reincidencia (Visa Core Rules §10.4.4.3). Cuanto más rápido el corte, menor la pérdida: trata este evento de forma automática si es posible. El campo `merchant` dice **cuál de tus tiendas** hizo la venta: la entrega siempre va al webhook único de la empresa, y tú enrutas internamente. ### Estructura del cuerpo | Campo | Tipo | Descripción | Obligatorio | |---|---|---|---| | `event` | string | `dispute.fraud.revoke_access` | Sí | | `dispute_id` | string (UUID) | ID de la disputa en Rapid. Úsalo como clave de idempotencia; la disputa aparece en el panel, en Disputas | Sí | | `merchant` | object \| null | Tienda asociada (`id`, `name`); `null` si la disputa todavía no se asoció | Sí | | `network` | string | Red de la tarjeta: `visa`, `mastercard`, … | Sí | | `condition` | string \| null | Condición o motivo de la red (ej.: `10.4`, `4837`) | No | | `transaction_id` | string \| null | ID de la transacción en la red, cuando lo informa el adquirente | No | | `customer_ref` | string \| null | Identificador del cliente que enviaste en la transacción (`account_id`), cuando existe | No | | `order_ref` | string | Referencia del pedido: número de pedido, tu ID externo o, si no hay ninguno, el `dispute_id` | Sí | | `reason` | string | Siempre `fraud_dispute_received` | Sí | | `is_account_takeover` | boolean | `true` cuando hay indicios de cuenta tomada (dispositivo e IP difieren del historial del cliente) | Sí | | `required_actions` | string[] | Acciones exigidas: `revoke_access`, `prevent_reoccurrence` y, en cuenta tomada, `re_authenticate` | Sí | | `citation` | object | Regla que fundamenta la exigencia (`section`, `visa_id`, `page`, `quote_en`, `ruleset_version`) | Sí | | `emitted_at` | string | Cuándo Rapid emitió el evento (ISO 8601) | Sí | | `deadline_hint` | string | Plazo de respuesta de la disputa (ISO 8601) o `as_soon_as_possible` cuando no hay plazo conocido | Sí | ### Ejemplo de payload ```json { "event": "dispute.fraud.revoke_access", "dispute_id": "00000000-0000-0000-0000-0000000000d1", "merchant": { "id": "00000000-0000-0000-0000-000000000001", "name": "Minha Loja" }, "network": "visa", "condition": "10.4", "transaction_id": "ch_3Qx0000000", "customer_ref": "acct-8842", "order_ref": "PED-5078", "reason": "fraud_dispute_received", "is_account_takeover": false, "required_actions": ["revoke_access", "prevent_reoccurrence"], "citation": { "section": "10.4.4.3", "visa_id": "0030642", "page": 634, "quote_en": "An Acquirer must ensure that its Merchant attempts to revoke provision of goods or services from the Cardholder after a Dispute category 10 (Fraud) Dispute and that the Merchant has a process in place to prevent reoccurrence by the Cardholder.", "ruleset_version": "visa-core-rules-2026-04-18" }, "emitted_at": "2026-09-30T14:25:00.000Z", "deadline_hint": "2026-10-14T14:20:00.000Z" } ``` ### Confirmar lo que hiciste (opcional) Responder `200` ya cierra la entrega. Si quieres registrar lo que se hizo, devuelve en el cuerpo un JSON con los campos de abajo. Aparece en el panel, en la disputa, como confirmación de tu integración. Una clave desconocida invalida todo el cuerpo (la entrega sigue siendo válida, solo no registra la confirmación). | Campo | Tipo | Descripción | |---|---|---| | `status` | string | `done`, `partial`, `refused`, `not_applicable` o `accepted` | | `actions_taken` | string[] | Cuáles de las `required_actions` ejecutaste | | `revoked_at` | string | Cuándo se cortó el acceso (ISO 8601) | | `note` | string | Observación libre, hasta 500 caracteres | ```json { "status": "done", "actions_taken": ["revoke_access", "prevent_reoccurrence"], "revoked_at": "2026-09-30T14:25:03Z", "note": "cuenta suspendida y tarjeta bloqueada para nuevas compras" } ``` **Idempotencia:** Rapid emite **un** evento por disputa (`dispute_id` es único). Los reintentos repiten el mismo `dispute_id`, así que trátalo por la clave en lugar de contar llamadas. Si no logramos entregarlo, la disputa aparece en el panel con la revocación pendiente, y el cliente la confirma manualmente ahí. --- ## Respuesta esperada Tu aplicación debe devolver uno de los siguientes códigos para confirmar la recepción: | Código | Significado | |---|---| | `2xx` | Éxito. `200`, `201`, `202` y `204` valen lo mismo; el cuerpo es opcional | Cualquier otro código (incluidos `4xx` y `5xx`) se trata como falla y dispara un reintento. Registra la URL final: un `301`, `302` o `303` en tu URL cuenta como falla (ver [Redirección](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/#redirección)). Ver [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/). En `dispute.fraud.revoke_access`, el cuerpo del `200` puede traer la confirmación de lo que ejecutaste (ver [arriba](#confirmar-lo-que-hiciste-opcional)). En los demás eventos el cuerpo se ignora. --- ## Campos que pueden evolucionar Se pueden agregar campos nuevos al payload en el futuro. Tu aplicación debe **ignorar los campos desconocidos** en lugar de fallar. Nunca modifiques ni elimines campos al procesar; solo léelos. --- ## Formato legacy Las cuentas migradas del sistema anterior reciben el **mismo POST de antes**. Headers: `Content-Type: application/json`, `x-source: rapid`, `clientid`, `clientkey`, y **sin** `X-Webhook-Signature`, `X-Webhook-Event` ni `X-Webhook-Reference-Id`. | Campo | Tipo | Descripción | |---|---|---| | `alert_id` | string | **ID de la alerta en el proveedor** (no es el UUID de Rapid). Es el valor a usar en `POST /chargeback-alert/get` y en el alias `POST /chargeback-alert/update/status` | | `merchant` | string | Nombre del merchant | | `provider` | string | `ethoca` o `verifi-rdr` | | `descriptor` | string | Nombre en el resumen del titular | | `transaction_date` | string | Fecha de la transacción (ISO 8601) | | `currency` | string | ISO 4217 | | `amount` | number \| null | Monto de la transacción | | `card_number` | string \| null | `BIN******LAST4`, o `null` cuando el proveedor no informó BIN ni últimos dígitos | | `created_at` | string | Cuándo Rapid recibió la alerta | | `arn` | string \| null | Acquirer Reference Number | | `authorization_code` | string \| null | Código de autorización | | `issuer` | string \| null | Banco emisor | | `type` | string \| null | Tipo de alerta | | `global` | boolean | `true` para alerta internacional | | `reason_code`, `status_code`, `mcc`, `tier`, `caid` | string \| null | Campos del proveedor, cuando existen | | `installment_number`, `total_installment_count` | number \| null | Cuotas | No hay campo `event`, `status` ni `expires_at` en este formato. Reintentos, timeout y logs son los mismos que en `v2`. --- # Autenticación > Cómo validar la firma HMAC-SHA256 de los webhooks de Rapid, con protección contra replay y ejemplos listos en Node.js, Python y PHP. Página: https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/ En el formato **`v2`**, Rapid firma cada webhook con **HMAC-SHA256** usando tu clave de firma (el `secret`). Rapid **genera** esa clave cuando registras el webhook y la muestra **una sola vez** en el panel, en **Configuración › Webhook**; guárdala en el momento. No hay forma de recuperarla después: si la pierdes, genera otra en **Configuración › API** (la anterior deja de valer en ese mismo instante). Tu aplicación debe validar esta firma antes de procesar el payload; así confirmas que el POST vino de Rapid. > Las cuentas en formato **`legacy`** (migradas del sistema anterior) **no reciben firma**: la autenticación se hace por los headers `clientid`/`clientkey`, como antes. Mira cuál es tu formato en [Payload](https://doc.rapidchargeback.com/es/canais/webhook/payload/). ## Header de firma ``` X-Webhook-Signature: sha256= ``` Donde `` es el HMAC-SHA256, en hexadecimal, de la cadena `${timestamp}.${cuerpo_crudo}`, es decir, el valor del header `X-Webhook-Timestamp` (segundos desde la epoch), un punto y el **cuerpo crudo de la solicitud** (el JSON recibido, byte a byte), usando tu clave de firma. El timestamp forma parte de la firma para dar **protección contra replay**: sin él, un POST válido capturado podría reenviarse indefinidamente con una firma correcta. Rechaza las solicitudes cuyo `X-Webhook-Timestamp` esté fuera de una ventana de tolerancia (recomendamos **5 minutos**). --- ## Cómo validar 1. Lee el cuerpo crudo de la solicitud. **No lo parsees como JSON antes de validar**: la firma se calcula sobre los bytes exactos recibidos. 2. Arma `signed = timestamp + "." + raw_body`, calcula `HMAC-SHA256(secret, signed)` y codifícalo en hexadecimal 3. Compáralo con el valor de `X-Webhook-Signature` (después del prefijo `sha256=`) 4. Usa una comparación timing-safe para evitar timing attacks ### Ejemplos Un endpoint completo en cada lenguaje: lee el cuerpo crudo, valida la firma y la ventana de tiempo, y solo entonces lee el JSON. Responde `401` a cualquier entrega que no pase, incluso sin los headers. La clave viene de la variable de entorno `RAPID_WEBHOOK_SECRET`. **Node.js** ```javascript import crypto from 'node:crypto' import express from 'express' const TOLERANCIA_SEGUNDOS = 5 * 60 function validarFirma(cuerpoCrudo, firma, timestamp, secret) { // 1. Ventana de tolerancia (anti-replay). Sin esto, un POST antiguo capturado // sigue pasando para siempre. const antiguedad = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp)) if (!Number.isFinite(antiguedad) || antiguedad > TOLERANCIA_SEGUNDOS) return false // 2. Firma `timestamp.cuerpo_crudo` (el cuerpo recibido, sin reserializar). const esperada = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${cuerpoCrudo}`).digest('hex') const a = Buffer.from(esperada) const b = Buffer.from(firma ?? '') return a.length === b.length && crypto.timingSafeEqual(a, b) } const app = express() // express.raw, y no express.json: la firma se calcula sobre el cuerpo crudo. app.post('/webhooks/rapid', express.raw({ type: 'application/json' }), (req, res) => { const cuerpoCrudo = req.body.toString('utf8') const ok = validarFirma( cuerpoCrudo, req.get('X-Webhook-Signature'), req.get('X-Webhook-Timestamp'), process.env.RAPID_WEBHOOK_SECRET, ) if (!ok) return res.status(401).end() const evento = JSON.parse(cuerpoCrudo) // Procesa el `evento` (preferentemente en una cola) y responde rápido. res.status(200).end() }) app.listen(process.env.PORT ?? 3000) ``` **Python** ```python import hashlib import hmac import os import time from flask import Flask, request TOLERANCIA_SEGUNDOS = 5 * 60 def validar_firma(cuerpo_crudo: bytes, firma: str, timestamp: str, secret: str) -> bool: # 1. Ventana de tolerancia (anti-replay). try: antiguedad = abs(int(time.time()) - int(timestamp)) except (TypeError, ValueError): return False if antiguedad > TOLERANCIA_SEGUNDOS or not firma: return False # 2. Firma `timestamp.cuerpo_crudo` (los bytes recibidos, sin reserializar). firmado = timestamp.encode() + b"." + cuerpo_crudo esperada = "sha256=" + hmac.new(secret.encode(), firmado, hashlib.sha256).hexdigest() return hmac.compare_digest(esperada.encode(), firma.encode()) app = Flask(__name__) @app.post("/webhooks/rapid") def webhook_rapid(): # get_data(), y no get_json(): la firma se calcula sobre el cuerpo crudo. cuerpo_crudo = request.get_data() ok = validar_firma( cuerpo_crudo, request.headers.get("X-Webhook-Signature", ""), request.headers.get("X-Webhook-Timestamp", ""), os.environ["RAPID_WEBHOOK_SECRET"], ) if not ok: return "", 401 evento = request.get_json() # Procesa el `evento` (preferentemente en una cola) y responde rápido. return "", 200 ``` **PHP** ```php TOLERANCIA_SEGUNDOS) { return false; } // 2. Firma `timestamp.cuerpo_crudo` (los bytes recibidos, sin reserializar). $esperada = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $cuerpoCrudo, $secret); return hash_equals($esperada, $firma); } // php://input, y no json_decode antes: la firma se calcula sobre el cuerpo crudo. $cuerpoCrudo = file_get_contents('php://input'); $ok = validarFirma( $cuerpoCrudo, $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '', $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '', getenv('RAPID_WEBHOOK_SECRET') ); if (!$ok) { http_response_code(401); exit; } $evento = json_decode($cuerpoCrudo, true); // Procesa el $evento (preferentemente en una cola) y responde rápido. http_response_code(200); ``` ## Verificador de firma ¿Tu validación no coincide? Pega aquí lo que recibiste y compáralo con la firma esperada. --- ## Rotación del secret Tú mismo generas una clave nueva en el panel, en **Configuración › API**. Aparece una sola vez, y a partir de ahí los webhooks ya salen firmados con ella, **sin período de superposición**: quien valide con la anterior empieza a rechazar. Cambia la clave en tus servidores enseguida, de preferencia en una ventana de poco tráfico. Guardar una **URL** nueva no cambia la clave. --- ## Headers heredados En el formato `legacy`, Rapid envía los headers `clientid` y `clientkey` y **no** envía firma, exactamente como el sistema anterior. ``` clientid: clientkey: ``` En el formato `v2` estos headers **no existen**: validar por `clientid`/`clientkey` significaría recibir la credencial de acceso a la API en cada solicitud (menos seguro que firmar el payload), así que la autenticación de la entrega es solo `X-Webhook-Signature`. Quien está en `legacy` sigue recibiendo los headers por tiempo indefinido, para no romper integraciones existentes. --- # Reintentos y logs > Cuándo Rapid intenta entregar el webhook de nuevo, en qué intervalos, qué cuenta como éxito y cómo leer el log de entregas. Página: https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/ ## Política de reintentos Si tu aplicación responde con cualquier código distinto de `2xx`, o no responde dentro del timeout, Rapid considera el intento como fallido y vuelve a enviar el webhook. Son **4 intentos** en total: el inicial y 3 más, cada uno esperando más que el anterior. 1. **En el momento** 1.er intento, apenas el evento entra en la cola 2. **+5 min** 2.º intento, 5 minutos después de la falla anterior (5 minutos desde el inicio) 3. **+15 min** 3.er intento (20 minutos desde el inicio) 4. **+30 min** 4.º y último intento (50 minutos desde el inicio) Si el 4.º también falla, la entrega se cierra y la alerta queda disponible en el panel para acción manual (ver [Reenvío manual](#reenvío-manual)). ## Timeout Cada intento tiene un **timeout de 30 segundos**. Si tu aplicación no responde en ese plazo, el intento se considera fallido. ## Qué cuenta como éxito Cualquier código **`2xx`**: `200`, `201`, `202`, `204` y los demás del rango. El cuerpo de la respuesta es opcional. Cualquier otro código (incluidos `4xx` y `5xx`) dispara un reintento. ### Redirección Registra la **URL final**. Rapid trata las redirecciones así: | Respuesta de tu URL | Qué pasa | |---|---| | `301`, `302`, `303` | **Falla.** Estos códigos cambian el POST por `GET` y descartan el cuerpo, así que seguirlos sería no entregar nada. El intento entra en el flujo de reintentos y el log muestra hacia dónde redirige tu URL. | | `307`, `308` al **mismo** dominio | Se sigue, con el POST, el cuerpo y los headers intactos. Hasta 3 redirecciones seguidas. | | `307`, `308` a **otro** dominio | **Falla.** El payload firmado no sale del dominio que registraste. | Los casos comunes son que el servidor agregue `/` al final de la ruta y que cambie de dominio, como de `ejemplo.com` a `www.ejemplo.com` (que cuenta como otro dominio). En el log de entregas, el motivo empieza con `[redirecionamento]`, junto con la dirección de destino. ## Dirección que no es pública Si la dirección registrada no resuelve a una dirección pública de internet (apunta a una red local o privada, o el dominio no existe), la entrega **falla sin ninguna solicitud** y entra en el flujo normal de reintentos. En el log de entregas, el motivo empieza con `[destino]`. Corrige la URL o el DNS del dominio; ver [Usa una dirección pública de internet](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/#usa-una-dirección-pública-de-internet). Si el motivo empieza con `[https]`, la URL registrada no usa HTTPS y Rapid no entrega en texto plano: registra una URL `https://`. Si el motivo empieza con `[assinatura]`, la falla es del lado de Rapid: la entrega no sale sin firma, y se reintenta automáticamente. No hace falta hacer nada en tu sistema. ## Empresas bloqueadas Si la empresa está bloqueada por falta de pago en Rapid, **el flujo de webhooks sigue normal**: las alertas se siguen recibiendo de los proveedores, guardando y entregando a la URL configurada. El panel sigue disponible. Lo que el bloqueo corta es la **API por credencial** (lectura y escritura: `GET/PATCH /chargeback-alert/alerts`, transacciones, merchants, alias heredados), que pasa a responder `403 COMPANY_BLOCKED`, y la defensa de nuevas disputas. Para dejar de recibir alertas nuevas, hay que desactivar el registro directamente en el proveedor (acción que realiza el equipo de Rapid). ## Logs de entrega Cada intento se registra internamente con: - Evento entregado (`chargeback_alert.received`, `dispute.fraud.revoke_access`) - Fecha y hora del intento - URL de destino - Código HTTP de la respuesta - Cuerpo de la respuesta (truncado en 1000 caracteres) - Número del intento Ves estos registros en el panel de Rapid en dos lugares: en **Configuración › Webhook**, en el **Historial de entregas**, las entregas más recientes; en **Actividad**, pestaña **Webhooks**, el historial completo para depurar fallas. Cuando la falla no llegó a tu servidor, el panel muestra una explicación del motivo; el texto original, que empieza con `[https]`, `[destino]`, `[redirecionamento]` o `[assinatura]`, aparece al pasar el mouse. ## Reenvío manual Cuando todos los intentos automáticos fallan, la alerta sigue en el panel. Para enviarla de nuevo, usa el botón **Reintentar** en el **Historial de entregas**, en **Configuración › Webhook**. La entrega reenviada llega como un webhook nuevo con el mismo `alert_id`, por eso la [idempotencia](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/#idempotencia) es esencial. El reenvío desde el panel vale para alertas. El evento `dispute.fraud.revoke_access` no tiene reenvío manual. --- # Buenas prácticas > Lo que un endpoint de webhook necesita hacer: validar la firma, responder rápido, ser idempotente, usar HTTPS y una dirección pública. Página: https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/ ## Valida la firma antes que nada Calcula y verifica `X-Webhook-Signature` **antes** de parsear el JSON o tocar la base de datos. Toda solicitud con firma inválida debe descartarse. Ver [Autenticación](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/). ## Responde rápido Devuelve `200` o `204` lo antes posible, idealmente en menos de 1 segundo. Si necesitas procesar la alerta (ej.: actualizar la base, llamar a la API del gateway), hazlo de forma asíncrona después de responder. El timeout es de 30 segundos por intento. Cualquier demora consume ese margen y puede disparar un reintento innecesario. ## Idempotencia Rapid puede volver a enviar la misma alerta: - Cuando el intento anterior falló (reintento automático) - Cuando alguien de tu equipo reenvía la entrega desde el panel - En casos raros de falla de red entre la respuesta de tu servidor y la confirmación del lado de Rapid Tu procesamiento debe ser **idempotente por `alert_id`**: 1. Al recibir un webhook, verifica si ya existe un registro con ese `alert_id` en tu sistema 2. Si existe, devuelve `200` de inmediato y no lo proceses de nuevo 3. Si no existe, procésalo y guárdalo ## Ignora los campos desconocidos El payload puede evolucionar con campos nuevos. Tu deserialización debe **tolerar campos extra** en lugar de fallar. Nunca elimines ni modifiques campos al procesar. ## Devuelve 200 incluso con error de validación Si el payload llega pero no puedes procesarlo (ej.: el merchant no existe de tu lado), **igual devuelve 200**. Devolver un error dispara un reintento inútil. Registra la falla de tu lado (log, alerta interna, cola de errores) y trátala offline. ## Usa siempre HTTPS La URL del webhook tiene que ser `https://`: el panel no permite guardar una URL `http://`, y Rapid no entrega por HTTP plano. La firma prueba que la solicitud vino de Rapid, pero no cifra el contenido, y el payload lleva datos de la tarjeta (BIN y últimos 4 dígitos) y de la compra. ## Usa una dirección pública de internet La URL tiene que apuntar a un servidor accesible desde internet. Rapid no entrega en una dirección de red local o privada: `localhost`, `127.0.0.1`, `10.x`, `172.16.x` a `172.31.x`, `192.168.x` y sus equivalentes en IPv6. El panel ya rechaza esas direcciones en el registro, y un nombre de dominio que resuelva a una de ellas falla en el momento de la entrega. Para probar la integración en tu máquina, expón el servidor local con un túnel HTTPS (como ngrok o Cloudflare Tunnel) y registra la dirección pública que genera. ## Protege el secret El `secret` usado para validar `X-Webhook-Signature` debe tratarse como una credencial sensible: - No lo subas a un repositorio - No lo registres en logs - Guárdalo en una variable de entorno o en un gestor de secretos ## Monitoreo Recomendamos instrumentar: - Tasa de webhooks recibidos (si cae, algo puede estar mal en Rapid o en la red) - Tasa de firmas inválidas (si sube, puede indicar una rotación de secret no propagada o un intento de falsificación) - Latencia de procesamiento (para asegurar que quede por debajo del timeout de 30 s) - Tasa de reintentos entregados (indica problemas de tu lado) --- # Visión general > Cómo Rapid registra, en el momento en que ocurren, las señales que respaldan una venta: aceptación de términos, dispositivo, acceso, entrega y uso. Página: https://doc.rapidchargeback.com/es/canais/capture/visao-geral/ La captura registra, en el momento en que ocurren, las señales que respaldan una venta: la aceptación de los términos en el checkout, el dispositivo usado en la compra, el acceso al producto, la confirmación de entrega, el uso del servicio. Son dos canales para lo mismo, y puedes usar los dos juntos: | Canal | Quién llama | Autenticación | |---|---|---| | **Navegador** | el snippet en tu checkout, o tu propio código | token publicable en la URL | | **Servidor** | tu backend | Basic Auth, igual que las otras APIs | ## Flujo resumido 1. Activas el SDK de captura en el panel y recibes el token publicable del merchant 2. [Instalas el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) en el checkout, o llamas al endpoint directamente 3. Con cada hecho relevante, envías un evento con el `order_ref` del pedido 4. Rapid correlaciona el evento con la transacción y guarda el registro 5. Si esa transacción se convierte en disputa, los registros entran en la defensa ## Cómo el evento se convierte en evidencia El evento **no** se adjunta a nada en el momento en que llega. Entra en una cola y solo se convierte en evidencia cuando coincide con una transacción real del merchant dueño del token, por el campo `order_ref`. Esto tiene una consecuencia práctica que vale la pena entender: un token filtrado genera ruido, nunca datos. Quien tenga tu token publicable puede enviar eventos, pero mueren en la cola si no corresponden a un pedido tuyo de verdad. Por eso: - enviar un evento antes de que exista la transacción es normal, la correlación ocurre después, dentro de una ventana de unas 68 horas - `order_ref` tiene que ser el mismo identificador que usas en la transacción (`external_id`) - la respuesta de éxito es `202 Accepted`, no `201`: Rapid aceptó el evento, el procesamiento es asíncrono - un `order_ref` equivocado no devuelve error. El evento se acepta y se descarta después, en silencio ## Diferencia entre captura y evidencia | | Captura | [Evidencia](https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/) | |---|---|---| | Cuándo usar | en el momento del hecho, sin saber si se convierte en disputa | cuando ya tienes la transacción en Rapid | | Referencia | `order_ref` (tu identificador) | `transaction_id` o `transaction_ref` | | La transacción debe existir | no | sí, si no `404` | | Campos del payload | lista cerrada | formato libre, tope de 32 KB | | Respuesta | `202`, asíncrono | `201`, ya guardado | ## Autenticación - **Navegador:** el token va en la URL (`/capture/{token}/events`). Es publicable, puede quedar en el HTML. - **Servidor:** Basic Auth con `client_id:client_secret`. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). El token de la captura se genera en el panel, en **Configuración › Integraciones**, al activar el SDK de captura del merchant. ## Endpoints | Endpoint | Canal | Qué hace | |---|---|---| | [`POST /capture/{token}/events`](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) | navegador | Envía un evento del checkout | | [`POST /capture/events`](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) | servidor | Envía un evento desde tu backend | | [`GET /capture/{token}/config`](https://doc.rapidchargeback.com/es/canais/capture/config-do-snippet/) | navegador | Configuración que el snippet lee al cargar | ## Próximos pasos - [Instalar el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) - [Tipos y payload](https://doc.rapidchargeback.com/es/canais/capture/payload/) - [Enviar evento desde el navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) - [Enviar evento desde el servidor](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) --- # Instalar el snippet > El snippet es la forma más corta de capturar evidencia: dos tags en tu checkout y una llamada por evento. Se comunica con el canal navegador por ti. Página: https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/ El snippet es la forma más corta de capturar evidencia: dos tags en tu checkout y una llamada por evento. Se comunica con el [canal navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) por ti. Si tu checkout se renderiza en el servidor, o si prefieres no cargar un script de terceros, salta esta página y llama al endpoint directamente. ## Dónde obtener el token En el panel, en **Configuración › Integraciones**, en la tarjeta del SDK de captura. Actívalo y el panel muestra el snippet listo, ya con el token del merchant seleccionado. La tarjeta aparece para quien tiene el producto de disputa activo. El token es **publicable**: queda en el HTML de tu tienda y no necesita protección. Con él solo se pueden enviar eventos, nunca leer datos. Un evento que no corresponde a un pedido tuyo se descarta. ## Instalación ```html ``` Dos cosas importan en el orden de arriba: 1. el `init` tiene que venir después de la carga del script, por eso el tag no lleva `async` ni `defer` 2. el `init` ya empieza a identificar el dispositivo, así que llámalo lo antes posible en la página, no solo en el momento del pago El script pesa unos 5 KB, no tiene dependencias y no bloquea la página. ## Llamadas ```js // Compra finalizada. También captura los datos del dispositivo. rapid('checkout', { order_ref: 'TXN-2026-001' }) // El cliente aceptó los términos. rapid('terms', { order_ref: 'TXN-2026-001' }) // El cliente accedió al producto. rapid('track', 'access_log', { order_ref: 'TXN-2026-001' }) // El cliente usó el producto o servicio. rapid('track', 'usage_log', { order_ref: 'TXN-2026-001' }) ``` | Llamada | Evento generado | Payload que arma el snippet | |---|---|---| | `rapid('checkout', …)` | `checkout` | identificación del dispositivo | | `rapid('terms', …)` | `terms_acceptance` | la URL de la página | | `rapid('track', 'access_log', …)` | `access_log` | la URL de la página | | `rapid('track', 'usage_log', …)` | `usage_log` | la URL de la página | El `order_ref` es obligatorio en todas. Es el identificador del pedido en tu sistema, el mismo que envías en `external_id` al crear la transacción. Ver [Tipos y payload](https://doc.rapidchargeback.com/es/canais/capture/payload/). Una llamada sin `order_ref` se ignora: no genera evento ni error visible. ## Fire and forget El snippet nunca rompe el checkout, y eso tiene un costo que vale la pena conocer: - toda llamada es silenciosa. No lanza excepciones, no devuelve promesas y no lee la respuesta - los errores de validación (tipo equivocado, `order_ref` demasiado largo) no aparecen en la consola - las fallas de red no se reintentan en el navegador Para **probar** la integración, llama al [endpoint del navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) directamente con curl, donde ves el estado y el mensaje. Una vez validado, el snippet hace lo mismo en producción. El envío usa `navigator.sendBeacon` cuando está disponible, con `fetch` en modo `keepalive` como alternativa. Los dos sobreviven a la navegación a la página siguiente, así que el evento de checkout no se pierde en la redirección del pago. ## Identificación del dispositivo En el `checkout`, el snippet identifica el dispositivo antes de enviar el evento. Intenta con Fingerprint, con un tope de 2 segundos, y recurre a una identificación propia si no lo logra (identificador en `localStorage` más un hash de atributos del navegador). El resultado va en el campo `fp` del payload: | `fp` | Significa | |---|---| | `pro` | identificación de Fingerprint, validada del lado del servidor | | `fallback` | identificación propia del snippet | La diferencia es práctica: solo la identificación validada completa el dispositivo y la IP de la transacción y genera el registro de verificación. Ver [El evento `checkout`](https://doc.rapidchargeback.com/es/canais/capture/payload/#el-evento-checkout). Si tu sitio tiene una CSP restrictiva, Fingerprint se carga desde `https://fpjscdn.net`. Si se bloquea, la captura sigue funcionando en modo `fallback`. ## Cómo saber si está funcionando La misma tarjeta del panel muestra si la cuenta ya recibió eventos y cuándo fue el último. Después de instalar, haz una compra de prueba y revísalo ahí. ## Próximos pasos - [Tipos y payload](https://doc.rapidchargeback.com/es/canais/capture/payload/) - [Enviar evento desde el navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) - [Enviar evento desde el servidor](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) --- # Enviar evento desde el navegador > Registra un evento de captura usando el token publicable. Es el endpoint que llama el snippet, y puedes llamarlo directamente si prefieres no cargar el script. Página: https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/ Registra un evento de captura usando el token publicable. Es el endpoint que llama el [snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/), y puedes llamarlo directamente si prefieres no cargar el script. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/capture/{token}/events ``` ## Autenticación Ninguna. El token publicable en la URL identifica al merchant. ``` Content-Type: application/json ``` El token no es secreto y puede quedar en el HTML de tu tienda. Solo permite escribir, y el evento solo se convierte en evidencia si corresponde a un pedido real tuyo. ## Parámetros de URL | Campo | Tipo | Descripción | |---|---|---| | `token` | string | Token publicable del merchant, generado en el panel | ## Cuerpo de la solicitud | Campo | Tipo | Descripción | Obligatorio | |---|---|---|---| | `type` | string (enum) | `checkout`, `terms_acceptance`, `access_log` o `usage_log` | Sí | | `order_ref` | string | Identificador del pedido en tu sistema, hasta 100 caracteres | Sí | | `event_id` | string | Identificador del evento, generado por ti, hasta 64 caracteres | Sí | | `payload` | objeto | Datos del hecho, con campos de lista cerrada | No | La referencia completa de los valores aceptados está en [Tipos y payload](https://doc.rapidchargeback.com/es/canais/capture/payload/). Dos puntos específicos de este canal: - `event_id` es obligatorio aquí. Genera un UUID por evento - `captured_at` enviado en el cuerpo se ignora. Rapid registra la hora de llegada. Para informar la hora del hecho, usa el [canal servidor](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) Los tipos `delivery_confirmation`, `scan` y `delivery_gps` no existen en este canal: son hechos de tu operación, no del navegador del comprador. ## Límite de llamadas 120 solicitudes por minuto, por IP de origen. Es holgado para un checkout real y limita a quien esté usando el token fuera de tu sitio. ## Validaciones | Regla | Respuesta | |---|---| | Token desconocido, inactivo o sin merchant | `404 NOT_FOUND` | | `type` ausente, o fuera de los cuatro aceptados en este canal | `422 VALIDATION_ERROR`: *invalid_type* | | `order_ref` ausente, vacío o de más de 100 caracteres | `422 VALIDATION_ERROR`: *invalid_order_ref* | | `event_id` ausente, vacío o de más de 64 caracteres | `422 VALIDATION_ERROR`: *invalid_event_id* | | Campo de texto del `payload` de más de 512 caracteres | `422 VALIDATION_ERROR`: *payload_too_large* | | Más de 120 solicitudes por minuto | `429 Too Many Requests` | No existe error para un `order_ref` inexistente. El evento se acepta, queda en la cola y se descarta si ninguna transacción corresponde dentro de la ventana de correlación. Ver [Ventana de correlación](https://doc.rapidchargeback.com/es/canais/capture/payload/#ventana-de-correlación). ## Ejemplo de solicitud ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/tu_token_publicable/events \ -H "Content-Type: application/json" \ -d '{ "type": "terms_acceptance", "order_ref": "TXN-2026-001", "event_id": "019b0000-1111-7000-8000-000000000001", "payload": { "url": "https://loja.exemplo.com/checkout" } }' ``` Evento de checkout con identificación del dispositivo: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/tu_token_publicable/events \ -H "Content-Type: application/json" \ -d '{ "type": "checkout", "order_ref": "TXN-2026-001", "event_id": "019b0000-1111-7000-8000-000000000002", "payload": { "device_id": "8kJ2mQvR1nZxYb0T", "device_fingerprint": "8kJ2mQvR1nZxYb0T", "fp": "pro", "fp_request_id": "1712059781234.Xk9Lp2" } }' ``` ## Ejemplos de respuesta ### Éxito (202) ```json { "accepted": true } ``` `202` significa que el evento entró en la cola, no que ya se convirtió en evidencia. La correlación con la transacción ocurre después. ### Error: token desconocido (404) ```json { "error": { "code": "NOT_FOUND" } } ``` ### Error: tipo no disponible en este canal (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "invalid_type" } } ``` ### Error: `event_id` ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "invalid_event_id" } } ``` ### Error: campo del payload demasiado largo (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "payload_too_large" } } ``` ## Próximos pasos - [Instalar el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) - [Enviar evento desde el servidor](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) - [Configuración del snippet](https://doc.rapidchargeback.com/es/canais/capture/config-do-snippet/) --- # Enviar evento desde el servidor > Registra eventos de captura desde tu backend: entrega confirmada, rastreo, uso del servicio y eventos con fecha retroactiva. Página: https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/ Registra un evento de captura desde tu backend, con las mismas credenciales de las otras APIs. Es el canal para hechos que no ocurren en el navegador: entrega confirmada, lectura de rastreo, coordenada de entrega, y para cualquier evento que necesites reenviar o fechar. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/capture/events ``` ## Autenticación Basic Auth con `client_id:client_secret`. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` No uses el token publicable aquí. La empresa viene de la credencial, por eso este canal puede grabar datos del dispositivo sin la validación exigida en el navegador. ## Cuerpo de la solicitud | Campo | Tipo | Descripción | Obligatorio | |---|---|---|---| | `merchant_id` | string (UUID) | Merchant al que pertenece el evento, dentro de tu empresa (ver [Listar merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/)) | Sí | | `type` | string (enum) | Los cuatro tipos del navegador más `delivery_confirmation`, `scan` y `delivery_gps` | Sí | | `order_ref` | string | Identificador del pedido en tu sistema, hasta 100 caracteres | Sí | | `event_id` | string | Identificador del evento, hasta 64 caracteres. Si se omite, Rapid genera uno | No | | `payload` | objeto | Datos del hecho, con campos de lista cerrada | No | | `captured_at` | string (ISO 8601) | Cuándo ocurrió el hecho. Si se omite, vale la hora de la llamada | No | La referencia completa de los valores aceptados está en [Tipos y payload](https://doc.rapidchargeback.com/es/canais/capture/payload/). Tres diferencias respecto del canal navegador: - `merchant_id` es obligatorio, porque la credencial identifica a la empresa y no al merchant - `captured_at` se respeta, así que una rutina por lotes puede informar la hora real de cada hecho - `event_id` es opcional, pero envía el tuyo: es lo que hace seguro el reenvío ## Idempotencia Reenviar la misma llamada con el mismo `event_id` no duplica la evidencia. Es el comportamiento esperado en un reintento por timeout o respuesta perdida. Si omites el `event_id`, cada llamada genera un identificador nuevo, y la misma llamada repetida se convierte en dos registros. ## Validaciones | Regla | Respuesta | |---|---| | Credencial ausente o inválida | `401 UNAUTHORIZED` | | `merchant_id` ausente | `422 VALIDATION_ERROR`: *merchant_id required* | | `type` ausente o fuera del enum | `422 VALIDATION_ERROR`: *invalid_type* | | `order_ref` ausente, vacío o de más de 100 caracteres | `422 VALIDATION_ERROR`: *invalid_order_ref* | | `event_id` de más de 64 caracteres | `422 VALIDATION_ERROR`: *invalid_event_id* | | Campo de texto del `payload` de más de 512 caracteres | `422 VALIDATION_ERROR`: *payload_too_large* | Un `merchant_id` de otra empresa no da error en la llamada: el evento se acepta y se descarta en la correlación, porque la transacción se busca dentro de tu empresa. Lo mismo vale para un `order_ref` inexistente. ## Ejemplo de solicitud Entrega confirmada: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/events \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "type": "delivery_confirmation", "order_ref": "TXN-2026-001", "event_id": "entrega-TXN-2026-001", "payload": { "carrier": "correios", "tracking": "AA123456789BR" }, "captured_at": "2026-04-03T11:20:00Z" }' ``` Coordenada de la entrega: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/events \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "type": "delivery_gps", "order_ref": "TXN-2026-001", "event_id": "gps-TXN-2026-001", "payload": { "lat": -23.5614, "lng": -46.6559 }, "captured_at": "2026-04-03T11:20:00Z" }' ``` ## Ejemplos de respuesta ### Éxito (202) ```json { "accepted": true } ``` `202` significa que el evento entró en la cola. La correlación con la transacción ocurre después, por el `order_ref`. ### Error: credencial ausente (401) ```json { "error": { "code": "UNAUTHORIZED", "message": "Missing or invalid Authorization header" } } ``` ### Error: `merchant_id` ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "merchant_id required" } } ``` ### Error: tipo inválido (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "invalid_type" } } ``` ## Captura o evidencia Los dos canales registran un hecho en una transacción, y la elección es simple: | Situación | Usa | |---|---| | La transacción ya está en Rapid y tienes su UUID | [`POST /evidence`](https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/) | | Solo tienes tu identificador de pedido, o el hecho ocurre antes del envío de la transacción | este endpoint | | El hecho necesita un campo fuera de la lista cerrada del payload | [`POST /evidence`](https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/), que acepta payload libre | ## Próximos pasos - [Tipos y payload](https://doc.rapidchargeback.com/es/canais/capture/payload/) - [Instalar el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) - [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/) --- # Tipos y payload > Referencia de los valores aceptados en los dos canales de captura. Vale para POST /capture/{token}/events y POST /capture/events. Página: https://doc.rapidchargeback.com/es/canais/capture/payload/ Referencia de los valores aceptados en los dos canales de captura. Vale para [`POST /capture/{token}/events`](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) y [`POST /capture/events`](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/). ## Campos del evento | Campo | Tipo | Límite | Obligatorio | |---|---|---|---| | `type` | string (enum) | ver tabla abajo | Sí | | `order_ref` | string | 100 caracteres | Sí | | `event_id` | string | 64 caracteres | Sí en el navegador, opcional en el servidor | | `payload` | objeto | ver campos aceptados | No | | `captured_at` | string (ISO 8601) | - | No, y solo lo usa el canal servidor | | `merchant_id` | string (UUID) | - | Solo en el canal servidor | ### `order_ref` Es el identificador del pedido en **tu** sistema, y es lo único que une el evento a una transacción. Rapid busca, dentro de tu empresa y del merchant informado: 1. una transacción con `external_id` igual al `order_ref` 2. si no la encuentra, una transacción con `order_number` igual al `order_ref` Envía siempre el mismo valor que usaste en `external_id` al [crear la transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/). Un `order_ref` equivocado no genera error en la llamada: el evento se acepta, no encuentra transacción y se descarta después de la ventana de correlación. ### `event_id` Identificador del evento, generado por ti. Sirve como clave de idempotencia: reenviar el mismo `event_id` para el mismo merchant no crea evidencia duplicada. En el canal navegador es **obligatorio** (el snippet genera un UUID por evento). En el canal servidor, si lo omites, Rapid genera uno. Envía el tuyo cuando puedas reenviar la misma llamada, es lo que garantiza la idempotencia. No uses `:` en el `event_id`. El carácter se elimina antes del uso interno, lo que haría que dos ids distintos colisionen. ### `captured_at` Cuándo ocurrió el hecho, en ISO 8601. | Canal | Comportamiento | |---|---| | Navegador | se ignora. Rapid registra la hora en que llegó el evento | | Servidor | se usa tal como se envió. Si se omite, vale la hora de la llamada | Si el hecho ocurrió antes de la llamada (un procesamiento por lotes de noche, por ejemplo), usa el canal servidor e informa `captured_at`. ## Valores de `type` | Valor | Qué registra | Navegador | Servidor | |---|---|---|---| | `checkout` | Finalización de la compra, con los datos del dispositivo | Sí | Sí | | `terms_acceptance` | Aceptación de términos, política o contrato | Sí | Sí | | `access_log` | Acceso al producto o al área con sesión iniciada | Sí | Sí | | `usage_log` | Uso efectivo del producto o servicio | Sí | Sí | | `delivery_confirmation` | Entrega confirmada | No | Sí | | `scan` | Lectura de código de rastreo en tránsito | No | Sí | | `delivery_gps` | Coordenada de la entrega | No | Sí | Los tres últimos existen solo en el canal servidor: son hechos de tu operación, no del navegador del comprador. Usarlos en el canal navegador responde `422 invalid_type`. ## Campos de `payload` El `payload` tiene una **lista cerrada** de campos. Una clave fuera de la lista se descarta en silencio, sin error, así que revisa la ortografía. | Campo | Tipo | Usar en | |---|---|---| | `device_id` | string | `checkout` | | `device_fingerprint` | string | `checkout` | | `fp` | string | `checkout`, indica el origen de la identificación (`pro` o `fallback`) | | `fp_request_id` | string | `checkout`, exigido para validar la identificación | | `url` | string | `terms_acceptance`, `access_log`, `usage_log` | | `note` | string | cualquier tipo | | `carrier` | string | `delivery_confirmation`, `scan` | | `tracking` | string | `delivery_confirmation`, `scan` | | `lat` | número | `delivery_gps` | | `lng` | número | `delivery_gps` | Reglas: - solo valores escalares (string, número, booleano). Objetos y listas se descartan - un string de más de **512 caracteres** responde `422 payload_too_large` - un `payload` ausente o vacío se acepta ## El evento `checkout` El `checkout` es el único tipo que graba datos directamente en la transacción, y no solo como registro adjunto. Completa el dispositivo y la IP de la transacción **solo cuando esos campos están vacíos**: una captura anterior nunca se sobrescribe. Qué puede grabar cada canal: | Dato de la transacción | Navegador | Servidor | |---|---|---| | `device_id` | no graba | graba | | `device_fingerprint` | solo con identificación validada | graba | | `ip_address` | solo con identificación validada | graba | La diferencia existe porque el token del navegador es publicable: cualquier persona que lo tenga puede enviar eventos. Un dato no validado no toca los campos que sostienen la defensa. **Identificación validada** significa: enviaste `fp_request_id` y `device_id` en el payload, y Rapid confirmó el par contra Fingerprint del lado del servidor. En ese caso el evento también genera un registro de verificación del dispositivo, con las señales de bot, VPN y ventana de incógnito. Sin `fp_request_id`, el evento sigue valiendo como registro, solo que sin la parte del dispositivo. Cada `fp_request_id` vale para **una** transacción. El mismo par reutilizado en otro pedido se trata como repetición y se ignora. ## Ventana de correlación El evento puede llegar antes de que exista la transacción. Queda en la cola y se reintenta durante unas **68 horas**, a intervalos crecientes. Pasada la ventana sin una transacción correspondiente, el evento se descarta. En la práctica: enviar el `checkout` en el momento exacto de la compra funciona, aunque tu rutina solo envíe la transacción a Rapid horas después. ## Próximos pasos - [Instalar el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) - [Enviar evento desde el navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) - [Enviar evento desde el servidor](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-servidor/) --- # Configuración del snippet > Endpoint que devuelve la configuración de identificación de la cuenta, leído por el snippet al cargar. Solo hace falta si escribes tu propio colector. Página: https://doc.rapidchargeback.com/es/canais/capture/config-do-snippet/ Devuelve la configuración de identificación de la cuenta. El [snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) llama a este endpoint al cargar, antes del primer evento. Solo lo necesitas si escribes tu propio colector en el navegador. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/capture/{token}/config ``` ## Autenticación Ninguna. El token publicable en la URL identifica al merchant. ## Parámetros de URL | Campo | Tipo | Descripción | |---|---|---| | `token` | string | Token publicable del merchant, generado en el panel | ## Validaciones | Regla | Respuesta | |---|---| | Token desconocido, inactivo o sin merchant | `404 NOT_FOUND` | ## Caché La respuesta viene con `cache-control: public, max-age=300`. Respeta la caché: la configuración cambia pocas veces y el snippet no necesita consultarla en cada página. ## Ejemplo de solicitud ```bash curl https://api.rapidchargeback.com/api/v1/capture/tu_token_publicable/config ``` ## Ejemplos de respuesta ### Éxito (200), con Fingerprint activo ```json { "data": { "fp_public_key": "pk_exemplo_123456", "fp_region": "us" } } ``` | Campo | Descripción | |---|---| | `fp_public_key` | Clave pública de Fingerprint para usar en el navegador. `null` cuando la identificación no está activa | | `fp_region` | Región de Fingerprint: `us`, `eu` o `ap` | Con la clave, el colector carga el agente de Fingerprint y obtiene dos valores: el identificador del visitante y el identificador de la consulta. Envíalos en el evento `checkout` como `device_id` y `fp_request_id`, y Rapid valida el par del lado del servidor. Ver [El evento `checkout`](https://doc.rapidchargeback.com/es/canais/capture/payload/#el-evento-checkout). ### Éxito (200), sin Fingerprint activo ```json { "data": { "fp_public_key": null, "fp_region": "us" } } ``` Un `fp_public_key` nulo no impide la captura. El evento se sigue registrando, solo que sin la parte de identificación validada del dispositivo. ### Error: token desconocido (404) ```json { "error": { "code": "NOT_FOUND" } } ``` ## Próximos pasos - [Instalar el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/) - [Enviar evento desde el navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/) --- # Visión general > La API de Evidencia adjunta a una transacción ya enviada los hechos que sostienen la defensa: aceptación, acceso, entrega, uso y conversación con el cliente. Página: https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/ La API de Evidencia registra, en una transacción ya enviada a Rapid, los hechos que sostienen una defensa: aceptación de términos, acceso al producto, confirmación de entrega, uso y comunicación con el cliente. Es un canal de **entrada**: tú llamas a Rapid. El registro queda adjunto a la transacción y se usa al armar la defensa cuando esa transacción se convierte en disputa. ## Lo que no es - **No es carga de archivos.** Cada evidencia es un registro JSON con un tope de 32 KB. Comprobantes en PDF, capturas de pantalla y contratos van en la biblioteca de evidencias del panel, no aquí. - **No crea transacciones.** La transacción tiene que existir antes, enviada por la [API de Transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/). Si no existe, la llamada responde `404 TRANSACTION_NOT_FOUND`. ## Flujo resumido 1. Envías la transacción de venta por la API de Transacciones 2. En tu sistema ocurre algo que respalda la venta: el cliente aceptó los términos, accedió al producto, recibió la entrega 3. Registras ese hecho con `POST /evidence`, apuntando a la transacción 4. Si esa transacción se convierte en disputa, Rapid usa los registros en la defensa ## Autenticación Basic Auth con `client_id:client_secret`, igual que los otros canales. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ## Endpoints | Endpoint | Qué hace | |---|---| | [`POST /evidence`](https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/) | Registra una evidencia en una transacción | | [`GET /evidence`](https://doc.rapidchargeback.com/es/canais/evidence/consultar-evidencias/) | Lista las evidencias de una transacción | ## Próximos pasos - [Registrar evidencia](https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/) - [Consultar evidencias](https://doc.rapidchargeback.com/es/canais/evidence/consultar-evidencias/) --- # Registrar evidencia > Adjunta un registro de evidencia a una transacción ya enviada a Rapid. Página: https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/ Adjunta un registro de evidencia a una transacción ya enviada a Rapid. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/evidence ``` ## Autenticación Basic Auth con `client_id:client_secret`. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` ## Cuerpo de la solicitud | Campo | Tipo | Descripción | Obligatorio | |---|---|---|---| | `transaction_id` | string (UUID) | ID de la transacción en Rapid, devuelto cuando la creaste | Sí, o `transaction_ref` | | `transaction_ref` | objeto | Alternativa a `transaction_id`: apunta a la transacción por **tu** identificador. Ver abajo | Sí, o `transaction_id` | | `type` | string (enum) | Naturaleza del hecho registrado. Valores aceptados abajo | Sí | | `payload` | objeto | Los datos del hecho. Formato libre, tope de 32 KB | Sí | | `captured_at` | string (ISO 8601 con offset) | Cuándo ocurrió el hecho en tu sistema, no cuándo lo envías | Sí | Informa **uno** de los dos: `transaction_id` o `transaction_ref`. Si faltan los dos, la respuesta es `422`. ### Campo `transaction_ref` | Campo | Tipo | Descripción | Obligatorio | |---|---|---|---| | `external_source` | string | El mismo origen que usaste al crear la transacción (ej.: `"shopify"`) | Sí | | `external_id` | string | El mismo ID de tu sistema que usaste al crear la transacción | Sí | ### Valores de `type` | Valor | Cuándo usar | |---|---| | `terms_acceptance` | El cliente aceptó términos, política o contrato | | `access_log` | El cliente accedió al producto o al área con sesión iniciada | | `delivery_confirmation` | Entrega confirmada | | `usage_log` | Uso efectivo del producto o servicio | | `communication` | Intercambio con el cliente (e-mail, chat, ticket) | | `other` | Cualquier hecho que no encaje en los anteriores | ### Campo `payload` Formato libre: tú decides las claves. La única regla es el **tope de 32 KB** en el JSON serializado: la evidencia es un registro, no un archivo. Sugerencias por tipo, no obligatorias: ```json // terms_acceptance { "accepted_at": "2026-04-01T15:29:40Z", "terms_version": "v3.2", "ip": "203.0.113.10" } // access_log { "first_access_at": "2026-04-01T16:02:11Z", "sessions": 3 } // delivery_confirmation { "carrier": "correios", "tracking": "AA123456789BR", "delivered_at": "2026-04-03T11:20:00Z" } ``` ## Validaciones | Regla | Respuesta | |---|---| | Ni `transaction_id` ni `transaction_ref` | `422 VALIDATION_ERROR`: *transaction_id or transaction_ref is required* | | `type` fuera del enum | `422 VALIDATION_ERROR` con la lista de valores aceptados | | `captured_at` sin offset de zona horaria | `422 VALIDATION_ERROR`: *Invalid datetime* | | `payload` serializado de más de 32 KB | `422 VALIDATION_ERROR`: *payload exceeds 32KB: evidence is a record, not a file* | | La transacción no existe, o no es de tu empresa | `404 TRANSACTION_NOT_FOUND` | | Credencial ausente o inválida | `401 UNAUTHORIZED` | La transacción siempre se resuelve **dentro de tu empresa**. Un ID de transacción de otra empresa responde `404`, nunca `403`: no confirmamos la existencia de datos ajenos. ## Ejemplo de solicitud ```bash curl -X POST https://api.rapidchargeback.com/api/v1/evidence \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "transaction_id": "00000000-0000-0000-0000-000000000042", "type": "terms_acceptance", "payload": { "accepted_at": "2026-04-01T15:29:40Z", "terms_version": "v3.2", "ip": "203.0.113.10" }, "captured_at": "2026-04-01T15:29:41Z" }' ``` Por tu propio identificador, sin guardar el UUID de Rapid: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/evidence \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "transaction_ref": { "external_source": "shopify", "external_id": "TXN-2026-001" }, "type": "access_log", "payload": { "first_access_at": "2026-04-01T16:02:11Z", "sessions": 3 }, "captured_at": "2026-04-01T16:02:12Z" }' ``` ## Ejemplos de respuesta ### Éxito (201) ```json { "data": { "id": "00000000-0000-0000-0000-0000000000e1", "transaction_id": "00000000-0000-0000-0000-000000000042", "type": "terms_acceptance" } } ``` El `id` devuelto es el de la evidencia. Guárdalo solo si vas a referenciarla; para listar, la clave es la transacción. ### Error: referencia de la transacción ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "transaction_id or transaction_ref is required" } } ``` ### Error: `type` inválido (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid enum value. Expected 'terms_acceptance' | 'access_log' | 'delivery_confirmation' | 'usage_log' | 'communication' | 'other', received 'nao_existe'" } } ``` ### Error: transacción no encontrada (404) ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` ### Error: payload por encima del tope (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "payload exceeds 32KB: evidence is a record, not a file" } } ``` ## Próximos pasos - [Consultar evidencias](https://doc.rapidchargeback.com/es/canais/evidence/consultar-evidencias/) - [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/) --- # Consultar evidencias > Lista las evidencias registradas en una transacción, de la más antigua a la más reciente. Página: https://doc.rapidchargeback.com/es/canais/evidence/consultar-evidencias/ Lista las evidencias registradas en una transacción, de la más antigua a la más reciente. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/evidence?transaction_id= ``` ## Autenticación Basic Auth con `client_id:client_secret`. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ## Query params | Param | Tipo | Descripción | Obligatorio | |---|---|---|---| | `transaction_id` | string (UUID) | Transacción cuyas evidencias quieres ver | Sí | A diferencia del `POST`, aquí **no** existe búsqueda por `transaction_ref`: la consulta es solo por el UUID de Rapid. ## Validaciones | Regla | Respuesta | |---|---| | `transaction_id` ausente | `422 VALIDATION_ERROR`: *transaction_id is required* | | Credencial ausente o inválida | `401 UNAUTHORIZED` | Una transacción de otra empresa, o inexistente, devuelve una **lista vacía**, porque la consulta se filtra por tu empresa; no da error. ## Ejemplo de solicitud ```bash curl "https://api.rapidchargeback.com/api/v1/evidence?transaction_id=00000000-0000-0000-0000-000000000042" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ## Ejemplos de respuesta ### Éxito (200) ```json { "data": [ { "id": "00000000-0000-0000-0000-0000000000e1", "type": "terms_acceptance", "payload": { "ip": "203.0.113.10", "accepted_at": "2026-04-01T15:29:40Z", "terms_version": "v3.2" }, "captured_at": "2026-04-01T15:29:41.000Z", "created_at": "2026-04-01T15:32:36.027Z" } ] } ``` | Campo | Descripción | |---|---| | `id` | ID de la evidencia | | `type` | El tipo informado en el registro | | `payload` | El objeto que enviaste, tal como lo enviaste. El orden de las claves no se conserva | | `captured_at` | Cuándo ocurrió el hecho, como lo informaste | | `created_at` | Cuándo Rapid recibió el registro | ### Sin evidencias (200) ```json { "data": [] } ``` ### Error: `transaction_id` ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "transaction_id is required" } } ``` ## Próximos pasos - [Registrar evidencia](https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/) - [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/) --- # Visión general > El callback de estado: la respuesta que tu aplicación devuelve a Rapid después de analizar una alerta, y cuándo es obligatoria. Página: https://doc.rapidchargeback.com/es/callback/visao-geral/ Después de recibir una alerta por webhook, tu aplicación devuelve un **estado** a Rapid con el resultado de su análisis: - **Ethoca (Mastercard)**: obligatorio en hasta 24 h. La respuesta vuelve a Ethoca y puede evitar que la disputa se convierta en contracargo. - **Verifi RDR (Visa)**: opcional. El reembolso ya se hizo automáticamente; el estado es solo para tu organización interna. ## Flujo resumido 1. Tu aplicación recibe la alerta por [webhook](https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/) 2. Analizas la transacción en tu sistema 3. Llamas a `PATCH /chargeback-alert/alerts/:id/status` con uno de los tres estados válidos 4. Rapid lo procesa, lo guarda y (en el caso de Ethoca) lo reenvía al proveedor También puedes actualizar el estado directamente en el panel de Rapid (útil para operaciones manuales), una alerta a la vez o en lote: seleccionándolas en la lista de alertas o subiendo un archivo CSV con el ID de la alerta y el estado. ## Autenticación El callback usa **Basic Auth** con `client_id`/`client_secret`. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ## Estados válidos Son tres: `notfound`, `account_suspended` y `other`. Qué significa cada uno, los plazos de cada red de tarjetas y las transiciones permitidas están en [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/). ## Consultar alertas Si tu integración necesita buscar alertas (ej.: confirmar si llegó una alerta con un `provider_alert_id` dado, o paginar el historial), usa el endpoint de listado: ``` GET /api/v1/chargeback-alert/alerts ``` Acepta filtros por `status`, `provider_alert_id`, rango de fechas, BIN y últimos dígitos de la tarjeta. Útil cuando solo tienes el ID del proveedor (Ethoca/Verifi) y necesitas encontrar el ID interno de Rapid para actualizar el estado. ## Próximos pasos - [Consultar alertas](https://doc.rapidchargeback.com/es/callback/consultar-alertas/): listar alertas con filtros (incluye búsqueda por tu `provider_alert_id`). - [Actualizar estado](https://doc.rapidchargeback.com/es/callback/atualizar-status/): especificación completa del endpoint de callback. --- # Actualizar estado > Actualiza el estado de una alerta recibida por webhook. Página: https://doc.rapidchargeback.com/es/callback/atualizar-status/ Actualiza el estado de una alerta recibida por webhook. ## Endpoint ``` PATCH https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/:id/status ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Parámetro de URL | Parámetro | Tipo | Descripción | |---|---|---| | `id` | string (UUID) | `alert_id` recibido en el payload del webhook | --- ## Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Descripción | |---|---|---|---| | `status` | string | Sí | Uno de tres valores: `notfound`, `account_suspended`, `other` | --- ## Validaciones - `status` debe ser exactamente uno de los tres valores válidos; cualquier otro devuelve `422` - La alerta debe pertenecer a tu empresa; si no, devuelve `404` - Los estados definitivos (`notfound`, `account_suspended`) no se pueden cambiar una vez enviados; si lo intentas, devuelve error - El estado `expired` lo genera el sistema automáticamente después de 24 h sin respuesta (Ethoca) y no lo envía el cliente - La única transición permitida después de la respuesta inicial es `other → account_suspended`, disponible hasta 6 días (Ethoca) Ver [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/) para el detalle completo. --- ## Ejemplo de solicitud Las credenciales vienen de variables de entorno (`RAPID_CLIENT_ID` y `RAPID_CLIENT_SECRET`), nunca escritas en el código. **cURL** ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/00000000-0000-0000-0000-000000000099/status \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "status": "account_suspended" }' ``` **Node.js** ```javascript const credenciales = Buffer.from(`${process.env.RAPID_CLIENT_ID}:${process.env.RAPID_CLIENT_SECRET}`).toString('base64') const alertId = '00000000-0000-0000-0000-000000000099' const respuesta = await fetch(`https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/${alertId}/status`, { method: 'PATCH', headers: { Authorization: `Basic ${credenciales}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'account_suspended' }), }) const cuerpo = await respuesta.json() if (!respuesta.ok) throw new Error(`${respuesta.status} ${cuerpo.error.code}: ${cuerpo.error.message}`) console.log('Estado actualizado:', cuerpo.data.status) ``` **Python** ```python import os import requests alert_id = "00000000-0000-0000-0000-000000000099" respuesta = requests.patch( f"https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/{alert_id}/status", auth=(os.environ["RAPID_CLIENT_ID"], os.environ["RAPID_CLIENT_SECRET"]), json={"status": "account_suspended"}, timeout=30, ) cuerpo = respuesta.json() if not respuesta.ok: raise RuntimeError(f"{respuesta.status_code} {cuerpo['error']['code']}: {cuerpo['error']['message']}") print("Estado actualizado:", cuerpo["data"]["status"]) ``` **PHP** ```php 'PATCH', CURLOPT_USERPWD => getenv('RAPID_CLIENT_ID') . ':' . getenv('RAPID_CLIENT_SECRET'), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode(['status' => 'account_suspended']), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $crudo = curl_exec($ch); if ($crudo === false) { throw new RuntimeException('Error de red: ' . curl_error($ch)); } $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); $cuerpo = json_decode($crudo, true); if ($status >= 400) { throw new RuntimeException("$status {$cuerpo['error']['code']}: {$cuerpo['error']['message']}"); } echo 'Estado actualizado: ', $cuerpo['data']['status'], PHP_EOL; ``` --- ## Ejemplos de respuesta ### Éxito ```json { "data": { "id": "00000000-0000-0000-0000-000000000099", "status": "account_suspended", "updated_at": "2026-04-14T14:30:00.000Z" } } ``` ### Alerta no encontrada ```json { "error": { "code": "ALERT_NOT_FOUND", "message": "Alert not found" } } ``` ### Empresa bloqueada ```json { "error": { "code": "COMPANY_BLOCKED", "message": "Company is blocked" } } ``` ### Estado fuera de los valores válidos Cuando el `status` enviado no es uno de los tres valores aceptados, la validación del cuerpo falla antes del procesamiento y devuelve `VALIDATION_ERROR` (HTTP 422): ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid enum value. Expected 'notfound' | 'account_suspended' | 'other', received 'foo'" } } ``` ### Transición no permitida Cuando el `status` es válido pero la transición no está permitida (plazo, vencimiento o estado ya definitivo), el código es `ALERT_INVALID_STATUS` (HTTP 422). El mensaje indica cuál de los tres casos ocurrió: ```json { "error": { "code": "ALERT_INVALID_STATUS", "message": "Alert has expired" } } ``` ```json { "error": { "code": "ALERT_INVALID_STATUS", "message": "Response deadline has passed" } } ``` ```json { "error": { "code": "ALERT_INVALID_STATUS", "message": "Alert already has a definitive status" } } ``` Estos tres solo ocurren en alertas de Ethoca; Verifi RDR no tiene reglas de plazo (ver [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/)). --- ## Clientes del sistema anterior Si integrabas con la versión anterior de la plataforma, el endpoint antiguo sigue disponible como alias: ``` POST https://api.rapidchargeback.com/chargeback-alert/update/status ``` Este alias acepta el body en el formato antiguo `{ "alert_id": "...", "status": "..." }` y tanto Basic Auth como los headers `clientid`/`clientkey`. Como en el sistema anterior, **`alert_id` es el ID de la alerta en el proveedor** (el mismo `alert_id` que recibes en el formato `legacy` del webhook y usas en `POST /chargeback-alert/get`); el UUID de Rapid también se acepta. La respuesta mantiene el formato antiguo `{ "success": true, "message": "...", "status": "..." }` y agrega `data` con el objeto del endpoint canónico. Los errores siguen el envelope nuevo (`422 VALIDATION_ERROR` / `ALERT_INVALID_STATUS`, `404 ALERT_NOT_FOUND`). **Recomendación:** migra a `PATCH /chargeback-alert/alerts/:id/status`. El alias se eliminará en el futuro, cuando ya no haya llamadas. --- # Consultar alertas > Lista las alertas de contracargo de tu empresa, con filtros opcionales y paginación. Página: https://doc.rapidchargeback.com/es/callback/consultar-alertas/ Lista las alertas de contracargo de tu empresa, con filtros opcionales y paginación. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts ``` ## Autenticación ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Query params Todos opcionales. Combina los que necesites. | Param | Tipo | Default | Descripción | |---|---|---|---| | `page` | int (≥ 1) | `1` | Página de la paginación | | `per_page` | int (1–100) | `20` | Elementos por página | | `status` | enum | - | `pending`, `notfound`, `account_suspended`, `other`, `expired` | | `provider_alert_id` | string | - | ID de la alerta en el sistema del proveedor (Ethoca/Verifi). Único dentro de cada proveedor; normalmente devuelve 0 o 1 elemento | | `date_from` | YYYY-MM-DD | - | Filtra por `received_at >= date_from` (00:00:00 UTC) | | `date_to` | YYYY-MM-DD | - | Filtra por `received_at <= date_to` (23:59:59 UTC) | | `card_bin` | string (6-8 dígitos) | - | BIN de la tarjeta | | `card_last4` | string (4 dígitos) | - | Últimos dígitos de la tarjeta | --- ## Buscar por tu propio ID (el del proveedor) Las alertas tienen dos IDs: - **`id`**: UUID que Rapid genera cuando recibe la alerta. Es lo que necesitas para actualizar el estado (`PATCH /chargeback-alert/alerts/:id/status`). - **`provider_alert_id`**: ID que generó Ethoca o Verifi. Es lo que probablemente ya tienes guardado en tus sistemas, del payload original del proveedor. Si solo tienes el `provider_alert_id` y necesitas encontrar nuestro `id` (o los datos de la alerta), usa este endpoint con el filtro: ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "provider_alert_id=ALERT-ETHOCA-12345" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` El `provider_alert_id` es único dentro de cada proveedor, así que la respuesta normalmente tendrá 1 elemento en `data`. Para una clave estable y globalmente única, usa el `id` (UUID) de la respuesta. --- ## Ejemplos ### Listar las últimas alertas pendientes ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "status=pending" \ --data-urlencode "per_page=50" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Alertas de los últimos 7 días ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "date_from=2026-04-16" \ --data-urlencode "date_to=2026-04-23" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Buscar por tarjeta (BIN + últimos dígitos) ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "card_bin=424242" \ --data-urlencode "card_last4=4242" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Respuesta ### Éxito ```json { "data": [ { "id": "00000000-0000-0000-0000-000000000099", "company_id": "00000000-0000-0000-0000-0000000000c1", "merchant_id": "00000000-0000-0000-0000-000000000001", "merchant_enrollment_id": "00000000-0000-0000-0000-0000000000aa", "provider": "ethoca_alerts", "provider_alert_id": "ALERT-ETHOCA-12345", "amount": "150.00", "currency": "USD", "card_last4": "4242", "card_bin": "424242", "transaction_date": "2026-04-01T00:00:00.000Z", "descriptor": "LOJA EXEMPLO", "arn": null, "caid": null, "auth_code": "AUTH999", "alert_type": "fraud", "reason_code": "10.4", "issuer": "BANK XYZ", "status": "pending", "received_at": "2026-04-23T10:15:00.000Z", "expires_at": "2026-04-24T10:15:00.000Z", "created_at": "2026-04-23T10:15:00.000Z", "updated_at": "2026-04-23T10:15:00.000Z" } ], "meta": { "page": 1, "per_page": 20, "total": 42, "total_pages": 3 } } ``` ### Sin resultados ```json { "data": [], "meta": { "page": 1, "per_page": 20, "total": 0, "total_pages": 0 } } ``` ### Validación inválida (ej.: `card_bin` no numérico) ```json { "error": { "code": "VALIDATION_ERROR", "message": "card_bin must be 6-8 digits" } } ``` --- ## Clientes del sistema anterior Quien ya integraba con el sistema anterior puede seguir consultando una alerta por el endpoint antiguo, mantenido como alias: ``` POST https://api.rapidchargeback.com/chargeback-alert/get ``` Ten en cuenta que este alias **no** tiene el prefijo `/api/v1`. Acepta Basic Auth o los headers `clientid`/`clientkey`. ### Cuerpo de la solicitud Envía **uno** de los dos: | Campo | Tipo | Descripción | |---|---|---| | `alert_id` | string | **ID de la alerta en el proveedor**, el mismo que recibes en el formato `legacy` del webhook. El UUID de Rapid también se acepta | | `authorization_code` | string | Código de autorización de la transacción | Si vienen los dos, `alert_id` tiene prioridad. Cuando más de una alerta coincide (por ejemplo, dos alertas con el mismo código de autorización), se devuelve la más reciente. ### Ejemplo ```bash curl -X POST https://api.rapidchargeback.com/chargeback-alert/get \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "alert_id": "ETH-99887766" }' ``` ### Respuesta `200` con `success` y `data`, donde `data` es el **mismo cuerpo del webhook en formato `legacy`** (ver [Formato legacy](https://doc.rapidchargeback.com/es/canais/webhook/payload/#formato-legacy)): ```json { "success": true, "data": { "alert_id": "ETH-99887766", "merchant": "Minha Loja", "provider": "ethoca", "descriptor": "LOJA EXEMPLO", "transaction_date": "2026-04-01T00:00:00.000Z", "currency": "USD", "amount": 150, "card_number": "424242******4242", "created_at": "2026-04-14T12:00:00.000Z" } } ``` La respuesta viene con `Cache-Control: no-store`, como en el sistema anterior. ### Errores de este alias Para mantener la paridad con el sistema anterior, los errores de este endpoint usan el envelope **antiguo** (`{"error": "texto"}`), y no el envelope nuevo con `code`: | Situación | Respuesta | |---|---| | Ni `alert_id` ni `authorization_code` | `400` `{"error": "Informe alert_id ou authorization_code."}` | | Ninguna alerta tuya coincide | `404` `{"error": "Alerta não encontrado."}` | Los mensajes están en portugués, tal como los devolvía el sistema anterior. En integraciones nuevas, prefiere [`GET /api/v1/chargeback-alert/alerts/:id`](#endpoint), que usa el envelope de error estándar de la API. --- ## Notas - **`provider`** viene como string slug (`"ethoca_alerts"` o `"verifi_rdr"`), igual que en el payload del webhook saliente (formato `v2`). - Los campos de la respuesta son exactamente los del ejemplo de arriba, más `installment_number` e `installment_count` (cuotas, los mismos del webhook) y `provider_id`, un identificador interno mantenido por compatibilidad: usa `provider`. - Las fechas de "solo fecha" (`transaction_date`) llegan como `"2026-04-01T00:00:00.000Z"`. - **Orden:** siempre por `received_at` descendente (la más reciente primero). No hay parámetro de orden personalizado. - **Auth, rate limit, códigos de error:** ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/) y [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/). --- # Autenticación > Referencia técnica de todos los mecanismos de autenticación de Rapid: Basic Auth para tus llamadas y la firma del webhook para las llamadas de Rapid. Página: https://doc.rapidchargeback.com/es/referencia/autenticacao/ Esta página es la referencia técnica de todos los mecanismos de autenticación de Rapid. ## Tu aplicación llamando a Rapid Usa **Basic Auth** con `client_id` como usuario y `client_secret` como contraseña. ``` Authorization: Basic base64(client_id:client_secret) ``` Endpoints que usan este método: - [API de Transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/): crear, consultar, actualizar y eliminar transacciones - [Merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/): listar los merchants de la empresa - [Consulta de alertas](https://doc.rapidchargeback.com/es/callback/consultar-alertas/) y [callback de estado](https://doc.rapidchargeback.com/es/callback/atualizar-status/) - [API de Evidencias](https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/) y captura del lado del servidor (producto Disputa) ### Credenciales | Credencial | Descripción | |---|---| | `client_id` | ID de tu empresa (generado en el panel) | | `client_secret` | Clave secreta (generada en el panel, trátala como una contraseña) | ### Ejemplo de header ``` Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ= ``` Donde el valor base64 se decodifica como `client_id:client_secret`. ### Seguridad - Usa siempre HTTPS - No incluyas el `client_secret` en código frontend, repositorios públicos ni logs - Rota el `client_secret` si sospechas que se expuso; las credenciales nuevas se generan en el panel --- ## Rapid llamando a tu aplicación (webhook) En el formato `v2`, Rapid firma cada webhook con **HMAC-SHA256** y envía la firma y el timestamp en los headers: ``` X-Webhook-Signature: sha256= X-Webhook-Timestamp: 1790000000 ``` El contenido firmado **no es solo el cuerpo**: es `${X-Webhook-Timestamp}.${cuerpo_crudo}`, el timestamp, un punto y el cuerpo exactamente como llegó. Calcular el HMAC solo sobre el cuerpo da un valor distinto y toda solicitud se rechaza. El timestamp entra en el cálculo para impedir que un POST capturado se reenvíe después (rechaza los que estén fuera de una ventana de 5 minutos). La clave de firma (`secret`) la **genera Rapid** cuando registras el webhook y aparece **una sola vez** en el panel, en **Configuración › Webhook**. No la eliges tú y no hay forma de consultarla después: si la pierdes, genera otra en **Configuración › API** (la anterior deja de valer al instante). El paso a paso de la validación, con ejemplos en Node.js, Python y PHP, está en [Autenticación del webhook](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/). ### Formato `legacy` Las cuentas migradas del sistema anterior reciben los webhooks en el formato `legacy`, que **no está firmado**. En él, la autenticación son los headers que el sistema antiguo ya enviaba: ``` clientid: clientkey: ``` Estos dos headers existen **solo en `legacy`**. En `v2` no se envían: `clientkey` es tu credencial de acceso a la API, y enviarla en cada entrega la expondría en tu endpoint y en tus logs sin necesidad, ya que en `v2` la autenticación la hace la firma. Para saber en qué formato está tu cuenta, ver [Payload](https://doc.rapidchargeback.com/es/canais/webhook/payload/#formato-legacy). --- # Códigos de respuesta > Referencia de los códigos HTTP usados en toda la API de Rapid. Página: https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/ Referencia de los códigos HTTP usados en toda la API de Rapid. ## Códigos de éxito | Código | Significado | |---|---| | 200 | Éxito con cuerpo | | 201 | Recurso creado | | 204 | Éxito sin cuerpo (ej.: `DELETE`) | ## Códigos de error del cliente | Código | Significado | |---|---| | 400 | El cuerpo no es un JSON válido (`INVALID_JSON`) | | 401 | Credenciales ausentes o inválidas | | 403 | Empresa bloqueada | | 404 | Recurso no encontrado | | 409 | Conflicto (duplicado, recurso inmutable) | | 413 | Cuerpo por encima del tamaño máximo (`PAYLOAD_TOO_LARGE`) | | 422 | Error de validación | | 429 | Demasiadas solicitudes (rate limit) | ## Códigos de error del servidor | Código | Significado | |---|---| | 500 | Error interno (`INTERNAL_ERROR`), se recomienda reintentar | --- ## Formato del cuerpo de error Toda respuesta de error tiene esta estructura: ```json { "error": { "code": "CODIGO_SEMANTICO", "message": "Descripción legible del error" } } ``` El `message` viene en inglés y es para quien lee el log: el texto puede cambiar. Para decidir qué hacer en tu código, usa el `code`. Los endpoints que se mantienen del sistema anterior responden como antes. ## Códigos semánticos más comunes | Código | HTTP | Uso | |---|---|---| | `INVALID_JSON` | 400 | El cuerpo no es un JSON válido | | `UNAUTHORIZED` | 401 | Credenciales ausentes o inválidas | | `COMPANY_BLOCKED` | 403 | Empresa bloqueada | | `VALIDATION_ERROR` | 422 | Uno o más campos inválidos | | `NOT_FOUND` | 404 | La dirección no existe en la API (error de tipeo en la ruta, barra final de más) | | `TRANSACTION_NOT_FOUND` | 404 | Transacción inexistente | | `TRANSACTION_DUPLICATE` | 409 | `external_source` + `external_id` ya registrado | | `TRANSACTION_IMMUTABLE` | 409 | Transacción ya utilizada, no se puede modificar | | `MERCHANT_NOT_FOUND` | 404 | Merchant inexistente | | `ALERT_NOT_FOUND` | 404 | Alerta inexistente | | `ALERT_INVALID_STATUS` | 422 | Estado inválido, o transición no permitida (plazo, vencimiento o estado ya definitivo) | | `PAYLOAD_TOO_LARGE` | 413 | Cuerpo por encima del límite: 1 MB por solicitud, 5 MB en el [envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/) | | `RATE_LIMIT_EXCEEDED` | 429 | Límite de solicitudes superado (ver abajo) | | `INTERNAL_ERROR` | 500 | Error inesperado en el servidor | ## Rate limit Todas las rutas comparten un límite de **100 solicitudes por minuto por IP**, incluidas las que responden `401` por credencial inválida. La excepción es el [envío de eventos desde el navegador](https://doc.rapidchargeback.com/es/canais/capture/enviar-evento-navegador/), que tiene su propio tope de 120 por minuto y no cuenta en los 100. Al superarlo, la API devuelve: ``` HTTP/1.1 429 Too Many Requests Retry-After: 15 X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 15 ``` ```json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded, retry in 15 seconds" } } ``` **Usa el `Retry-After`.** Indica, en segundos, cuánto falta para que la ventana se reinicie, y el mensaje repite el mismo número. Esperar exactamente eso es mejor que adivinar: una espera progresiva a ciegas puede reintentar antes de tiempo (y recibir otro `429`) o esperar más de lo necesario. Los headers `X-RateLimit-*` vienen en **todas** las respuestas, no solo en el `429`, así que puedes adelantarte: cuando `X-RateLimit-Remaining` se acerque a cero, frena el envío en vez de esperar el error. Para volumen, prefiere el [envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/), que manda hasta 1000 transacciones en una solicitud y gasta una unidad del límite. ## Reintentos en errores 5xx Los errores `5xx` suelen ser transitorios. Reintenta aumentando el intervalo entre intentos. Nunca reintentes `4xx`: indican un error de tu lado y volverán a fallar. --- # Problemas comunes > Índice por síntoma de los problemas de integración más comunes, con la causa probable y la página que resuelve cada uno. Página: https://doc.rapidchargeback.com/es/referencia/problemas-comuns/ ¿Encontraste tu síntoma? La causa probable está en una línea, y el detalle en la página del enlace. ## Credenciales y acceso ### Toda llamada responde `401` El header `Authorization` no coincide: credencial incorrecta, regenerada en el panel (la anterior deja de valer al instante) o base64 armado sobre algo distinto de `client_id:client_secret`. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ### La API responde `403 COMPANY_BLOCKED` La empresa está bloqueada en Rapid. Las llamadas con credencial se detienen; los webhooks siguen llegando. Ver [Empresas bloqueadas](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/#empresas-bloqueadas). ### Recibo `429` Superaste el límite de solicitudes. Espera el tiempo del header `Retry-After` y, para volumen, usa el envío por lotes. Ver [Rate limit](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/#rate-limit). ### Recibo `404 NOT_FOUND` en un endpoint que existe La ruta tiene una diferencia: barra final de más, falta `/api/v1` o un error de tipeo. Ver [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/). ## Webhook ### No llega ningún webhook Primero confirma que el webhook esté registrado y activo en **Configuración › Webhook**: sin eso no hay entrega ni registro en el log. Después, mira el motivo de cada intento en el log de entregas del panel, en **Actividad**, pestaña **Webhooks**: empieza con `[https]`, `[destino]`, `[redirecionamento]` o `[assinatura]` cuando la falla no fue una respuesta de tu servidor. Ver [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/#logs-de-entrega). ### La firma nunca coincide Casi siempre el cuerpo se leyó como JSON antes de validar: la firma es sobre el cuerpo crudo, byte a byte. Otras causas: una clave que ya se cambió y un timestamp fuera de la ventana. Pruébalo con el [verificador de firma](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/#verificador-de-firma) y compáralo con los ejemplos de [Autenticación del webhook](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/). ### El log muestra una falla, pero mi servidor lo recibió Tu servidor respondió fuera de `2xx` o tardó más que el tiempo límite. Ver [Qué cuenta como éxito](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/#qué-cuenta-como-éxito). ### La misma alerta llegó dos veces Es un reintento o un reenvío, con el mismo `alert_id`. Ver [Idempotencia](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/#idempotencia). ## Alertas ### `422 ALERT_INVALID_STATUS` al responder una alerta El plazo pasó o la alerta ya tiene un estado definitivo. El mensaje indica cuál de los casos es. Ver [Transición no permitida](https://doc.rapidchargeback.com/es/callback/atualizar-status/#transición-no-permitida). ### No sé el `id` de la alerta, solo el del proveedor Busca por el `provider_alert_id`. Ver [Buscar por tu propio ID](https://doc.rapidchargeback.com/es/callback/consultar-alertas/#buscar-por-tu-propio-id-el-del-proveedor). ## Transacciones ### `409 TRANSACTION_DUPLICATE` Ya tienes una transacción con el mismo `external_source` y `external_id`. Ver [Códigos de error](https://doc.rapidchargeback.com/es/canais/transactions/codigos-de-erro/). ### `409 TRANSACTION_IMMUTABLE` La transacción ya fue usada por un producto y ya no se puede modificar ni eliminar. Ver [Protección de inmutabilidad](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/#protección-de-inmutabilidad). ### `404 MERCHANT_NOT_FOUND` El `merchant_id` no es de un merchant de tu empresa. Ver [Listar merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/). ### Perdí el `id` de la transacción Encuéntrala por el identificador que enviaste. Ver [Por el ID de tu sistema](https://doc.rapidchargeback.com/es/canais/transactions/consultar-transacao/#por-el-id-de-tu-sistema). ### `413 PAYLOAD_TOO_LARGE` en el envío por lotes El cuerpo superó el tamaño máximo. Divídelo en lotes más chicos. Ver [Envío por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/). ### La respuesta trae `warnings` La transacción se creó, pero faltan campos que mejoran la protección. Ver [Warnings](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/#warnings). ### Llegó una disputa sin la transacción asociada La transacción no tiene el identificador del cobro en el gateway. Ver [Nota sobre `transaction_id`](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/#nota-sobre-transaction_id). --- # Glosario > Los términos de pago y de integración usados en esta documentación, de ARN a webhook, con lo que cada uno significa para quien integra con Rapid. Página: https://doc.rapidchargeback.com/es/referencia/glossario/ Los términos que aparecen en esta documentación, en orden alfabético. Cuando el término es un campo de la API, el nombre del campo va entre paréntesis. ## 3-DS La autenticación del titular en la compra online, hecha por el emisor (código por SMS, app del banco, biometría). Una compra autenticada pesa a favor de la tienda en una disputa por fraude. ## Adquirente La empresa que procesa los pagos con tarjeta de la tienda y le transfiere el dinero. Es del lado del adquirente que el contracargo se le cobra a la tienda. ## Alerta Aviso de que un titular abrió una disputa en el banco emisor, antes de que se convierta en contracargo. Ver [Alerta](https://doc.rapidchargeback.com/es/produtos/alerta/visao-geral/). ## ARN (`arn`) *Acquirer Reference Number*: el número que el adquirente le da a la transacción en la compensación. Ayuda a ubicar la misma compra en los sistemas de todos los involucrados. ## BIN (`card_bin`) Los primeros 6 a 8 dígitos de la tarjeta. Identifican al banco emisor y el tipo de tarjeta. ## CAID (`caid`) *Card Acceptor ID*: el identificador de la tienda en el adquirente. Junto con el BIN del adquirente (no el de la tarjeta), es como las alertas de Visa se asocian a tu empresa. ## Captura El registro de señales del checkout (dispositivo, aceptación de términos, acceso, entrega) que se convierten en prueba en la defensa. Ver [Captura](https://doc.rapidchargeback.com/es/canais/capture/visao-geral/). ## Clave de firma (`secret`) La clave que Rapid genera cuando registras el webhook y usa para firmar cada entrega. Aparece una sola vez en el panel. Ver [Autenticación del webhook](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/). ## Código de autorización (`auth_code`) El código que el emisor devuelve cuando aprueba la compra. ## Contracargo La reversión forzada de una compra: el titular la disputa en el banco emisor y el monto vuelve a él, cobrado a la tienda. ## Credenciales (`client_id`, `client_secret`) El par que autentica las llamadas a la API por Basic Auth. Se genera en el panel. Ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/). ## Descriptor (`descriptor`) El nombre de la tienda que aparece en el resumen de la tarjeta. Es como las alertas de Mastercard se asocian a tu empresa, y el motivo de muchas disputas: quien no reconoce el nombre, disputa el cargo. ## Disputa El reclamo de una compra por parte del titular. También el nombre del producto de Rapid que defiende el contracargo ya abierto. Ver [Disputa](https://doc.rapidchargeback.com/es/produtos/disputa/visao-geral/). ## ECI (`eci`) *Electronic Commerce Indicator*: el indicador que dice si la compra online fue autenticada y cómo (por ejemplo, con 3-DS). ## Emisor El banco que emitió la tarjeta del titular. Es donde empieza la disputa. ## Estado de la alerta (`status`) La situación de la alerta: `pending`, `notfound`, `account_suspended`, `other` o `expired`. Ver [Reglas y plazos](https://doc.rapidchargeback.com/es/produtos/alerta/regras-e-prazos/). ## Evidencia Una prueba registrada sobre una transacción (aceptación de términos, acceso, entrega, comunicación) para sostener la defensa. Ver [Evidencia](https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/). ## Firma del webhook El código HMAC-SHA256 que Rapid envía en el header `X-Webhook-Signature`, calculado con tu clave de firma. Prueba que la entrega vino de Rapid. Ver [Autenticación del webhook](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/). ## Idempotencia Procesar el mismo evento dos veces sin efecto duplicado. Necesaria porque el webhook puede llegar más de una vez. Ver [Idempotencia](https://doc.rapidchargeback.com/es/canais/webhook/boas-praticas/#idempotencia). ## MCC (`mcc`) *Merchant Category Code*: el código de cuatro dígitos que clasifica el rubro de la tienda. ## Merchant La tienda, marca o vendedor de una empresa cliente. Una empresa puede tener varios. Ver [Listar merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/). ## Prevención El producto de Rapid que responde al banco emisor con los datos del pedido para que la disputa no nazca. Ver [Prevención](https://doc.rapidchargeback.com/es/produtos/prevencao/visao-geral/). ## Red de la tarjeta (`network`) La red de la tarjeta, como Visa o Mastercard. Define las reglas y los plazos de la disputa. ## Titular La persona dueña de la tarjeta usada en la compra. ## Token publicable El token del snippet de captura, que queda en el HTML de la tienda. Solo permite enviar eventos, nunca leer datos. Ver [Instalar el snippet](https://doc.rapidchargeback.com/es/canais/capture/instalar-o-snippet/). ## Transacción Una venta enviada a Rapid por la [API de Transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/). Es el material de la Prevención y de la Disputa. ## Webhook El POST que Rapid hace a la URL que registraste, en cada evento (alerta nueva, corte de acceso). Ver [Webhook](https://doc.rapidchargeback.com/es/canais/webhook/visao-geral/). --- # Ejemplos canónicos > Los IDs, valores y credenciales fijos de todos los ejemplos de la documentación, para que el ejemplo de una página se conecte con el de otra. Página: https://doc.rapidchargeback.com/es/referencia/exemplos-canonicos/ Valores fijos usados en todos los ejemplos de la documentación. Úsalos como referencia al leer los ejemplos de curl y los payloads: los mismos IDs aparecen en páginas distintas a propósito, para que un ejemplo de transacción se conecte con un ejemplo de alerta. ## Valores por defecto ### IDs generados por Rapid Todos siguen el mismo molde, `00000000-0000-0000-0000-` más un sufijo, para que sea obvio que son de ejemplo. Un ID real nunca tiene este formato. | Qué identifica | Campo | Valor | |---|---|---| | Transacción | `id`, `transaction_id` | `00000000-0000-0000-0000-000000000042` | | Merchant | `merchant_id` | `00000000-0000-0000-0000-000000000001` | | Alerta | `alert_id` | `00000000-0000-0000-0000-000000000099` | | Disputa | `dispute_id` | `00000000-0000-0000-0000-0000000000d1` | | Evidencia | `id` | `00000000-0000-0000-0000-0000000000e1` | | Tu empresa | `company_id` | `00000000-0000-0000-0000-0000000000c1` | | Afiliación del merchant | `merchant_enrollment_id` | `00000000-0000-0000-0000-0000000000aa` | La transacción `…042` es la misma en todas las páginas: es la que creas en [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/), consultas, actualizas y eliminas en las páginas siguientes, y es a la que apunta la [evidencia](https://doc.rapidchargeback.com/es/canais/evidence/registrar-evidencia/). ### Valores de la transacción | Campo | Valor | |---|---| | `external_id` (tu ID de la transacción) | `TXN-2026-001` | | `amount` | `150.00` | | `currency` | `USD` | | `transaction_date` | `2026-04-01T15:30:00Z` | | `card_last4` | `4242` | | `card_bin` | `424242` | | `descriptor` | `LOJA EXEMPLO` | | `arn` | `74537119547024600128228` | | URL del webhook del cliente | `https://seu-sistema.com/webhooks/rapid` | | URL base de la API | `https://api.rapidchargeback.com/api/v1` | ## Header de Basic Auth Todos los ejemplos usan el mismo header codificado: ``` Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ= ``` El valor base64 se decodifica como `client_id:client_secret`. En tu código, reemplázalo por las credenciales reales de tu empresa. ## Nombres y direcciones de ejemplo - Cliente: `João Silva`, email `joao@exemplo.com` - Dirección: `Rua das Flores, 123, São Paulo, SP, 01001000, BRA` Estos valores no tienen un significado especial: son solo marcadores consistentes entre páginas. Están en portugués porque son los mismos en todos los idiomas de esta documentación. --- # Herramientas para devs > La documentación en tu asistente de IA (MCP), en Markdown y en llms.txt, y la colección de Postman con todas las solicitudes listas. Página: https://doc.rapidchargeback.com/es/referencia/ferramentas-para-devs/ Atajos para integrar más rápido: la documentación dentro de tu asistente de IA y las solicitudes listas para probar. ## MCP El servidor MCP permite que tu asistente de IA (Claude, Cursor, VS Code, ChatGPT y otros) **busque y lea esta documentación** mientras programas. En vez de responder de memoria, consulta la página correcta y usa los nombres de campo, los valores aceptados y los códigos de error reales. ``` https://doc.rapidchargeback.com/mcp/ ``` Solo lee la documentación pública: no pide credenciales, no accede a tu cuenta de Rapid y no llama a la API. La documentación está en portugués, inglés y español; pide al asistente que use español (las herramientas aceptan el parámetro `language`). ### Claude Code ```bash claude mcp add --transport http rapid-docs https://doc.rapidchargeback.com/mcp/ ``` ### Cursor En `~/.cursor/mcp.json` (o `.cursor/mcp.json` en el proyecto): ```json { "mcpServers": { "rapid-docs": { "url": "https://doc.rapidchargeback.com/mcp/" } } } ``` ### VS Code En `.vscode/mcp.json` en el proyecto: ```json { "servers": { "rapid-docs": { "type": "http", "url": "https://doc.rapidchargeback.com/mcp/" } } } ``` ### Claude (app y web) En la configuración de **Conectores**, agrega un **conector personalizado** con el nombre `Rapid` y la URL de arriba. ### Otros clientes Cualquier cliente MCP con transporte HTTP funciona con la misma URL. ### Qué puede hacer el asistente | Herramienta | Qué hace | |---|---| | `search_docs` | Busca por tema, nombre de campo, código de error, header o ruta de endpoint. Corrige errores de tipeo | | `get_page` | Lee una página completa en Markdown | | `list_pages` | Lista todas las páginas, en orden de lectura | Ejemplo de pedido: *"Usando la documentación de Rapid, escribe el handler del webhook de alertas en Node.js, validando la firma."* ## Copiar una página Toda página tiene el botón **Copiar página**, junto al título. Copia la página en Markdown, el formato que se pega en un asistente de IA sin perder tablas ni bloques de código. El menú junto al botón abre la misma página directamente en ChatGPT o en Claude. Cada página también está disponible en Markdown en su propia dirección, cambiando la barra final por `.md`: ``` https://doc.rapidchargeback.com/es/canais/webhook/payload.md ``` ## llms.txt Para herramientas que leen la documentación de una sola vez: | Archivo | Contenido | |---|---| | [`/es/llms.txt`](https://doc.rapidchargeback.com/es/llms.txt) | Índice de todas las páginas, con descripción y enlace al Markdown | | [`/es/llms-full.txt`](https://doc.rapidchargeback.com/es/llms-full.txt) | Toda la documentación en un solo archivo | ## Colección de Postman Todas las solicitudes de ejemplo de esta documentación, organizadas por las secciones del menú. 1. Descarga la [colección](https://doc.rapidchargeback.com/es/rapid.postman_collection.json). 2. En Postman, haz clic en **Import** y elige el archivo. 3. En las variables de la colección, completa `client_id` y `client_secret` con las credenciales del panel (ver [Autenticación](https://doc.rapidchargeback.com/es/referencia/autenticacao/)). La autenticación Basic ya viene configurada en la colección. Los IDs de los ejemplos son ficticios (ver [Ejemplos canónicos](https://doc.rapidchargeback.com/es/referencia/exemplos-canonicos/)): reemplázalos por los de tu cuenta antes de enviar. La colección se genera a partir de los ejemplos de las páginas, así que acompaña la documentación. --- # Novedades de la API > Qué cambió en la API de integración de Rapid, por fecha: endpoints nuevos, cambios de comportamiento y lo que sigue funcionando del sistema anterior. Página: https://doc.rapidchargeback.com/es/referencia/novidades-da-api/ Cambios en la API de integración, del más reciente al más antiguo. Los cambios solo en el panel no entran aquí. ## Octubre de 2026: nueva API La versión actual de la API, que reemplaza la del sistema anterior. Si ya integrabas con Rapid, esta es la lista de lo que cambia. ### Nuevo - **API de Transacciones** en `/api/v1/transactions`: [crear](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/), [enviar por lotes](https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/) (hasta 1000 por llamada), [consultar](https://doc.rapidchargeback.com/es/canais/transactions/consultar-transacao/) por el ID de Rapid o por el ID de tu sistema, [actualizar](https://doc.rapidchargeback.com/es/canais/transactions/atualizar-transacao/) y [eliminar](https://doc.rapidchargeback.com/es/canais/transactions/deletar-transacao/). - **[Listar merchants](https://doc.rapidchargeback.com/es/canais/merchants/listar-merchants/)**, para encontrar el `merchant_id` por la API. - **[Consultar alertas](https://doc.rapidchargeback.com/es/callback/consultar-alertas/)** con filtros (estado, fechas, tarjeta, ID del proveedor) y paginación. - **[Actualizar estado](https://doc.rapidchargeback.com/es/callback/atualizar-status/)** de la alerta en `PATCH /api/v1/chargeback-alert/alerts/:id/status`. - **Webhook en formato `v2`**: entrega [firmada](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/) con HMAC-SHA256 y timestamp, evento identificado en el cuerpo y en un header, y un solo canal para todos los productos. - **[Evidencia](https://doc.rapidchargeback.com/es/canais/evidence/visao-geral/) y [Captura](https://doc.rapidchargeback.com/es/canais/capture/visao-geral/)**, que alimentan la defensa de la Disputa. - **Errores en un formato único** en toda la API, incluso en rutas que no existen (`404 NOT_FOUND`). El `message` viene en inglés; decide por el `code` (ver [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/)). - **[Herramientas para devs](https://doc.rapidchargeback.com/es/referencia/ferramentas-para-devs/)**: la documentación en tu asistente de IA (MCP), en Markdown y en `llms.txt`, y la colección de Postman. ### Cambió - **Webhook solo por HTTPS y a una dirección pública de internet.** Una redirección que cambia el POST por GET (`301`, `302`, `303`) no se sigue. Ver [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/). - **Límite de solicitudes** por IP, que también cuenta las respuestas `401`, con `Retry-After` en el `429`. Ver [Códigos de respuesta](https://doc.rapidchargeback.com/es/referencia/codigos-de-resposta/#rate-limit). - **Reintentos del webhook** con intervalos definidos. Ver [Reintentos y logs](https://doc.rapidchargeback.com/es/canais/webhook/retries-e-logs/). ### Sigue funcionando, del sistema anterior Se mantienen para quien ya integraba, sin cambios de tu lado. Para una integración nueva, usa los endpoints de la columna de la derecha. | Del sistema anterior | Usar en una integración nueva | |---|---| | `POST /chargeback-alert/update/status` | [`PATCH /api/v1/chargeback-alert/alerts/:id/status`](https://doc.rapidchargeback.com/es/callback/atualizar-status/) | | `POST /chargeback-alert/get` | [`GET /api/v1/chargeback-alert/alerts`](https://doc.rapidchargeback.com/es/callback/consultar-alertas/) | | Webhook en el [formato `legacy`](https://doc.rapidchargeback.com/es/canais/webhook/payload/#formato-legacy), con `clientid`/`clientkey` | Webhook en el formato `v2`, con [firma](https://doc.rapidchargeback.com/es/canais/webhook/autenticacao/) | Estos endpoints antiguos se eliminarán cuando ya no haya llamadas a ellos. ### Sin equivalente La **API de Transacciones del sistema anterior** (`/transactions/create`, `/transactions/update` y `/transactions/delete`, sin `/api/v1`) no existe en la nueva API. Cambiaron la ruta y los campos: la integración tiene que pasar a la nueva [API de Transacciones](https://doc.rapidchargeback.com/es/canais/transactions/visao-geral/).