ARBA R122
certificado retención digital (preliminar)
certificado retención digital (preliminar)
Este servicio (API) de ARBA permite emitir el certificado de retención digital (previa declaración jurada abierta) y descargar el PDF correspondiente
REM ejemplo para visual basic 6
REM ejecutar el código directamente
REM no es necesario agregar referencia
REM la interfaz se crea dinamicamente
Dim mio As Object
Dim bresultado As Boolean
bresultado = True
Dim curl As String
Rem URL del servidor (prueba o real)
curl = "https://app2.test.arba.gov.ar/a122rSrv/api/external/comprobante"
Dim crutaticket As String
Rem Ruta donde se guardó el token del paso anterior
crutaticket = "d:\ticket.txt"
Dim carchivoxmlenviado As String
Dim carchivoxmlrecibido As String
Rem Rutas para guardar el log de tráfico enviado/recibido
carchivoxmlenviado = "d:\arbapet.txt"
carchivoxmlrecibido = "d:\arbaret.txt"
Dim ctoken As String
Dim numeroArchivo As Integer
numeroArchivo = 1
Rem Lectura del archivo de ticket (Sintaxis VB6 clásica)
Open crutaticket For Input As #numeroArchivo
ctoken = Input(LOF(numeroArchivo), #numeroArchivo)
Close #numeroArchivo
Dim ccuit As String
Rem CUIT del agente ARBA
ccuit = "20111111112"
Dim crutalicencia As String
Rem Ruta de la licencia (Servicio ARBA A122)
crutalicencia = "D:\20111111112.lic"
Dim cidDDJJ As String
Rem ID de la DDJJ (obtenido previamente)
cidDDJJ = "1234"
Rem Creación del objeto COM (Sintaxis VB6)
Set mio = CreateObject("WSAFIPFE.misdatos")
If mio.iniciar(ccuit, "") Then
mio.tls = -1
mio.archivolicencia = crutalicencia
mio.ArchivoXMLEnviado = carchivoxmlenviado
mio.ArchivoXMLRecibido = carchivoxmlrecibido
bresultado = mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.ticket", ctoken, 0, 0)
Dim cticket As String
If bresultado Then
cticket = mio.apiLeerPropiedad("ARBA2025", "obtenerticket.ticketvigente", "", 0, 0)
If cticket = "SI" Then
If bresultado Then
bresultado = mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
Rem Configuración de parámetros JSON
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.URLMETODO", curl, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.TIPOMETODO", "POST", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.idDj", cidDDJJ, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.nTransaccionAgente", "numeroÚnicoEnCadaLLamada", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.cuitContribuyente", "20111111112", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.cuitAgente", ccuit, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.sucursal", "3", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.alicuota", "2", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.baseImponible", "100.10", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.importeRetencion", "2.01", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.razonSocialContribuyente", "prueba", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.fechaOperacion", "2025-11-20T20:00:20.595Z", 0, 0)
Rem Dirección (Diccionario anidado)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.calle", "san martin", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.numero", "260", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.piso", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.departamento", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.codigoPostal", "0000", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.localidad", "Capital Federal", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.diccionario.direccion.provincia", "Capital Federa", 0, 0)
If bresultado Then
If mio.apiEjecutar("ARBA2025") Then
Dim ccadena As String
Dim cmessage As String
Dim cid As String
cmessage = mio.apiLeerPropiedad("ARBA2025", "diccionario.error", "", 0, 0)
If cmessage = "" Then
cid = mio.apiLeerPropiedad("ARBA2025", "diccionario.id", "", 0, 0)
MsgBox "id certificado " & cid
Else
MsgBox "error " & cmessage
End If
Else
MsgBox "error metodo " & mio.UltimoMensajeError
bresultado = False
End If
Else
bresultado = False
MsgBox "error cargar propiedad " & mio.UltimoMensajeError
End If
End If
Else
MsgBox "ticket vencido"
End If
Else
MsgBox mio.UltimoMensajeError
End If
End If
Esta API (replicada por la interfaz WSAFIFPE.misdatos) contiene método para abrir una declaración jurado (obteniendo su ID) mensual o quincenalmente (según la actividad) y luego otro método para emitir retenciónes (informando sus datos: fecha, monto, id DD.JJ, monto retenido, etc.) y descargar el PDF generado por el mismo servicio.
Para poder usar este servicio debe tener en cuenta los siguientes puntos o requisitos
El instalador 100.90 o superior.
Un usuario/contraseña (CUIT/CIT) del agente de retención válido para sesión en la web de ARBA (tanto para el modo prueba o real).
Un archivo de licencia (provisorio o definitivo) generado para ese CUIT que incluya el servicio ARBA A122 retención digital como figura en este tutorial.
Un algoritmo o procedimiento que genere un identificador único para cada llamada para generar un certificado y asi poder administrar fallos de conexión.
Los PDF y manuales del servicio (al pie) donde figuran los datos y campos de cada método y las URL que cada una de las operaciones y sus validaciones.
Dim mio As Object
Dim bresultado As Boolean
bresultado = True
Dim curl As String
Rem URL del servidor (prueba o real) para obtener el token
curl = "https://idp.test.arba.gov.ar/realms/ARBA/protocol/openid-connect/token"
Dim crutaticket As String
Rem Ruta donde se guardará el token obtenido
crutaticket = "d:\ticket.txt"
Dim carchivoxmlenviado As String
Dim carchivoxmlrecibido As String
Rem Rutas para guardar el log de tráfico enviado/recibido
carchivoxmlenviado = "d:\arbapet.txt"
carchivoxmlrecibido = "d:\arbaret.txt"
Dim ccadena As String
Dim numeroArchivo As Integer
numeroArchivo = 1
Dim ccuit As String
Rem CUIT del agente ARBA
ccuit = "cuit Agente"
Dim cpassword As String
cpassword = "clave"
Dim crutalicencia As String
Rem Archivo de licencia que incluye el servicio ARBA A122
crutalicencia = "D:\cuitagente.lic"
Set mio = CreateObject("WSAFIPFE.misdatos")
If mio.iniciar(ccuit, "") Then
mio.tls = -1
mio.archivolicencia = crutalicencia
mio.ArchivoXMLEnviado = carchivoxmlenviado
mio.ArchivoXMLRecibido = carchivoxmlrecibido
' Carga de parámetros para el Token (OAuth/OpenID)
bresultado = bresultado And mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.URLMETODO", curl, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.TIPOMETODO", "POST", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOS.client_id", "A122RServicios", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOS.client_secret", "44cqahkhERKtkkDGmcqrPApCMtez3XxT", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOS.username", ccuit, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOS.password", cpassword, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOS.grant_type", "password", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOS.scope", "openid", 0, 0)
If bresultado Then
If mio.apiEjecutar("ARBA2025.OBTENERTICKET") Then
ccadena = mio.apiLeerPropiedad("ARBA2025", "obtenerticket", "", 0, 0)
MsgBox "TICKET " & ccadena
If mio.UltimoMensajeError = "" Then
' Guardamos el token en un archivo de texto
Open crutaticket For Output As #numeroArchivo
Print #numeroArchivo, ccadena
Close #numeroArchivo
Else
MsgBox "error " & mio.UltimoMensajeError
End If
Else
MsgBox "error obtener ticket " & mio.UltimoMensajeError
End If
Else
MsgBox "error cargar propiedad " & mio.UltimoMensajeError
End If
Else
MsgBox mio.UltimoMensajeError & " fallo iniciar"
End If
Dim mio As Object
Dim bresultado As Boolean
bresultado = True
Dim curl As String
Rem es la url o dirección del servidor (prueba o real)
curl = "https://app2.test.arba.gov.ar/a122rSrv/api/external/declaracionJurada"
Dim crutaticket As String
Rem es donde se guardó el token obtenido en paso anterior.
crutaticket = "d:\ticket.txt"
Dim carchivoxmlenviado As String
Dim carchivoxmlrecibido As String
carchivoxmlenviado = "d:\arbapet.txt"
carchivoxmlrecibido = "d:\arbaret.txt"
Dim ctoken As String
Dim numeroArchivo
numeroArchivo = 1
Rem leemos el ticket de acceso
Open crutaticket For Input As #numeroArchivo
ctoken = Input(LOF(numeroArchivo), #numeroArchivo)
Close #numeroArchivo
Dim ccuit As String
ccuit = "cuit agente ARBA"
Dim crutalicencia As String
crutalicencia = "D:\cuitagente.lic"
Set mio = CreateObject("WSAFIPFE.misdatos")
If mio.iniciar(ccuit, "") Then
mio.tls = -1
mio.archivolicencia = crutalicencia
mio.ArchivoXMLEnviado = carchivoxmlenviado
mio.ArchivoXMLRecibido = carchivoxmlrecibido
bresultado = mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.ticket", ctoken, 0, 0)
Dim cticket As String
If bresultado Then
cticket = mio.apiLeerPropiedad("ARBA2025", "obtenerticket.ticketvigente", "", 0, 0)
If cticket = "SI" Then
bresultado = mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.URLMETODO", curl, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.TIPOMETODO", "POST", 0, 0)
' Configuración JSON
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.cuitAgente", ccuit, 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.quincena", "0", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.actividadId", "10", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.anio", "2025", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.DATOSJSON.mes", "11", 0, 0)
If bresultado Then
If mio.apiEjecutar("ARBA2025") Then
Dim ccadena As String
ccadena = mio.apiLeerPropiedad("ARBA2025", "resultado", "", 0, 0)
If mio.UltimoMensajeError = "" Then
MsgBox (ccadena)
Dim cid As String
Dim cmessage As String
cmessage = mio.apiLeerPropiedad("ARBA2025", "diccionario.message", "", 0, 0)
If cmessage = "" Then
cid = mio.apiLeerPropiedad("ARBA2025", "diccionario.id", "", 0, 0)
MsgBox ("id DDJJ " + cid)
Else
MsgBox (cmessage)
End If
Else
MsgBox ("errorpropioed " + mio.UltimoMensajeError)
End If
Else
MsgBox ("eror metodo " + mio.UltimoMensajeError)
bresultado = False
End If
Else
bresultado = False
MsgBox ("error cargar propiedad " + mio.UltimoMensajeError)
End If
Else
MsgBox ("ticket vencido")
End If
Else
MsgBox ("error recuperar ticket" + mio.UltimoMensajeError)
End If
End If
Dim mio As Object
Dim bresultado As Boolean
bresultado = True
Dim curl As String
Rem URL del servidor (prueba o real) para descarga de PDF
curl = "https://app.test.arba.gov.ar/a122rSrv/api/external/comprobantePdf"
Dim crutaticket As String
Rem Ruta donde se guardó el token obtenido
crutaticket = "d:\ticket.txt"
Dim carchivoxmlenviado As String
Dim carchivoxmlrecibido As String
Rem Rutas para guardar el log de tráfico
carchivoxmlenviado = "d:\arbapet.txt"
carchivoxmlrecibido = "d:\arbaret.txt"
Dim ctoken As String
Dim numeroArchivo As Integer
numeroArchivo = 1
Rem Lectura del ticket de acceso
Open crutaticket For Input As #numeroArchivo
ctoken = Input(LOF(numeroArchivo), #numeroArchivo)
Close #numeroArchivo
Dim ccuit As String
Rem CUIT del agente
ccuit = "cuitagente"
Dim crutalicencia As String
Rem Ruta de la licencia del servicio
crutalicencia = "D:\cuitagente.lic"
Set mio = CreateObject("WSAFIPFE.misdatos")
If mio.iniciar(ccuit, "") Then
mio.tls = -1
mio.archivolicencia = crutalicencia
mio.ArchivoXMLEnviado = carchivoxmlenviado
mio.ArchivoXMLRecibido = carchivoxmlrecibido
' Cargamos parámetros iniciales
bresultado = mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.ticket", ctoken, 0, 0)
Dim cticket As String
If bresultado Then
' Verificamos si el ticket es válido
cticket = mio.apiLeerPropiedad("ARBA2025", "obtenerticket.ticketvigente", "", 0, 0)
If cticket = "SI" Then
bresultado = mio.apiCargarPropiedad("LIMPIAR", "", 0, 0)
' Configuración de la llamada GET para el PDF
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.URLMETODO", curl, 0, 0)
' CORREGIDO: El método es GET y el contenido es JSON
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.TIPOMETODO", "GET", 0, 0)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.TIPOCONTENIDO", "application/json", 0, 0)
' Parámetro de ejemplo (ID de comprobante)
bresultado = bresultado And mio.apiCargarPropiedad("ARBA2025.PARAMETROS.comprobante", "1", 0, 0)
If bresultado Then
If mio.apiEjecutar("ARBA2025") Then
Dim ccadena As String
' Leemos el resultado crudo
ccadena = mio.apiLeerPropiedad("ARBA2025", "resultado", "", 0, 0)
If mio.UltimoMensajeError = "" Then
Dim cmessage As String
cmessage = mio.apiLeerPropiedad("ARBA2025", "diccionario.error", "", 0, 0)
If cmessage = "" Then
' Si no hay error lógico, guardamos el PDF
' El tercer parámetro indica la ruta de destino del archivo binario
bresultado = mio.apiLeerPropiedad("ARBA2025", "diccionario.stack", "d:\archivo.pdf", 0, 0)
MsgBox "PDF descargado correctamente: " & mio.UltimoMensajeError
Else
MsgBox cmessage
End If
Else
MsgBox "Error propio: " & mio.UltimoMensajeError
End If
Else
MsgBox "Error metodo: " & mio.UltimoMensajeError
bresultado = False
End If
Else
bresultado = False
MsgBox "Error cargar propiedad: " & mio.UltimoMensajeError
End If
Else
MsgBox "Ticket vencido o inválido"
End If
Else
MsgBox "Error recuperar ticket: " & mio.UltimoMensajeError
End If
End If
Los datos de este servicio (tanto enviados como recibidos) son en formato json por lo que es recomendable tener claro como el método leerPropiedad ubica los datos de la respuesta (ver JSON) de igual forma el método cargarPropiedad.
Al autorizar un certificado de retención entre los datos a enviar figura el nTransaccionAgente un identifcador único (generado localmente) que permite luego rastrear el certificado. Ya que si por alguna razón hay un fallo de conexión (o error 500 o timeout o similar) y no se alcanza a recibir la respuesta simplmente podremos volver a enviar los mismos datos (con el mismo identificador) y habrá 2 alternativas:
1) si en la primera llamada el fallo se produjo ANTES de recibir los datos pero DESPUÉS que el servidor los enviara, la segunda llamada simplemente devolverá el error "Número de transacción ya existente para esta actividad y período" impidiendo que se duplique el certificado (en este se debe usar el método comprobantes para consultar y recuperar el certificado perdido).
2) Si en cambio la primera llamada no llego a ser procesada por el servidor la segunda se autorizará normalmente.
Tener en cuenta que esto solo se aplica si se trata de una interrupción de la conexión. Si se recibe una respuesta (aunque sea con error pero diferente al error 500 o timeout) se deben enviar nuevos datos corregidos y con un nuevo identifcador.
La planilla de test que figura al pie implementa los métodos y campos de la API para ejecutarlos mediante macros. debe ser ejecutada desde un excel de 32 bits y con macros habilitadas.
Tomando como referencia los ejemplos en visual basic 6 (o las macro de planilla) puede generar código en otros lenguajes teniendo en cuenta que en los ejemplos solo se realizan 3 acciones básicas: cargar el valor de una propiedad, llamar a un método con o sin argumentos, leer el valor de una propiedad. Para generar código en otros lenguajes introducir este prompt en un chat de IA (ChatGPT, gemini u otros) preferentemente desde una cuenta paga:
Prompt equivalencia ARBA: https://docs.google.com/document/d/1CW9Qp6uleRzir8iSZa1OtFiUgChDi8QS5csePjI8L94/edit?usp=sharing
Esta confirmada la compatibilidad con estos lenguajes:
Visual Basic 6.
Visual FoxPro.
COBOL (rm, wow, acu, microfocus, power, fujitsu).
NET.
Delphi (5, 9, 2009).
Windows.
PowerBuilder.
Clarion.
Paradox.
Office (excel, access)
el nombre y tipo de cada métodoy parámetro.
Desde la plataforma MisDatos puede adquirir soporte pago sin limites. Para ahorrar costos recomendamos antes leer esta guia y usar los prompt de IA sugeridos y solo usar el soporte pago para casos específicos o errores no documentados.
El correo promete: "pronto se actualizará dentro de 'Servicio web' dentro de la página de Arba". Sin embargo, la verificación realizada sobre la estructura pública del sitio arba.gov.ar y los resultados de búsqueda arrojan una discrepancia significativa.
Inexistencia de Acceso Público Directo: No existe en el menú principal de ARBA una sección denominada "Servicio web" accesible sin autenticación que contenga documentación de APIs.
Ubicación Probable: Basado en la arquitectura de información típica de ARBA, la documentación técnica suele residir en micrositios específicos ("Micrositio Agentes de Recaudación") o, más probablemente, dentro del entorno autenticado al que se accede con CUIT y Clave CIT.
Implicancia para Desarrolladores Externos: Esta arquitectura cerrada presenta una barrera de entrada para los desarrolladores de software que no son, en sí mismos, agentes de recaudación, sino proveedores de tecnología. Si la documentación solo es accesible tras el login de un Agente, los desarrolladores dependen de que sus clientes les descarguen y envíen los manuales (como ocurrió con el PDF analizado), lo cual es ineficiente y propenso a versiones desactualizadas.
Aunque el documento no utiliza explícitamente términos como "Cloud Computing" o "Nube", la infraestructura subyacente inferida de los endpoints (app2.test.arba.gov.ar) y la integración con Blockchain apuntan a una modernización tecnológica.
Balanceo de Carga: El uso de subdominios numéricos (app2) en el entorno de test sugiere la existencia de múltiples nodos de aplicación balanceados para soportar la carga concurrente de pruebas.
Dependencia Externa (Blockchain): La API de ARBA actúa como un orquestador que consulta servicios externos (Padrón Federal). Esto implica que la disponibilidad del servicio A122R no depende solo de los servidores de ARBA, sino de la salud de la red Blockchain de la Comisión Arbitral. Si el "servicio de Blockchain" se cae (escenario contemplado en las validaciones de la v5.0), ARBA debe activar mecanismos de contingencia (fallback) para permitir la operación local.
Al comparar los manuales v2.0 y v5.0 , se observa que los fundamentos arquitectónicos se mantienen, pero la implementación se ha endurecido.
Ambas versiones utilizan REST sobre HTTPS. El intercambio de datos es mediante JSON (inferido por los ejemplos de respuesta {"id": 0...}).
Autenticación: Se basa en un Token. La v5.0 añade una capa de validación explícita: "El Cuit del agente... debe coincidir con el cuit del agente que generó el token".
Implicancia de Seguridad: Esto previene ataques de suplantación donde un usuario autenticado (con un token válido) intenta enviar declaraciones juradas en nombre de otro CUIT (por ejemplo, un contador que maneja múltiples empresas). La v5.0 hace mandatorio el chequeo de correspondencia biunívoca entre la identidad del token y el cuitAgente del payload, rechazando la operación si no coinciden.
Se mantienen las URLs base diferenciadas:
TEST: https://app2.test.arba.gov.ar/a122rSrv/api/external/
PRODUCCIÓN: https://app.arba.gov.ar/a122rSrv/api/external/
La persistencia de app2 en test durante 4 meses (desde octubre a enero) sugiere que es un entorno estable y persistente, no efímero.
El servicio POST /declaracionJurada es la puerta de entrada al flujo de trabajo. Sin un ID de DJ válido, no se pueden cargar comprobantes.
Parámetro
Versión 2.0 (Oct 2025)
Versión 5.0 (Ene 2026)
Análisis del Cambio
Identificador Agente
cuit (N11)
cuitAgente (N11)
Cambio de Nombre (Breaking Change)
Actividad
actividadId (N2)
actividadId (N2)
Sin cambios
Período - Año
anio (N4)
anio (N4)
Sin cambios
Período - Mes
mes (N2)
Mes (N2)
Cambio de capitalización (documentación)
Quincena
quincena (N2)
quincena (N2)
Sin cambios
Análisis de Impacto:
El renombrado de cuit a cuitAgente es una modificación crítica que rompe la compatibilidad hacia atrás. Cualquier script desarrollado con la especificación v2.0 fallará inmediatamente.
Racionalidad: Es probable que este cambio busque homogeneizar la nomenclatura con el servicio de Alta de Comprobante, que ya utilizaba cuitAgente. La consistencia semántica reduce la carga cognitiva del desarrollador y facilita el mantenimiento del código.
La versión 2.0 era opaca respecto a la respuesta, delegando la explicación al Swagger. La versión 5.0 es explícita y revela una lógica de negocio mucho más compleja en el backend.
Objeto de Respuesta v5.0:
JSON
{
"id": 0,
"fechaVencimiento": "datetime",
"rectificativa": 0,
"fechaCierre": "datetime",
"totalRetenciones": 0,
"tieneLotePendiente": true,
"tieneObservaciones": true,
"tieneErrores": true
...
}
Nuevas Lógicas Detectadas:
Manejo de Rectificativas: La v5.0 introduce el concepto de "DJ Cerrada". Si se intenta iniciar una DJ para un período que ya fue cerrado, el sistema no devuelve un error bloqueante, sino que genera automáticamente una rectificativa. El mensaje "Importante se da de alta la rectificativa" instruye al desarrollador a cargar solo las novedades. Esto es un cambio fundamental respecto a sistemas anteriores que requerían la anulación total de la presentación original.
Estado del Lote: El campo tieneLotePendiente sugiere que el sistema soporta procesamiento asíncrono o híbrido (carga manual + carga por API), y alerta al desarrollador si hay procesos en cola que podrían afectar el saldo de la DJ.
El endpoint POST /comprobante es donde reside la mayor carga transaccional y donde se han introducido las medidas de control más estrictas en la v5.0.
En la versión 2.0, no existía un mecanismo claro para prevenir la duplicación de comprobantes ante reintentos de red. Si un agente enviaba un comprobante, la conexión fallaba (timeout), y el agente reintentaba, ARBA podía terminar con dos retenciones idénticas, duplicando la deuda del agente y el crédito del contribuyente.
La Solución v5.0: Se introduce el campo nTransaccionAgente como OBLIGATORIO (SI).
Especificación: String de hasta 20 caracteres, debe ser numérico.
Regla de Unicidad: "Se valida que para la misma actividad y periodo no se ingrese duplicado el nro de transacción del agente".
Impacto: Esto transfiere la responsabilidad de la unicidad al sistema del Agente. El ERP (SAP, Tango, etc.) debe generar un ID único para cada retención y persistirlo. Ante un fallo de red, el ERP puede reintentar el envío con el mismo ID; si ARBA ya lo procesó, devolverá un error de "Transacción existente" en lugar de crear un duplicado. Este patrón es el estándar de oro en diseño de APIs financieras y marca una maduración técnica significativa del equipo de ARBA.
La versión 5.0 elimina el campo mes del payload de Alta de Comprobante.
Análisis: Dado que el comprobante se vincula obligatoriamente a una DJ (vía idDj), y la DJ ya tiene un mes y año asignados, solicitar el mes nuevamente en cada comprobante era redundante y abría la puerta a inconsistencias (ej. adjuntar un comprobante de "Marzo" a una DJ de "Febrero"). La eliminación normaliza el modelo de datos.
Se introduce una regla de tolerancia monetaria:
Regla: Abs(ImporteRetencion - (BaseImponible * Alicuota)) < $1.00.
Contexto Técnico: Los sistemas informáticos manejan los números decimales de formas diferentes (Coma flotante en JavaScript vs. Decimal en SQL/Java). Estas diferencias a menudo resultan en discrepancias de centavos (ej. 100.00 * 0.03 puede dar 2.999999999).
Impacto: La v2.0 probablemente rechazaba estas discrepancias o las aceptaba ciegamente. La v5.0 formaliza un "buffer" de 1 peso para absorber los errores de redondeo de las distintas plataformas de desarrollo, reduciendo la fricción de integración sin comprometer la integridad fiscal significativa.
Una de las revelaciones más significativas de la documentación v5.0 es la mención explícita a la tecnología subyacente de validación: "Padrón Federal (Blockchain con información de Ingresos Brutos)".
El Padrón Federal es una iniciativa de la Comisión Arbitral del Convenio Multilateral y la AFIP para unificar los registros tributarios provinciales. El uso de Blockchain (cadena de bloques) garantiza que todas las jurisdicciones (Provincias) tengan una vista inmutable y consensuada del estado de un contribuyente.
Cuando la API recibe un cuitContribuyente:
Consulta Externa: ARBA interroga al nodo de Blockchain del Padrón Federal.
Prioridad de Datos: Si el CUIT existe y está activo en la cadena, ARBA utilizará la RazonSocial oficial registrada en el Blockchain, ignorando potencialmente la que envía el agente en el campo razonSocialContribuyente.
Mecanismo de Fallback: La documentación v5.0 es pragmática. Reconoce que la tecnología puede fallar. "Si... no está disponible el servicio de Blockchain, se toman los datos de entrada en el servicio".
Implicancia: Los desarrolladores deben enviar siempre la Razón Social correcta, no pueden confiar en que el sistema la "autocompletará", porque en caso de caída del servicio de Blockchain (timeout o downtime), el dato enviado será el que quede registrado legalmente en el comprobante.
La versión 2.0 era esencialmente un "buzón de entrada" (solo POST y DELETE). La versión 5.0 transforma la API en una herramienta de gestión bidireccional mediante la incorporación de métodos GET.
Este nuevo endpoint es vital para los procesos de auditoría y conciliación.
Filtros: Permite buscar por idDj, cuitAgente, cuitContribuyente, periodo y estado.
Caso de Uso: Un Agente masivo (ej. Supermercado) envía un lote de 10,000 retenciones. Al final del proceso, su sistema puede invocar este endpoint filtrando por estado: ACTIVO y comparar la lista devuelta por ARBA contra su base de datos interna para asegurar que no falta nada.
Datos Devueltos: Incluye nroEmision (el número oficial de comprobante generado por ARBA) y fechaAceptacion.
Se estandariza la capacidad de descargar la información en formatos legacy (TXT) para compatibilidad con sistemas contables antiguos, y en PDF para el cumplimiento de la obligación de entregar constancia al retenido.
Restricción de Integridad: La v5.0 aclara que para obtener el PDF, el comprobante no debe tener observaciones. Esto impide la emisión de documentos inválidos que podrían ser rechazados posteriormente, protegiendo al agente de generar responsabilidad fiscal indebida.
Basado en las diferencias identificadas, se propone la siguiente hoja de ruta para los equipos técnicos que deben migrar de la integración v2.0 a la v5.0 antes de marzo de 2026.
Actualización del Modelo de Datos (DJ): Modificar todas las llamadas al servicio de inicio de DJ para reemplazar el campo cuit por cuitAgente. Verificar que el parseo de la respuesta capture los nuevos campos de estado de rectificativa.
Generación de IDs Transaccionales: Implementar lógica en el ERP para generar UUIDs o secuencias numéricas únicas para el campo nTransaccionAgente. Advertencia: Aunque el campo es string, la documentación exige que sea numérico. Se recomienda usar secuencias numéricas (ej. 2026012200001) en lugar de UUIDs alfanuméricos para evitar rechazos de validación.
Manejo de Errores de Validación: Implementar bloques try-catch específicos para manejar los códigos de error relacionados con discrepancias matemáticas (tolerancia $1) y validaciones de CUIT contra Blockchain.
Dado que el entorno de test (app2.test.arba.gov.ar) es persistente, se recomienda:
Limpieza de Entorno: Antes de correr baterías de pruebas automatizadas, invocar el borrado de DJs pendientes vía web (como sugiere el manual) para evitar colisiones de períodos.
Prueba de Estrés de Idempotencia: Enviar intencionalmente el mismo comprobante dos veces con el mismo nTransaccionAgente para verificar que la API devuelve el error correcto y no duplica el registro.
Simulación de Fallo de Blockchain: Si es posible, probar con CUITs inexistentes o inválidos para verificar que el sistema recurre a los datos de Razón Social proporcionados en el payload (Fallback).
La transición a la versión 5.0 de la API de Servicios A122R no es una mera actualización incremental; es una refundación de las reglas de intercambio de información tributaria entre los agentes privados y el estado provincial.
La inclusión de Blockchain para la validación de identidad federal y la imposición de transaccionalidad estricta (idempotencia) posicionan a esta API como una de las más avanzadas en el ecosistema de gobierno digital argentino. Sin embargo, la madurez tecnológica del backend contrasta con la precariedad de los canales de comunicación (distribución por email, listas no segmentadas) y la opacidad de la documentación pública en el sitio web.
Para los desarrolladores y empresas, el mensaje es claro: la v2.0 está obsoleta y su lógica es incompatible con los nuevos requisitos de integridad de datos. La prórroga hasta marzo de 2026 es una ventana de oportunidad crítica que no debe desaprovecharse, dado que la complejidad de las nuevas validaciones (especialmente la conciliación con el Padrón Federal) requerirá ciclos de prueba extensos.
La "nube" de ARBA ha dejado de ser un repositorio pasivo de declaraciones juradas para convertirse en un validador activo de la realidad fiscal, y los sistemas de los contribuyentes deben evolucionar para dialogar con esta nueva autoridad digital en tiempo real.
Fin del Informe.