Referencia · v1.0.0

Referencia

Generada del contrato OpenAPI 3.1.0. Cómo autenticarse, la idempotencia, los webhooks y los errores están explicados en la guía.

  • https://autoinvoice.com.arPROD, sólo acepta claves mf_live_
  • https://test.autoinvoice.com.arTEST, sólo acepta claves mf_test_

Todas las respuestas llevan Cache-Control: no-store: no se repite en cada endpoint.

Endpoints

Pedir un comprobante

POST /v1/comprobantes

Repetir el pedido con el mismo Idempotency-Key y el mismo cuerpo devuelve el mismo comprobante, en su estado actual, y no crea otro. La comparación es por contenido: el orden de los campos o escribir 121 en vez de 121.00 no cambia el pedido. La misma clave con otro cuerpo es un 409. Ante un 500 o un corte, hay que repetir con la misma clave.

Pide la clave de API: autenticación.

Parámetros

NombreEnTipoDescripción
Idempotency-Keyobligatorio encabezado string

Clave elegida por el cliente, única por pedido.

  • Patrón: ^[\x21-\x7e]{1,255}$

Cuerpo del pedido

application/json, obligatorio. Schema: PedidoComprobante .

Sin importes calculados ni fecha: un cuerpo que los traiga se rechaza. El punto de venta sale de la configuración de la cuenta.

CampoTipoDescripción
tipoobligatoriointeger

1 factura A, 6 factura B. Tiene que corresponder a la condición del receptor.

  • Valores: 1, 6
conceptoobligatoriointeger

1 productos, 2 servicios, 3 ambos.

  • Valores: 1, 2, 3
receptorobligatorioReceptor
renglonesobligatorioRenglon[]
  • Elementos: de 1 a 200
servicio_desdeopcionalFecha
servicio_hastaopcionalFecha
vencimiento_pagoopcionalFecha
condicion_ventaopcionalCondicionVenta

Por defecto, contado.

  • Si concepto es 2 o 3: son obligatorios servicio_desde, servicio_hasta, vencimiento_pago.
  • Si no: servicio_desde no se admite; servicio_hasta no se admite; vencimiento_pago no se admite.
  • No admite campos que no estén en esta tabla.
Ejemplo del contratojson
{
  "tipo": 6,
  "concepto": 2,
  "receptor": {
    "doc_tipo": 96,
    "doc_nro": "30111222",
    "condicion_iva": 5,
    "nombre": "Ana Pérez",
    "domicilio": "San Martín 123, Rosario"
  },
  "renglones": [
    {
      "descripcion": "Abono mensual",
      "importe": "121.00",
      "alicuota": 21
    }
  ],
  "servicio_desde": "2026-11-01",
  "servicio_hasta": "2026-11-30",
  "vencimiento_pago": "2026-12-10",
  "condicion_venta": "contado"
}

Respuestas

CódigoQué significaCuerpo
202

Pedido aceptado. El cuerpo es el comprobante en su estado actual.

  • Location . Dónde consultar el comprobante.
application/json
Comprobante
400

Falta el Idempotency-Key, es inválido, o el cuerpo no es JSON válido.

application/problem+json
Problema
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
409

El Idempotency-Key ya se usó con otro cuerpo, o a la cuenta le falta el punto de venta o sus datos fiscales de emisor. title dice cuál. No se encoló nada.

application/problem+json
Problema
413

El cuerpo supera los 256 KB.

application/problem+json
Problema
415

El cuerpo no es application/json, o viene comprimido.

application/problem+json
Problema
422

El pedido está bien formado pero no se puede emitir. errores dice por qué. No se encoló nada.

application/problem+json
ProblemaDeValidacion
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
Pedidobash
curl -X POST 'https://test.autoinvoice.com.ar/v1/comprobantes' \
  -H 'Authorization: Bearer mf_test_...' \
  -H 'Idempotency-Key: pago-1234' \
  -H 'Content-Type: application/json' \
  -d '{
  "tipo": 6,
  "concepto": 2,
  "receptor": {
    "doc_tipo": 96,
    "doc_nro": "30111222",
    "condicion_iva": 5,
    "nombre": "Ana Pérez",
    "domicilio": "San Martín 123, Rosario"
  },
  "renglones": [
    {
      "descripcion": "Abono mensual",
      "importe": "121.00",
      "alicuota": 21
    }
  ],
  "servicio_desde": "2026-11-01",
  "servicio_hasta": "2026-11-30",
  "vencimiento_pago": "2026-12-10",
  "condicion_venta": "contado"
}'
Respuesta 202 · armada desde el schemajson
{
  "id": "0b8f3c2e-6a1d-4f5b-9c7e-2d4a6b8c1e3f",
  "estado": "procesando",
  "en_revision": false,
  "cuit_emisor": "11111111111",
  "punto_venta": 1,
  "tipo": 1,
  "numero": null,
  "concepto": 1,
  "fecha": "2026-11-10",
  "servicio_desde": null,
  "servicio_hasta": null,
  "vencimiento_pago": null,
  "receptor": {
    "doc_tipo": 80,
    "doc_nro": "11",
    "condicion_iva": 1,
    "nombre": "texto",
    "domicilio": "texto",
    "email": "ana@ejemplo.com"
  },
  "renglones": [
    {
      "descripcion": "texto",
      "importe": "21.11",
      "alicuota": 21
    }
  ],
  "condicion_venta": "contado",
  "importe_neto": "11.11",
  "importe_iva": "11.11",
  "importe_total": "11.11",
  "cae": null,
  "cae_vencimiento": null,
  "emitido_en": null,
  "comprobante_asociado_id": null,
  "rechazo": null,
  "creado_en": "2026-11-10T14:30:00Z"
}

Los valores son ilustrativos; la forma es la del contrato.

Consultar un comprobante

GET /v1/comprobantes/{id}

Pide la clave de API: autenticación.

Parámetros

NombreEnTipoDescripción
idobligatorio ruta string

Respuestas

CódigoQué significaCuerpo
200

El comprobante en su estado actual.

application/json
Comprobante
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

No hay un comprobante de este cliente con ese id. La respuesta no distingue si existe para otro.

application/problem+json
Problema
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
Pedidobash
curl -X GET 'https://test.autoinvoice.com.ar/v1/comprobantes/<id>' \
  -H 'Authorization: Bearer mf_test_...'
Respuesta 200 · armada desde el schemajson
{
  "id": "0b8f3c2e-6a1d-4f5b-9c7e-2d4a6b8c1e3f",
  "estado": "procesando",
  "en_revision": false,
  "cuit_emisor": "11111111111",
  "punto_venta": 1,
  "tipo": 1,
  "numero": null,
  "concepto": 1,
  "fecha": "2026-11-10",
  "servicio_desde": null,
  "servicio_hasta": null,
  "vencimiento_pago": null,
  "receptor": {
    "doc_tipo": 80,
    "doc_nro": "11",
    "condicion_iva": 1,
    "nombre": "texto",
    "domicilio": "texto",
    "email": "ana@ejemplo.com"
  },
  "renglones": [
    {
      "descripcion": "texto",
      "importe": "21.11",
      "alicuota": 21
    }
  ],
  "condicion_venta": "contado",
  "importe_neto": "11.11",
  "importe_iva": "11.11",
  "importe_total": "11.11",
  "cae": null,
  "cae_vencimiento": null,
  "emitido_en": null,
  "comprobante_asociado_id": null,
  "rechazo": null,
  "creado_en": "2026-11-10T14:30:00Z"
}

Los valores son ilustrativos; la forma es la del contrato.

Pedir una nota de crédito sobre una factura

POST /v1/comprobantes/{id}/notas-de-credito

Sólo sobre una factura emitida. La nota toma de la factura la letra (factura A → nota de crédito A, tipo 3; factura B → nota de crédito B, tipo 8), el receptor, el concepto, el período del servicio y la condición de venta, y sale del mismo CUIT, por el punto de venta actual de la cuenta. A ARCA va informada la factura que corrige.

Sin renglones es una nota por el total de la factura. Con renglones, por lo que digan: cada uno con una alícuota que la factura tenga. Sumada a las otras notas de la misma factura que no fueron rechazadas, nunca supera su total ni lo facturado en cada alícuota; dos pedidos simultáneos que juntos se pasan no salen los dos.

El Idempotency-Key funciona igual que al pedir una factura, y es uno por pedido entre facturas y notas.

Pide la clave de API: autenticación.

Parámetros

NombreEnTipoDescripción
idobligatorio ruta string

El id de la factura que se corrige.

Idempotency-Keyobligatorio encabezado string

Clave elegida por el cliente, única por pedido.

  • Patrón: ^[\x21-\x7e]{1,255}$

Cuerpo del pedido

application/json, obligatorio. Schema: PedidoNotaDeCredito .

Sin renglones, la nota es por el total de la factura. Sin importes calculados ni fecha.

CampoTipoDescripción
renglonesopcionalRenglon[]
  • Elementos: de 1 a 200
  • No admite campos que no estén en esta tabla.
Ejemplo del contratojson
{
  "renglones": [
    {
      "descripcion": "Devolución parcial del abono",
      "importe": "60.50",
      "alicuota": 21
    }
  ]
}

Respuestas

CódigoQué significaCuerpo
202

Pedido aceptado. El cuerpo es la nota de crédito en su estado actual.

  • Location . Dónde consultar la nota de crédito.
application/json
Comprobante
400

Falta el Idempotency-Key, es inválido, o el cuerpo no es JSON válido.

application/problem+json
Problema
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

No hay un comprobante de este cliente con ese id. La respuesta no distingue si existe para otro.

application/problem+json
Problema
409

El comprobante no es una factura o todavía no está emitido; se emitió con un CUIT distinto del que tiene hoy la cuenta; la nota superaría a la factura sumada a las otras; el Idempotency-Key ya se usó con otro cuerpo; o a la cuenta le falta el punto de venta o sus datos fiscales. title dice cuál. No se encoló nada.

application/problem+json
Problema
413

El cuerpo supera los 256 KB.

application/problem+json
Problema
415

El cuerpo no es application/json, o viene comprimido.

application/problem+json
Problema
422

El pedido está bien formado pero no se puede emitir. errores dice por qué. No se encoló nada.

application/problem+json
ProblemaDeValidacion
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
Pedidobash
curl -X POST 'https://test.autoinvoice.com.ar/v1/comprobantes/<id>/notas-de-credito' \
  -H 'Authorization: Bearer mf_test_...' \
  -H 'Idempotency-Key: pago-1234' \
  -H 'Content-Type: application/json' \
  -d '{
  "renglones": [
    {
      "descripcion": "Devolución parcial del abono",
      "importe": "60.50",
      "alicuota": 21
    }
  ]
}'
Respuesta 202 · armada desde el schemajson
{
  "id": "0b8f3c2e-6a1d-4f5b-9c7e-2d4a6b8c1e3f",
  "estado": "procesando",
  "en_revision": false,
  "cuit_emisor": "11111111111",
  "punto_venta": 1,
  "tipo": 1,
  "numero": null,
  "concepto": 1,
  "fecha": "2026-11-10",
  "servicio_desde": null,
  "servicio_hasta": null,
  "vencimiento_pago": null,
  "receptor": {
    "doc_tipo": 80,
    "doc_nro": "11",
    "condicion_iva": 1,
    "nombre": "texto",
    "domicilio": "texto",
    "email": "ana@ejemplo.com"
  },
  "renglones": [
    {
      "descripcion": "texto",
      "importe": "21.11",
      "alicuota": 21
    }
  ],
  "condicion_venta": "contado",
  "importe_neto": "11.11",
  "importe_iva": "11.11",
  "importe_total": "11.11",
  "cae": null,
  "cae_vencimiento": null,
  "emitido_en": null,
  "comprobante_asociado_id": null,
  "rechazo": null,
  "creado_en": "2026-11-10T14:30:00Z"
}

Los valores son ilustrativos; la forma es la del contrato.

Descargar el PDF de un comprobante emitido

GET /v1/comprobantes/{id}/pdf

Devuelve el archivo directamente, sin URL firmada. El contenido sale de lo que autorizó ARCA y de los datos congelados al crear el comprobante: el mismo comprobante da siempre el mismo archivo.

Pide la clave de API: autenticación.

Parámetros

NombreEnTipoDescripción
idobligatorio ruta string

Respuestas

CódigoQué significaCuerpo
200

El PDF.

  • Content-Disposition . Sugiere el nombre del archivo.
application/pdf
binario (application/pdf)
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

No hay un comprobante de este cliente con ese id. La respuesta no distingue si existe para otro.

application/problem+json
Problema
409

No hay PDF para servir. title dice por qué: el comprobante no está emitido (todavía, o fue rechazado); se creó sin los datos del emisor; o el archivo generado no coincide con el original, caso en el que no se sirve y lo revisa una persona. Reintentar sólo sirve en el primer caso, cuando el comprobante esté emitido.

application/problem+json
Problema
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
Pedidobash
curl -X GET 'https://test.autoinvoice.com.ar/v1/comprobantes/<id>/pdf' \
  -H 'Authorization: Bearer mf_test_...' \
  -o 'archivo.pdf'

Volver a enviar el resultado de un comprobante

POST /v1/comprobantes/{id}/webhook/reenviar

Encola otra entrega del último evento de resultado, con el mismo id, sin tocar el comprobante. Sirve después de un webhook_agotado, o si el receptor perdió el mensaje. Si ese evento ya está esperando entrega no se agrega otra: repetir el pedido es seguro. Cada reenvío tiene otras 24 horas de reintentos. Tiene el mismo tope de pendientes por cuenta que los pedidos: pasado ese tope responde 429, salvo que el evento ya esté esperando.

Pide la clave de API: autenticación.

Parámetros

NombreEnTipoDescripción
idobligatorio ruta string

Respuestas

CódigoQué significaCuerpo
202

Entrega encolada. El resultado llega al webhook, no a esta respuesta.

application/json
ReenvioEncolado
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

No hay un comprobante de este cliente con ese id. La respuesta no distingue si existe para otro.

application/problem+json
Problema
409

No hay nada que enviar. title dice por qué: la cuenta no tiene webhook registrado, o el comprobante todavía no tiene un resultado.

application/problem+json
Problema
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
503

La entrega de webhooks no está encendida en este ambiente. No se registró ni se encoló nada.

application/problem+json
Problema
Pedidobash
curl -X POST 'https://test.autoinvoice.com.ar/v1/comprobantes/<id>/webhook/reenviar' \
  -H 'Authorization: Bearer mf_test_...'
Respuesta 202 · armada desde el schemajson
{
  "evento": {
    "id": "0b8f3c2e-6a1d-4f5b-9c7e-2d4a6b8c1e3f",
    "tipo": "comprobante.emitido"
  }
}

Los valores son ilustrativos; la forma es la del contrato.

Consultar el webhook de la cuenta

GET /v1/webhook

El secreto no se vuelve a mostrar.

Pide la clave de API: autenticación.

Respuestas

CódigoQué significaCuerpo
200

El webhook registrado.

application/json
Webhook
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

La cuenta no tiene un webhook registrado.

application/problem+json
Problema
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
Pedidobash
curl -X GET 'https://test.autoinvoice.com.ar/v1/webhook' \
  -H 'Authorization: Bearer mf_test_...'
Respuesta 200 · armada desde el schemajson
{
  "url": "https://sistema.ejemplo.com/modofactura/eventos",
  "creado_en": "2026-11-10T14:30:00Z",
  "actualizado_en": "2026-11-10T14:30:00Z"
}

Los valores son ilustrativos; la forma es la del contrato.

Dar de alta el webhook o cambiar su URL

PUT /v1/webhook

Hay un webhook por cuenta. El alta responde 201 con el secreto, que se muestra UNA SOLA VEZ: si se pierde, hay que rotarlo. Con un webhook ya registrado cambia la URL, conserva el secreto y responde 200; lo que esté pendiente de entrega sale a la URL nueva.

La URL tiene que ser https, sin credenciales, y resolver sólo a direcciones públicas. Se vuelve a verificar antes de cada entrega.

Pide la clave de API: autenticación.

Cuerpo del pedido

application/json, obligatorio. Schema: PedidoWebhook .

CampoTipoDescripción
urlobligatoriostring (uri)

https, sin credenciales, y con un destino público.

  • Largo: hasta 2048
  • No admite campos que no estén en esta tabla.
Ejemplo del contratojson
{
  "url": "https://sistema.ejemplo.com/modofactura/eventos"
}

Respuestas

CódigoQué significaCuerpo
200

La URL cambió.

application/json
Webhook
201

Webhook creado. Es la única vez que se muestra el secreto.

application/json
WebhookConSecreto
400

El cuerpo no es JSON válido.

application/problem+json
Problema
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
413

El cuerpo supera los 256 KB.

application/problem+json
Problema
415

El cuerpo no es application/json, o viene comprimido.

application/problem+json
Problema
422

La URL no se admite. Un destino que no resuelve y uno interno dan el mismo error.

application/problem+json
ProblemaDeValidacion
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
503

La entrega de webhooks no está encendida en este ambiente. No se registró ni se encoló nada.

application/problem+json
Problema
Pedidobash
curl -X PUT 'https://test.autoinvoice.com.ar/v1/webhook' \
  -H 'Authorization: Bearer mf_test_...' \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://sistema.ejemplo.com/modofactura/eventos"
}'
Respuesta 200 · armada desde el schemajson
{
  "url": "https://sistema.ejemplo.com/modofactura/eventos",
  "creado_en": "2026-11-10T14:30:00Z",
  "actualizado_en": "2026-11-10T14:30:00Z"
}

Los valores son ilustrativos; la forma es la del contrato.

Borrar el webhook de la cuenta

DELETE /v1/webhook

Lo que esté pendiente de entrega se descarta. Una URL nueva necesita un alta, con otro secreto.

Pide la clave de API: autenticación.

Respuestas

CódigoQué significaCuerpo
204

Borrado.

sin cuerpo
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

La cuenta no tiene un webhook registrado.

application/problem+json
Problema
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
Pedidobash
curl -X DELETE 'https://test.autoinvoice.com.ar/v1/webhook' \
  -H 'Authorization: Bearer mf_test_...'

Rotar el secreto del webhook

POST /v1/webhook/secreto

Genera un secreto nuevo y lo muestra UNA SOLA VEZ. Vale al instante: lo pendiente sale firmado con el nuevo, y lo que el receptor rechace mientras se cambia se reintenta solo.

Pide la clave de API: autenticación.

Respuestas

CódigoQué significaCuerpo
200

Secreto nuevo.

application/json
WebhookConSecreto
401

La clave falta, es inválida, está revocada o es de otro ambiente. La respuesta no distingue cuál.

  • WWW-Authenticate
application/problem+json
Problema
404

La cuenta no tiene un webhook registrado.

application/problem+json
Problema
429

Se superó el límite de pedidos del cliente, su tope de pedidos sin procesar, el de autenticaciones fallidas de la IP, o hay demasiados PDF generándose a la vez. Por defecto, 300 pedidos por minuto por cliente, 1000 sin procesar por cliente y 20 autenticaciones fallidas por minuto por IP. Reintentar con el mismo Idempotency-Key es seguro.

  • Retry-After . Segundos hasta poder volver a intentar.
application/problem+json
Problema
500

Error interno, sin detalles. Se puede reintentar; en un POST, con el mismo Idempotency-Key.

application/problem+json
Problema
503

La entrega de webhooks no está encendida en este ambiente. No se registró ni se encoló nada.

application/problem+json
Problema
Pedidobash
curl -X POST 'https://test.autoinvoice.com.ar/v1/webhook/secreto' \
  -H 'Authorization: Bearer mf_test_...'
Respuesta 200 · armada desde el schemajson
{
  "url": "https://sistema.ejemplo.com/modofactura/eventos",
  "creado_en": "2026-11-10T14:30:00Z",
  "actualizado_en": "2026-11-10T14:30:00Z",
  "secreto": "mf_whsec_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
}

Los valores son ilustrativos; la forma es la del contrato.

Webhooks

Pedidos que ModoFactura le hace a tu sistema, a la URL que registraste.

Resultado de un comprobante

POST URL de tu webhook

Cada POST lleva X-ModoFactura-Firma: t=<unix>,v1=<hex>: HMAC-SHA256 en hexadecimal, con el secreto entero como clave, sobre <t>.<cuerpo crudo>. Hay que verificarlo contra los bytes recibidos, antes de interpretar el JSON, y rechazar un t con más de 5 minutos de diferencia. Cada intento firma con su propio t. La documentación trae un ejemplo de verificación.

La entrega es «al menos una vez» y sin orden garantizado: un mismo evento puede llegar más de una vez, siempre con el mismo id, y conviene deduplicar por ese campo. comprobante.estado es el estado al momento de entregar. Cualquier 2xx confirma; todo lo demás, también un 3xx, se reintenta con espera creciente durante 24 horas. No se siguen redirecciones, y el pedido se corta a los 10 segundos.

Encabezados que manda ModoFactura

NombreEnTipoDescripción
X-ModoFactura-Firmaobligatorio encabezado string
  • Patrón: ^t=[0-9]+,v1=[0-9a-f]{64}$

Cuerpo que recibís

application/json, obligatorio. Schema: EventoWebhook .

comprobante.emitido: ARCA autorizó, y trae número y CAE. comprobante.rechazado: ARCA dijo que no; motivo trae lo mismo que rechazo en el GET. comprobante.error_datos: los datos del comprobante no se pueden enviar a ARCA; sigue procesando hasta que lo resuelva una persona. comprobante.en_revision: espera la revisión de una persona; sigue procesando y no hace falta pedirlo de nuevo. Estos dos últimos no se entregan si el comprobante se resolvió mientras esperaban: llega el resultado. comprobante.descartado: ModoFactura lo cerró sin mandarlo a ARCA; no tiene número ni CAE y no va a cambiar más.

CampoTipoDescripción
idobligatoriostring (uuid)

Estable. Se repite en cada reintento y en un reenvío, para deduplicar.

tipoobligatorioTipoEventoWebhook
creado_enobligatoriostring (date-time)

Cuándo pasó, no cuándo se entregó.

comprobanteobligatorioComprobanteDelEvento
motivoopcionalstring

Legible. No trae más que lo que muestra el GET del comprobante.

  • Largo: desde 1
  • Si tipo es comprobante.emitido: motivo no se admite; comprobante.estado es emitido; comprobante.numero es integer desde 1; comprobante.cae es string; comprobante.cae_vencimiento es string.
  • Si no: motivo es obligatorio; comprobante.numero es null; comprobante.cae es null; comprobante.cae_vencimiento es null.
  • Si tipo es comprobante.error_datos o comprobante.en_revision: comprobante.estado es procesando.
  • Si tipo es comprobante.rechazado: comprobante.estado es rechazado.
  • Si tipo es comprobante.descartado: comprobante.estado es descartado.
  • No admite campos que no estén en esta tabla.
Ejemplo armado desde el schemajson
{
  "id": "0b8f3c2e-6a1d-4f5b-9c7e-2d4a6b8c1e3f",
  "tipo": "comprobante.emitido",
  "creado_en": "2026-11-10T14:30:00Z",
  "comprobante": {
    "id": "0b8f3c2e-6a1d-4f5b-9c7e-2d4a6b8c1e3f",
    "estado": "emitido",
    "tipo": 1,
    "punto_venta": 1,
    "numero": 1,
    "cae": "11111111111111",
    "cae_vencimiento": "2026-11-10",
    "fecha": "2026-11-10",
    "comprobante_asociado_id": null
  }
}

Los valores son ilustrativos; la forma es la del contrato.

Respuestas

CódigoQué significaCuerpo
200

Recibido. Vale cualquier 2xx, y la respuesta se descarta.

sin cuerpo

Schemas

Fecha

Tipo string (date) .

AAAA-MM-DD

Importe

Tipo string . Patrón: ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,2})?$.

En pesos, como texto para no perder precisión.

Receptor

Tipo object .

CampoTipoDescripción
doc_tipoobligatoriointeger

80 CUIT, 86 CUIL, 87 CDI, 96 DNI, 99 sin identificar.

  • Valores: 80, 86, 87, 96, 99
doc_nroobligatoriostring

CUIT, CUIL o CDI con dígito verificador válido, DNI, o "0" si no se identifica.

  • Patrón: ^[0-9]{1,11}$
condicion_ivaobligatoriointeger

Condición frente al IVA, código de ARCA (RG 5616). La declara el cliente; ARCA la cruza con su padrón al autorizar. Con DNI o sin identificar, sólo 5 (consumidor final).

  • Valores: 1, 4, 5, 6, 7, 8, 9, 10, 13, 15, 16
nombreopcionalstring

Nombre o razón social. Va en el PDF, no a ARCA. Obligatorio con CUIT. Sin caracteres de control.

  • Largo: de 1 a 200
domicilioopcionalstring

Va en el PDF, no a ARCA. Obligatorio con CUIT. Sin caracteres de control.

  • Largo: de 1 a 300
emailopcionalstring (email)

Opcional. Si viene, el comprobante emitido se le manda por mail con el PDF adjunto, desde no-responder@modoagrario.com y con la razón social del emisor como nombre. Las notas de crédito van al mismo mail que su factura. No va a ARCA ni al PDF.

  • Largo: hasta 254
  • Si doc_tipo es 80: son obligatorios nombre, domicilio.
  • No admite campos que no estén en esta tabla.

CondicionVenta

Tipo string . Valores: contado, cuenta_corriente, tarjeta_debito, tarjeta_credito, transferencia, cheque, otra.

Se imprime en el PDF. No viaja a ARCA.

Renglon

Tipo object .

CampoTipoDescripción
descripcionobligatoriostring
  • Largo: de 1 a 500
importeobligatorioImporte

Precio final del renglón, IVA incluido. Mayor a cero.

alicuotaobligatorionumber
  • Valores: 21, 10.5, 27
  • No admite campos que no estén en esta tabla.

PedidoComprobante

Tipo object .

Sin importes calculados ni fecha: un cuerpo que los traiga se rechaza. El punto de venta sale de la configuración de la cuenta.

CampoTipoDescripción
tipoobligatoriointeger

1 factura A, 6 factura B. Tiene que corresponder a la condición del receptor.

  • Valores: 1, 6
conceptoobligatoriointeger

1 productos, 2 servicios, 3 ambos.

  • Valores: 1, 2, 3
receptorobligatorioReceptor
renglonesobligatorioRenglon[]
  • Elementos: de 1 a 200
servicio_desdeopcionalFecha
servicio_hastaopcionalFecha
vencimiento_pagoopcionalFecha
condicion_ventaopcionalCondicionVenta

Por defecto, contado.

  • Si concepto es 2 o 3: son obligatorios servicio_desde, servicio_hasta, vencimiento_pago.
  • Si no: servicio_desde no se admite; servicio_hasta no se admite; vencimiento_pago no se admite.
  • No admite campos que no estén en esta tabla.

PedidoNotaDeCredito

Tipo object .

Sin renglones, la nota es por el total de la factura. Sin importes calculados ni fecha.

CampoTipoDescripción
renglonesopcionalRenglon[]
  • Elementos: de 1 a 200
  • No admite campos que no estén en esta tabla.

MensajeArca

Tipo object .

CampoTipoDescripción
codigoobligatoriointeger
mensajeobligatoriostring
  • No admite campos que no estén en esta tabla.

Rechazo

Tipo object .

Lo que contestó ARCA. El comprobante rechazado no se reintenta solo.

CampoTipoDescripción
erroresobligatorioMensajeArca[]
observacionesobligatorioMensajeArca[]
  • No admite campos que no estén en esta tabla.

Comprobante

Tipo object .

CampoTipoDescripción
idobligatoriostring (uuid)
estadoobligatoriostring
  • Valores: procesando, emitido, rechazado, descartado
en_revisionobligatorioboolean

true si está procesando y nadie lo está trabajando: espera la revisión de una persona. false mientras esté en curso, aunque ARCA tarde, y siempre en un comprobante emitido, rechazado o descartado.

cuit_emisorobligatoriostring
  • Patrón: ^[0-9]{11}$
punto_ventaobligatoriointeger
  • Valor: de 1 a 99999
tipoobligatoriointeger

1 factura A, 6 factura B, 3 nota de crédito A, 8 nota de crédito B.

  • Valores: 1, 6, 3, 8
numeroobligatoriointeger | null

Sólo con el comprobante emitido.

conceptoobligatoriointeger
  • Valores: 1, 2, 3
fechaobligatorioFecha

La fecha guardada. Hasta que el comprobante esté emitido es sólo la del pedido, y puede cambiar: la definitiva es la del día de emisión en Argentina.

servicio_desdeobligatoriostring (date) | null
servicio_hastaobligatoriostring (date) | null
vencimiento_pagoobligatoriostring (date) | null

Si quedó atrás al emitir, pasa a ser el día de emisión. Hasta entonces puede cambiar.

receptorobligatorioReceptor
renglonesobligatorioRenglon[]
  • Elementos: desde 1
condicion_ventaobligatorioCondicionVenta
importe_netoobligatorioImporteExacto
importe_ivaobligatorioImporteExacto
importe_totalobligatorioImporteExacto
caeobligatoriostring | null
  • Patrón: ^[0-9]{14}$
cae_vencimientoobligatoriostring (date) | null
emitido_enobligatoriostring (date-time) | null
comprobante_asociado_idobligatoriostring (uuid) | null

En una nota de crédito, la factura que corrige. null en una factura.

rechazoobligatorioRechazo | null
creado_enobligatoriostring (date-time)
  • Si estado es emitido: numero es integer desde 1; cae es string; cae_vencimiento es string; emitido_en es string; rechazo es null.
  • Si no: numero es null; cae es null; cae_vencimiento es null; emitido_en es null.
  • Si estado es rechazado: rechazo es object.
  • Si no: rechazo es null.
  • No admite campos que no estén en esta tabla.

PedidoWebhook

Tipo object .

CampoTipoDescripción
urlobligatoriostring (uri)

https, sin credenciales, y con un destino público.

  • Largo: hasta 2048
  • No admite campos que no estén en esta tabla.

Webhook

Tipo object .

CampoTipoDescripción
urlobligatoriostring (uri)
creado_enobligatoriostring (date-time)
actualizado_enobligatoriostring (date-time)
  • No admite campos que no estén en esta tabla.

WebhookConSecreto

Tipo object .

CampoTipoDescripción
urlobligatoriostring (uri)
creado_enobligatoriostring (date-time)
actualizado_enobligatoriostring (date-time)
secretoobligatoriostring

Se muestra sólo en esta respuesta. Es la clave del HMAC, entera, como texto.

  • Patrón: ^mf_whsec_[A-Za-z0-9_-]{43}$
  • No admite campos que no estén en esta tabla.

TipoEventoWebhook

Tipo string . Valores: comprobante.emitido, comprobante.rechazado, comprobante.error_datos, comprobante.en_revision, comprobante.descartado.

ReenvioEncolado

Tipo object .

CampoTipoDescripción
eventoobligatorioobject
evento.idobligatoriostring (uuid)
evento.tipoobligatorioTipoEventoWebhook
  • No admite campos que no estén en esta tabla.

ComprobanteDelEvento

Tipo object .

Lo necesario para reconocerlo. El detalle completo sale de GET /v1/comprobantes/{id}.

CampoTipoDescripción
idobligatoriostring (uuid)
estadoobligatoriostring

El estado público al momento de entregar.

  • Valores: procesando, emitido, rechazado, descartado
tipoobligatoriointeger

1 factura A, 6 factura B, 3 nota de crédito A, 8 nota de crédito B.

  • Valores: 1, 6, 3, 8
punto_ventaobligatoriointeger
  • Valor: de 1 a 99999
numeroobligatoriointeger | null

Sólo con el comprobante emitido.

caeobligatoriostring | null
  • Patrón: ^[0-9]{14}$
cae_vencimientoobligatoriostring (date) | null
fechaobligatorioFecha
comprobante_asociado_idobligatoriostring (uuid) | null

En una nota de crédito, la factura que corrige.

  • No admite campos que no estén en esta tabla.

EventoWebhook

Tipo object .

comprobante.emitido: ARCA autorizó, y trae número y CAE. comprobante.rechazado: ARCA dijo que no; motivo trae lo mismo que rechazo en el GET. comprobante.error_datos: los datos del comprobante no se pueden enviar a ARCA; sigue procesando hasta que lo resuelva una persona. comprobante.en_revision: espera la revisión de una persona; sigue procesando y no hace falta pedirlo de nuevo. Estos dos últimos no se entregan si el comprobante se resolvió mientras esperaban: llega el resultado. comprobante.descartado: ModoFactura lo cerró sin mandarlo a ARCA; no tiene número ni CAE y no va a cambiar más.

CampoTipoDescripción
idobligatoriostring (uuid)

Estable. Se repite en cada reintento y en un reenvío, para deduplicar.

tipoobligatorioTipoEventoWebhook
creado_enobligatoriostring (date-time)

Cuándo pasó, no cuándo se entregó.

comprobanteobligatorioComprobanteDelEvento
motivoopcionalstring

Legible. No trae más que lo que muestra el GET del comprobante.

  • Largo: desde 1
  • Si tipo es comprobante.emitido: motivo no se admite; comprobante.estado es emitido; comprobante.numero es integer desde 1; comprobante.cae es string; comprobante.cae_vencimiento es string.
  • Si no: motivo es obligatorio; comprobante.numero es null; comprobante.cae es null; comprobante.cae_vencimiento es null.
  • Si tipo es comprobante.error_datos o comprobante.en_revision: comprobante.estado es procesando.
  • Si tipo es comprobante.rechazado: comprobante.estado es rechazado.
  • Si tipo es comprobante.descartado: comprobante.estado es descartado.
  • No admite campos que no estén en esta tabla.

ImporteExacto

Tipo string . Patrón: ^[0-9]{1,13}\.[0-9]{2}$.

Calculado por el servidor, siempre con 2 decimales.

Problema

Tipo object .

RFC 9457.

CampoTipoDescripción
typeobligatoriostring
titleobligatoriostring
statusobligatoriointeger
detailopcionalstring
  • No admite campos que no estén en esta tabla.

ProblemaDeValidacion

Tipo object .

RFC 9457, con la lista de campos a corregir.

CampoTipoDescripción
typeobligatoriostring
titleobligatoriostring
statusobligatoriointeger
erroresobligatorioobject[]
  • Elementos: desde 1
errores[].campoobligatoriostring

Ruta del campo, por ejemplo renglones.0.importe.

errores[].mensajeobligatoriostring
  • No admite campos que no estén en esta tabla.