Saltearse al contenido

Changelog

Acá listamos cambios que afectan a integradores: endpoints nuevos, campos agregados/cambiados, deprecaciones. Mejoras del dashboard o internas no entran.

2026-08

  • expires_in en POST /v1/payments (2026-08-29). Los pagos directos ahora aceptan un plazo, igual que el checkout hospedado: mín 60 s, máx 86400. Vencido, el pago pasa a expired y recibís payment.expired. El default depende del proveedor: 3600 s para dinelco y bancard, y sin vencimiento para transferencia (el comprador va al banco y sube el comprobante horas después — ponerle un default rompería ese flujo). Un expires_in explícito gana siempre. Ver Expiración.
  • La página hospedada avisa y devuelve al comercio al vencer (2026-08-29). El checkout hospedado muestra un contador con el tiempo restante; al llegar a cero cierra el formulario de tarjeta, se lo explica al comprador y a los 5 segundos lo redirige a tu cancel_url con ?status=expired&reference=...&checkout_session_id=.... Antes se quedaba trabado en una página muerta. Si ya manejás la vuelta del comprador, agregá el caso expired — si no, va a caer en tu rama genérica de cancelación. Ver Expiración.
  • Cuatro campos nuevos en el payload de webhook (2026-08-29). Aditivos, no rompen nada: expires_at (el plazo del intento), expired_at (cuándo lo marcamos vencido), confirmed_after_expiry y recovered_from_status. Los dos últimos identifican una confirmación que llegó fuera de la ventana: el formulario de tarjeta vive en el dominio del proveedor y un pago puede aprobarse justo después del vencimiento. Si manejás stock o cupo, usalos para decidir si honrás el pago o lo revertís. Ver confirmaciones fuera de ventana.
  • Correcciones de documentación (2026-08-29). La doc de webhooks describía un payload con wrapper data y claves event_type / event_id en el body que nunca existió: el payload real es plano, el tipo viene en event, y el event_id solo en el header X-Ingalca-Event-Id. También estaba mal documentado que amount es un entero (es un string decimal, "150000.00") y que currency es opcional en POST /v1/payments (es requerido). El código no cambió — solo la documentación, que ahora refleja lo que la API viene devolviendo. Si escribiste tu handler siguiendo esos ejemplos, revisalo.
  • Checkout hospedado (2026-08-04). POST /v1/checkout-sessions crea una sesión de pago y te devuelve una url a la que redirigís el browser del comprador. Él elige método (Dinelco, Bancard o transferencia) y paga en una página hospedada por nosotros con tu logo y tus colores; vos no construís UI de pago ni embebés iframes. Al terminar vuelve a tu success_url / cancel_url, y la confirmación llega por webhook como siempre. Ver Checkout hospedado.
  • Bancard disponible como proveedor de pago (2026-08). POST /v1/payments acepta provider=bancard para cobro con tarjeta (pago ocasional): el cliente tipea la tarjeta dentro del iframe de Bancard —embebido en tu UI vía el checkout_url que te devolvemos, proxeado por el gateway— y el 3DS lo maneja Bancard. La confirmación llega por callback y te la reenviamos como payment.confirmed / payment.failed. La reversa (POST /v1/payments/{id}/reverse) funciona el mismo día, antes de la liquidación. Solo PYG. Las tarjetas guardadas con Bancard (catastro + cobro con token) llegan en una fase posterior. Ver Elegir método de pago.

2026-07

  • return_url con deep links + guía de integración móvil (2026-07-16). POST /v1/cards y POST /v1/payments aceptan ahora un campo return_url (opcional en integraciones web, obligatorio en apps móviles). Cuando termina el 3DS el proxy redirige a esa URL con ?status=X&card_id=Y (o payment_id). Acepta http/https además de esquemas custom (fixapp://, com.fix.app://) para integrar con SFSafariViewController (iOS) y Custom Tabs (Android) usando deep links — el patrón necesario porque los WebView modernos bloquean cookies third-party y rompen el 3DS. Sin return_url la comunicación sigue siendo postMessage como antes. Fix relacionado del mismo commit: POST /v1/cards ahora siempre envía un returnUrl válido a Dinelco (antes se colaba null cuando el integrador no lo mandaba y Dinelco cancelaba el 3DS con “cancelado por el cliente” aunque el OTP hubiera sido correcto). Ver guía mobile para ejemplos por stack.
  • checkout_url proxeado por el gateway (2026-07-16). POST /v1/cards (Dinelco) devuelve un nuevo campo registration.checkout_url que embebés como <iframe src> — servimos el HTML del checkout desde api.pay.ingalca.com y proxeamos al proveedor por atrás. Tu app nunca ve URLs ni tokens del proveedor. POST /v1/payments con Dinelco (sin card_id) suma un bloque data.checkout con el mismo shape. Los eventos del iframe llegan como postMessage normalizados en tu vocabulario: ingalca.registry.completed/.failed/.cancelled para catastro, ingalca.checkout.* para pagos. Los campos crudos anteriores (integrity_token, session_id, validate_url) siguen en la respuesta como internos — usá checkout_url. Ver guía de catastro y reference de pagos.
  • Eliminar tarjetas (borrado lógico) + dedup de catastros (2026-07-15). DELETE /v1/cards/{id} ahora responde 204 y hace un borrado lógico (la tarjeta queda deleted, sale del listado y no es cobrable); emitimos card.deleted. Además, re-catastrar la misma tarjeta ya no acumula duplicados: la registración anterior del mismo customer_id con igual número enmascarado/marca/tipo pasa a deleted automáticamente. Antes el DELETE devolvía 501. Dinelco no expone unregister remoto — si lo habilita, el DELETE lo va a usar sin cambiar el contrato.
  • Idempotencia por reference (2026-07-14). POST /v1/cards/{id}/charge y POST /v1/payments deduplican por reference: reenviar el mismo request (misma reference, mismo body) devuelve el pago original con 200, sin cobrar de nuevo; la misma reference con otro amount/card_id/currency devuelve 409 REFERENCE_ALREADY_USED. El replay devuelve el resultado original aunque haya terminado failed — para reintentar de verdad, usá una reference nueva. Ver idempotencia.

2026-05

  • target_origin acepta múltiples dominios (2026-05-12). Podés mandar target_origin como array en POST /v1/payments y POST /v1/cards para listar todos los orígenes (dominios/subdominios) desde donde podés embeber el iframe de Dinelco. La forma string (un solo origen) sigue funcionando. Ver Sobre target_origin.
  • Notificaciones por email configurables (2026-05-02). Te avisamos por email cuando un webhook agota reintentos o cuando un cliente sube un comprobante de transferencia para revisar. Configurás en Configuración → Webhooks → Notificaciones por email. Throttle: máx 1 email por hora (webhooks fallidos) / 30 min (comprobantes).
  • Aprobar/rechazar comprobantes vía API (2026-05). Endpoints POST /v1/payments/{id}/confirm y POST /v1/payments/{id}/reject para automatizar la aprobación de transferencias si tenés tu propia lógica.

2026-04

  • Customers como entidad referencial (2026-04). Endpoints GET /v1/customers y GET /v1/customers/{id}. Auto-create al crear pagos o tarjetas con customer.customerId. Webhook payment.* ahora incluye customer_id (external_id) en el payload. Ver guía de customers.
  • Reversa de pagos Dinelco (2026-04). POST /v1/payments/{id}/reverse para Dinelco antes del corte de liquidación. Webhook payment.reversed. Mensaje específico cuando ya pasó la ventana (responseCode: 90019). Ver guía de reversa.
  • Pago Failed (no Pending) cuando falla el create (2026-04). Antes los pagos con payload inválido quedaban como pending fantasma. Ahora se marcan failed con rejection_reason = mensaje del provider.
  • Sección /cards en el dashboard del tenant (2026-04). Listado read-only con drawer.

Si tenés un caso particular o preguntas sobre algún cambio, escribinos a desarrollo@ingalca.com.