Factura SDK
Comprobantes

Comprobantes

Referencia completa para emitir, consultar y listar comprobantes, descargar el PDF y entender cada estado y cada error.


Endpoints

Método y rutaQué hace
POST /v1/invoicesEmite un comprobante.
GET /v1/invoices/:idDevuelve un comprobante con su estado actual.
GET /v1/invoicesLista los comprobantes, con filtros y paginación.
GET /v1/invoices/:id/pdf?token=El PDF de un comprobante aprobado. Es su pdf_url: pública y fija.
GET /v1/invoices/:id/arca-request?token=La solicitud que se mandó a ARCA. Es arca_request_url: pública y fija.
GET /v1/invoices/:id/arca-response?token=La respuesta de ARCA. Es arca_response_url: pública y fija.
POST /v1/invoices/:id/cancelCancela un comprobante que todavía está queued.

Emitir un comprobante

POST /v1/invoices recibe los datos de la venta y los convierte en un comprobante electrónico autorizado por ARCA. Factura SDK asigna el número correlativo, obtiene el CAE y arma el comprobante impreso con los datos del emisor y del receptor.

El emisor se indica por su CUIT (issuer_cuit) y tiene que estar verificado. El comprobante sale por el punto de venta y con el certificado del emisor.

Headers

HeaderRequeridoDescripción
AuthorizationSíBearer <ACCESS_TOKEN>.
Content-TypeSíapplication/json.
Idempotency-KeyRecomendadoIdentificador único de la venta en tu sistema, hasta 255 caracteres. Ver idempotencia.

Ejemplo

Una Factura A de $12.100 entre responsables inscriptos:

Solicitud
const response = await fetch('https://app.afipsdk.com/api/v1/invoices', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer <ACCESS_TOKEN>',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'venta-0002'
  },
  body: JSON.stringify({
    issuer_cuit: '20111111112',
    invoice_type: 1,
    concept: 1,
    receiver: {
      doc_type: 80,
      doc_number: '30715000004',
      vat_condition: 1,
      name: 'Comercio del Centro S.R.L.',
      address: 'Av. Corrientes 1234, CABA'
    },
    amounts: {
      net: 10000,
      vat: 2100,
      total: 12100
    },
    vat_items: [
      { id: 5, base: 10000, amount: 2100 }
    ],
    items: [
      { description: 'Notebook 14', quantity: 1, unit_price: 10000, subtotal: 10000, vat_rate: 21 }
    ],
    sale_condition: 'Cuenta corriente'
  })
});

const invoice = await response.json();

Campos generales

CampoTipoRequeridoDescripción
issuer_cuitstringSíCUIT del emisor, 11 dígitos. Tiene que existir en el ambiente del token y estar active.
invoice_typeintegerSíTipo de comprobante. Ver tipos de comprobante.
conceptintegerSí1 productos, 2 servicios, 3 productos y servicios. Con 2 o 3 es obligatorio service_dates.
invoice_datestringNoFecha del comprobante en formato YYYY-MM-DD. Si no la mandás, se usa la fecha de autorización en hora de Argentina. ARCA la rechaza (error 10016) si es anterior a la del último comprobante autorizado del mismo punto de venta y tipo, o si se aleja más de 5 días de hoy (10 días con concept 2 o 3): el comprobante queda rejected con ese error, o failed con el detalle en last_error si lo emitiste con sync: true.
currencystringNoPES (pesos) o DOL (dólares). Si no lo mandás, PES.
exchange_ratenumberCondicionalCotización de la moneda. Obligatoria con DOL; con PES no se manda (equivale a 1).
sale_conditionstringSíCondición de venta impresa en el comprobante, por ejemplo Contado. Hasta 50 caracteres.
reasonstringCondicionalMotivo de la nota. Obligatorio en notas de crédito y débito. Hasta 200 caracteres.
notestringNoTexto al pie del comprobante. Hasta 500 caracteres.
syncbooleanNoCon true el comprobante se emite dentro de la solicitud, la respuesta es siempre final y no se manda webhook. Sin él la respuesta es 202 y el resultado llega por webhook. Ver respuesta.
sandboxobjectNoSolo en sandbox: sandbox.result fuerza el resultado del comprobante. Ver ambiente de pruebas.

Receptor

Objeto receiver.

CampoTipoRequeridoDescripción
doc_typeintegerSíTipo de documento. Ver tipos de documento. Los comprobantes A exigen CUIT (80).
doc_numberstringSíNúmero de documento, solo dígitos, hasta 20. Con doc_type 99 (sin identificar) es 0.
vat_conditionintegerSíCondición frente al IVA del receptor. Ver condiciones frente al IVA.
namestringSíNombre o razón social. Hasta 200 caracteres.
addressstringSíDomicilio. Hasta 300 caracteres.
emailstringNoSi lo mandás, el PDF se envía a esta dirección cuando el comprobante se aprueba. Tiene que ser un email válido, hasta 200 caracteres.

Importes

Objeto amounts. Todos los importes van en la moneda del comprobante, con hasta dos decimales. El total tiene que ser igual a la suma de los otros cinco, con una tolerancia de medio centavo por el redondeo.

CampoTipoRequeridoDescripción
netnumberSíImporte neto gravado.
vatnumberNoIVA total. Si no lo mandás es 0. En los comprobantes C tiene que ser 0.
exemptnumberNoImporte exento. Si no lo mandás es 0.
untaxednumberNoImporte no gravado. Si no lo mandás es 0.
tributesnumberNoTotal de otros tributos (percepciones, impuestos internos). Si no lo mandás es 0.
totalnumberSíImporte total, mayor a 0.

Alícuotas de IVA

Array vat_items, con una entrada por alícuota. Obligatorio en los comprobantes A y B con importe neto mayor a 0; no se manda en los comprobantes C. La suma de base tiene que ser igual a amounts.net y la suma de amount a amounts.vat.

CampoTipoRequeridoDescripción
idintegerSíId de la alícuota. Ver alícuotas de IVA.
basenumberSíBase imponible de la alícuota.
amountnumberSíIVA de la alícuota.

Tributos

Array tribute_items. Obligatorio cuando amounts.tributes es mayor a 0; la suma de amount tiene que ser igual a ese importe.

CampoTipoRequeridoDescripción
idintegerSíId del tributo según ARCA, de 1 a 99.
descriptionstringSíDescripción. Hasta 80 caracteres.
basenumberSíBase imponible.
ratenumberSíAlícuota del tributo.
amountnumberSíImporte del tributo.

Comprobantes asociados

Las notas de crédito y débito tienen que indicar qué ajustan: los comprobantes asociados o el período asociado. Se manda uno de los dos, no ambos.

Array associated_invoices, con los comprobantes del mismo emisor que se ajustan:

CampoTipoRequeridoDescripción
invoice_typeintegerSíTipo del comprobante asociado.
sales_pointintegerSíPunto de venta del comprobante asociado, de 1 a 99999.
numberintegerSíNúmero del comprobante asociado.
datestringNoFecha del comprobante asociado en formato YYYY-MM-DD.

Objeto associated_period, cuando la nota ajusta un período:

CampoTipoRequeridoDescripción
fromstringSíInicio del período, YYYY-MM-DD.
tostringSíFin del período, YYYY-MM-DD. Tiene que ser igual o posterior a from.

Fechas del servicio

Objeto service_dates. Obligatorio con concept 2 o 3.

CampoTipoRequeridoDescripción
fromstringSíInicio del servicio, YYYY-MM-DD.
tostringSíFin del servicio, YYYY-MM-DD. Tiene que ser igual o posterior a from.
duestringSíVencimiento del pago, YYYY-MM-DD.

Ítems

Array items, de 1 a 200 líneas. Son el detalle impreso en el comprobante; ARCA no los recibe.

CampoTipoRequeridoDescripción
descriptionstringSíDescripción del ítem. Hasta 300 caracteres.
quantityintegerSíCantidad, entera y mayor o igual a 1.
unit_pricenumberSíPrecio unitario.
subtotalnumberSíSubtotal de la línea.
codestringNoCódigo del producto o servicio. Hasta 50 caracteres.
vat_ratenumberCondicionalAlícuota de IVA del ítem en porcentaje, por ejemplo 21 o 10.5. Obligatoria en los comprobantes A con IVA.

Ejemplos por tipo de comprobante

Hay una solicitud completa, con su respuesta y sus variantes (servicios, varias alícuotas, dólares, notas parciales, período asociado), para cada tipo:

Respuesta

Por defecto la emisión es asíncrona: Factura SDK guarda el comprobante, lo pone en cola y responde 202 con el comprobante en queued. La autorización en ARCA ocurre en segundo plano y el resultado llega por webhook o lo consultás con GET /v1/invoices/:id. Mientras está queued podés cancelarlo.

Con sync: true Factura SDK emite el comprobante dentro de la solicitud y la respuesta es siempre final: 200 con el comprobante en approved, rejected o failed, nada sigue en segundo plano y no se envian los estados via webhook. Si ARCA no responde dentro del tiempo de la solicitud o algo ocurrió en la emisión del comprobante, el comprobante queda failed.

El comprobante tiene esta forma:

{
  "id": "7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f",
  "idempotency_key": "venta-0002",
  "verification": false,
  "status": "approved",
  "invoice_type": 1,
  "sales_point": 1,
  "number": 482,
  "invoice_date": "2026-10-14",
  "total_amount": 12100,
  "currency": "PES",
  "cae": "76412345678901",
  "cae_expiration": "2026-10-24",
  "payload": { "...": "los datos que mandaste, normalizados" },
  "observations": null,
  "errors": null,
  "last_error": null,
  "attempts": 1,
  "next_retry_at": null,
  "created_at": "2026-10-14T14:05:00.000Z",
  "updated_at": "2026-10-14T14:05:03.000Z",
  "processed_at": "2026-10-14T14:05:03.000Z",
  "pdf_url": "https://app.afipsdk.com/api/v1/invoices/7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f/pdf?token=kX3v9Qw2LmN8pR5tY7uZ1aB4cD6eF8gH0jK2lM4nO6p",
  "pdf_generated_at": null,
  "arca_request_url": "https://app.afipsdk.com/api/v1/invoices/7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f/arca-request?token=kX3v9Qw2LmN8pR5tY7uZ1aB4cD6eF8gH0jK2lM4nO6p",
  "arca_response_url": "https://app.afipsdk.com/api/v1/invoices/7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f/arca-response?token=kX3v9Qw2LmN8pR5tY7uZ1aB4cD6eF8gH0jK2lM4nO6p",
  "email_status": null,
  "email_sent_at": null,
  "issuer": {
    "id": "0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c",
    "tax_id": "20111111112",
    "business_name": "Emisor de prueba",
    "vat_condition": 1
  }
}
CampoDescripción
idIdentificador del comprobante.
statusEstado actual. Ver estados.
verificationtrue en los comprobantes que Factura SDK emitió para verificar el emisor.
numberNúmero asignado por ARCA al aprobar. Correlativo por emisor, punto de venta y tipo.
cae, cae_expirationCódigo de autorización y su vencimiento (YYYY-MM-DD). Solo en comprobantes aprobados.
payloadLos datos del comprobante tal como se guardaron.
observationsObservaciones de ARCA en un comprobante aprobado, como lista de code y message.
errorsMotivos de rechazo de ARCA, como lista de code y message.
last_errorCausa del último fallo técnico o de configuración.
attempts, next_retry_atIntentos realizados y, si el comprobante está en cola, cuándo se reintenta.
pdf_urlURL pública y fija del PDF. Solo en comprobantes aprobados. Ver PDF.
arca_request_url, arca_response_urlURLs públicas y fijas de la solicitud y la respuesta de ARCA que decidieron el comprobante. Aparecen una vez que ARCA respondió (aprobado o rechazado), a veces unos segundos después de la decisión. Ver Solicitud y respuesta de ARCA.
email_status, email_sent_atsent o failed cuando el comprobante tenía receiver.email; email_sent_at solo cuando salió.
issuerid, tax_id, business_name y vat_condition del emisor.

Idempotencia

El header Idempotency-Key identifica la venta en tu sistema (el id del pedido, por ejemplo). Es opcional: si no lo mandás, Factura SDK genera una clave y cada solicitud crea un comprobante nuevo. Conviene mandarlo siempre, porque es lo que hace seguro reintentar: si la solicitud se corta por un timeout o una caída y no sabés si el comprobante se emitió, lo repetís con la misma clave y recibís el comprobante original en vez de emitir otro.

Estados

EstadoQué significaQué hacer
queuedRecibido.Esperar el webhook o consultar.
processingSe está autorizando.Esperar.
approvedAprobado.Nada. Es final.
rejectedARCA lo rechazó. Los motivos están en errors.Corregir los datos y emitir un comprobante nuevo con otra Idempotency-Key. Es final.
failedNo se pudo autorizar, la causa está en last_error.Resolver la causa si es de configuración y repetir la misma solicitud con la misma Idempotency-Key.
cancelledLo cancelaste mientras estaba queued. Nunca se emitió.Nada. Es final. Repetir su Idempotency-Key lo vuelve a emitir.

Un comprobante aprobado con observaciones es approved: no existe un estado aparte. Revisá observations si te interesa lo que marcó ARCA.

Cuando un comprobante queda en segundo plano, los fallos técnicos se reintentan solos con esperas crecientes (un minuto, dos, cuatro… hasta una hora entre intentos) durante 24 horas desde la creación, o desde que repetiste su Idempotency-Key si lo reencolaste; después el comprobante pasa a failed. Con sync: true no hay reintentos automáticos: vos decidís cuándo repetir la solicitud.

Cancelar un comprobante

POST /v1/invoices/:id/cancel cancela un comprobante que todavía está queued: pasa a cancelled, un estado final, y nunca se emite.

Solicitud
const response = await fetch('https://app.afipsdk.com/api/v1/invoices/<INVOICE_ID>/cancel', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer <ACCESS_TOKEN>'
  }
});

const invoice = await response.json();

console.log(response.status, invoice.status);

Ambiente de pruebas

Con un access token de dev estás en sandbox: ningún comprobante llega a ARCA. Sirve para integrar y probar sin trámites y sin consumir el plan.

  • El emisor se da de alta y se verifica igual que en producción, pero con un certificado simulado que no firma nada.
  • Aplica las mismas reglas y los mismos campos que producción.

Con el campo sandbox.result forzás el resultado para probar cada camino de tu integración:

{
  "sandbox": { "result": "approved_with_observations" }
}
sandbox.resultQué simula
approvedAprobado. Es el comportamiento por defecto.
approved_with_observationsAprobado (status: "approved") con una observación de prueba en observations, de código sandbox_forced_observation.
rejectedRechazado, con un error de prueba en errors, de código sandbox_forced_rejection. Si el comprobante además viola una regla real del sandbox (una fecha fuera de rango, por ejemplo), los errores reales tienen prioridad.
errorUn fallo técnico al autorizar. Por defecto el comprobante queda queued con la causa en last_error y se reintenta durante la ventana de 24 horas como en producción; con sync: true queda failed en el momento.

Consultar un comprobante

GET /v1/invoices/:id devuelve el comprobante con su estado actual.

Solicitud
const response = await fetch('https://app.afipsdk.com/api/v1/invoices/<INVOICE_ID>', {
  headers: {
    'Authorization': 'Bearer <ACCESS_TOKEN>'
  }
});

const invoice = await response.json();

Listar comprobantes

GET /v1/invoices lista los comprobantes del más nuevo al más viejo, con paginación por cursor. Incluye los comprobantes de verificación de los emisores, marcados con verification: true.

ParámetroTipoDescripción
issuer_cuitstringCUIT del emisor.
statusstringUno de los estados.
invoice_typeintegerTipo de comprobante.
startstringFecha de creación desde, como fecha y hora ISO 8601 completa, con milisegundos y zona: 2026-10-01T00:00:00.000Z.
endstringFecha de creación hasta, en el mismo formato. Tiene que ser igual o posterior a start.
limitintegerCantidad por página: 10 si no la mandás, hasta 100. Un valor fuera de rango se ajusta.
cursorstringEl next_cursor de la página anterior.
Solicitud
const params = new URLSearchParams({
  issuer_cuit: '20111111112',
  status: 'approved',
  limit: '50'
});

const response = await fetch(`https://app.afipsdk.com/api/v1/invoices?${params}`, {
  headers: {
    'Authorization': 'Bearer <ACCESS_TOKEN>'
  }
});

const { data, next_cursor, total_count } = await response.json();
{
  "data": [
    { "id": "7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f", "status": "approved", "verification": false, "...": "..." }
  ],
  "next_cursor": "7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f",
  "total_count": 128
}

Para la página siguiente, repetí la solicitud con cursor igual a next_cursor, que es el id del último comprobante de la página. Cuando next_cursor es null, no hay más páginas. Si el CUIT de issuer_cuit no tiene emisor, la lista viene vacía.

PDF

Todo comprobante aprobado trae pdf_url: una URL pública y fija para toda la vida del comprobante, con un token propio de ese comprobante. No requiere autenticación: podés guardarla en tu sistema, ponerla en un email o mostrársela al cliente. Al abrirla muestra el PDF; con ?download=true lo descarga.

https://app.afipsdk.com/api/v1/invoices/7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f/pdf?token=kX3v9Qw2LmN8pR5tY7uZ1aB4cD6eF8gH0jK2lM4nO6p

Solicitud y respuesta de ARCA

Todo comprobante emitido trae arca_request_url y arca_response_url: la solicitud y la respuesta de la autorización tal como viajaron. Son URLs públicas y fijas, con el mismo token que pdf_url. Con ?download=true descargan el archivo en vez de mostrarlo.

https://app.afipsdk.com/api/v1/invoices/7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f/arca-request?token=kX3v9Qw2LmN8pR5tY7uZ1aB4cD6eF8gH0jK2lM4nO6p
https://app.afipsdk.com/api/v1/invoices/7c1d9e4b-2f3a-4b8c-9d0e-1a2b3c4d5e6f/arca-response?token=kX3v9Qw2LmN8pR5tY7uZ1aB4cD6eF8gH0jK2lM4nO6p

Son el XML SOAP de FECAESolicitar (o de FECompConsultar, cuando el comprobante se recuperó de un intento anterior que ARCA había autorizado), con las credenciales del ticket de acceso (Token y Sign) tachadas: con el archivo no se puede firmar nada. En sandbox son la solicitud y la respuesta simulados, en JSON.

Email al receptor

Si el comprobante tiene receiver.email, al aprobarse Factura SDK le manda al receptor un email con el PDF adjunto, una sola vez por comprobante. El resultado queda en email_status (sent o failed) y, si salió, email_sent_at.

Errores

HTTPCuándo
400El cuerpo tiene errores de forma (data_errors); el comprobante no cumple una regla (errors); el emisor está pending (sin verificar) o inactive, no tiene punto de venta, o su certificado falta, venció o está revocado; el Idempotency-Key supera los 255 caracteres; alcanzaste el límite de comprobantes o CUITs del plan, o el presupuesto mensual de pago por uso; la suscripción está vencida o impaga; cancelar un comprobante de verificación.
401Access token inválido, ausente o revocado.
404No hay un emisor con ese CUIT (data_errors.issuer_cuit), o el comprobante no existe.
409Con sync: true, otra solicitud está emitiendo ese mismo comprobante. En el PDF y en los archivos de ARCA, el comprobante todavía no está decidido. Al cancelar, el comprobante ya está processing o ya terminó.

Los errores de forma llegan en data_errors, con un mensaje por campo y sin message:

{
  "statusCode": 400,
  "data_errors": {
    "receiver": {
      "vat_condition": "El campo Condición frente al IVA del receptor es invalido"
    }
  }
}

Las reglas del comprobante llegan en errors:

{
  "message": "El comprobante no cumple las validaciones. Revise el detalle en errors.",
  "errors": [
    {
      "code": "amounts_mismatch",
      "message": "El total (12000) debe ser igual a net + vat + exempt + untaxed + tributes (12100)"
    }
  ]
}

Los problemas del emisor llegan con el motivo en message y la clave en data_errors.issuer_cuit:

{
  "message": "El emisor 20111111112 todavía no está verificado. Verificalo con POST /v1/issuers/0f8f3c2a-5b1e-4c7d-9a2e-6d4b8e1f2a3c/verify (o desde el dashboard) para empezar a emitir.",
  "data_errors": {
    "issuer_cuit": "El emisor no está verificado"
  }
}

El formato de cada código está en Errores y respuestas.

Catálogos

Tipos de comprobante

invoice_typeComprobante
1Factura A
2Nota de Débito A
3Nota de Crédito A
6Factura B
7Nota de Débito B
8Nota de Crédito B
11Factura C
12Nota de Débito C
13Nota de Crédito C

La clase del comprobante depende de la condición frente al IVA del emisor y del receptor, y Factura SDK la controla antes de emitir. Los A los emiten los responsables inscriptos a otros responsables inscriptos y a monotributistas, y exigen receptor con CUIT. Los B los emiten los responsables inscriptos a consumidores finales, exentos, no alcanzados y no categorizados. Los C los emiten los monotributistas, exentos, no alcanzados y no categorizados, a cualquier receptor, y no discriminan IVA.

Conceptos

conceptConcepto
1Productos
2Servicios
3Productos y servicios

Condiciones frente al IVA

Se usan en receiver.vat_condition y en el emisor.

IdCondición
1IVA Responsable Inscripto
4IVA Sujeto Exento
5Consumidor Final
6Responsable Monotributo
7Sujeto No Categorizado
8Proveedor del Exterior
9Cliente del Exterior
10IVA Liberado - Ley N° 19.640
13Monotributista Social
15IVA No Alcanzado
16Monotributo Trabajador Independiente Promovido

Alícuotas de IVA

Se usan en vat_items.id.

IdAlícuota
30%
410,5%
521%
627%
85%
92,5%

Tipos de documento

Se usan en receiver.doc_type.

IdDocumento
80CUIT
86CUIL
87CDI
89Libreta de enrolamiento
90Libreta cívica
91CI extranjera
92En trámite
93Acta de nacimiento
94Pasaporte
95CI Buenos Aires RNP
96DNI
99Sin identificar (consumidor final)

Monedas

currencyMoneda
PESPesos argentinos. Es la moneda por defecto.
DOLDólares estadounidenses. Requiere exchange_rate.