Endpoints
| Método y ruta | Qué hace |
|---|---|
POST /v1/invoices | Emite un comprobante. |
GET /v1/invoices/:id | Devuelve un comprobante con su estado actual. |
GET /v1/invoices | Lista 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/cancel | Cancela 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
| Header | Requerido | Descripción |
|---|---|---|
Authorization | Sí | Bearer <ACCESS_TOKEN>. |
Content-Type | Sí | application/json. |
Idempotency-Key | Recomendado | Identificador único de la venta en tu sistema, hasta 255 caracteres. Ver idempotencia. |
Ejemplo
Una Factura A de $12.100 entre responsables inscriptos:
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
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
issuer_cuit | string | Sí | CUIT del emisor, 11 dígitos. Tiene que existir en el ambiente del token y estar active. |
invoice_type | integer | Sí | Tipo de comprobante. Ver tipos de comprobante. |
concept | integer | Sí | 1 productos, 2 servicios, 3 productos y servicios. Con 2 o 3 es obligatorio service_dates. |
invoice_date | string | No | Fecha 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. |
currency | string | No | PES (pesos) o DOL (dólares). Si no lo mandás, PES. |
exchange_rate | number | Condicional | Cotización de la moneda. Obligatoria con DOL; con PES no se manda (equivale a 1). |
sale_condition | string | Sí | Condición de venta impresa en el comprobante, por ejemplo Contado. Hasta 50 caracteres. |
reason | string | Condicional | Motivo de la nota. Obligatorio en notas de crédito y débito. Hasta 200 caracteres. |
note | string | No | Texto al pie del comprobante. Hasta 500 caracteres. |
sync | boolean | No | Con 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. |
sandbox | object | No | Solo en sandbox: sandbox.result fuerza el resultado del comprobante. Ver ambiente de pruebas. |
Receptor
Objeto receiver.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
doc_type | integer | Sí | Tipo de documento. Ver tipos de documento. Los comprobantes A exigen CUIT (80). |
doc_number | string | Sí | Número de documento, solo dígitos, hasta 20. Con doc_type 99 (sin identificar) es 0. |
vat_condition | integer | Sí | Condición frente al IVA del receptor. Ver condiciones frente al IVA. |
name | string | Sí | Nombre o razón social. Hasta 200 caracteres. |
address | string | Sí | Domicilio. Hasta 300 caracteres. |
email | string | No | Si 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.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
net | number | Sí | Importe neto gravado. |
vat | number | No | IVA total. Si no lo mandás es 0. En los comprobantes C tiene que ser 0. |
exempt | number | No | Importe exento. Si no lo mandás es 0. |
untaxed | number | No | Importe no gravado. Si no lo mandás es 0. |
tributes | number | No | Total de otros tributos (percepciones, impuestos internos). Si no lo mandás es 0. |
total | number | Sí | 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.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
id | integer | Sí | Id de la alícuota. Ver alícuotas de IVA. |
base | number | Sí | Base imponible de la alícuota. |
amount | number | Sí | 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.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
id | integer | Sí | Id del tributo según ARCA, de 1 a 99. |
description | string | Sí | Descripción. Hasta 80 caracteres. |
base | number | Sí | Base imponible. |
rate | number | Sí | Alícuota del tributo. |
amount | number | Sí | 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:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
invoice_type | integer | Sí | Tipo del comprobante asociado. |
sales_point | integer | Sí | Punto de venta del comprobante asociado, de 1 a 99999. |
number | integer | Sí | Número del comprobante asociado. |
date | string | No | Fecha del comprobante asociado en formato YYYY-MM-DD. |
Objeto associated_period, cuando la nota ajusta un período:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
from | string | Sí | Inicio del período, YYYY-MM-DD. |
to | string | Sí | 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.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
from | string | Sí | Inicio del servicio, YYYY-MM-DD. |
to | string | Sí | Fin del servicio, YYYY-MM-DD. Tiene que ser igual o posterior a from. |
due | string | Sí | 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.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
description | string | Sí | Descripción del ítem. Hasta 300 caracteres. |
quantity | integer | Sí | Cantidad, entera y mayor o igual a 1. |
unit_price | number | Sí | Precio unitario. |
subtotal | number | Sí | Subtotal de la línea. |
code | string | No | Código del producto o servicio. Hasta 50 caracteres. |
vat_rate | number | Condicional | Alí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:
- Factura A, Factura B y Factura C
- Nota de crédito A, Nota de crédito B y Nota de crédito C
- Nota de débito A, Nota de débito B y Nota de débito C
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
}
}
| Campo | Descripción |
|---|---|
id | Identificador del comprobante. |
status | Estado actual. Ver estados. |
verification | true en los comprobantes que Factura SDK emitió para verificar el emisor. |
number | Número asignado por ARCA al aprobar. Correlativo por emisor, punto de venta y tipo. |
cae, cae_expiration | Código de autorización y su vencimiento (YYYY-MM-DD). Solo en comprobantes aprobados. |
payload | Los datos del comprobante tal como se guardaron. |
observations | Observaciones de ARCA en un comprobante aprobado, como lista de code y message. |
errors | Motivos de rechazo de ARCA, como lista de code y message. |
last_error | Causa del último fallo técnico o de configuración. |
attempts, next_retry_at | Intentos realizados y, si el comprobante está en cola, cuándo se reintenta. |
pdf_url | URL pública y fija del PDF. Solo en comprobantes aprobados. Ver PDF. |
arca_request_url, arca_response_url | URLs 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_at | sent o failed cuando el comprobante tenía receiver.email; email_sent_at solo cuando salió. |
issuer | id, 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
| Estado | Qué significa | Qué hacer |
|---|---|---|
queued | Recibido. | Esperar el webhook o consultar. |
processing | Se está autorizando. | Esperar. |
approved | Aprobado. | Nada. Es final. |
rejected | ARCA lo rechazó. Los motivos están en errors. | Corregir los datos y emitir un comprobante nuevo con otra Idempotency-Key. Es final. |
failed | No 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. |
cancelled | Lo 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.
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.result | Qué simula |
|---|---|
approved | Aprobado. Es el comportamiento por defecto. |
approved_with_observations | Aprobado (status: "approved") con una observación de prueba en observations, de código sandbox_forced_observation. |
rejected | Rechazado, 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. |
error | Un 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.
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ámetro | Tipo | Descripción |
|---|---|---|
issuer_cuit | string | CUIT del emisor. |
status | string | Uno de los estados. |
invoice_type | integer | Tipo de comprobante. |
start | string | Fecha de creación desde, como fecha y hora ISO 8601 completa, con milisegundos y zona: 2026-10-01T00:00:00.000Z. |
end | string | Fecha de creación hasta, en el mismo formato. Tiene que ser igual o posterior a start. |
limit | integer | Cantidad por página: 10 si no la mandás, hasta 100. Un valor fuera de rango se ajusta. |
cursor | string | El next_cursor de la página anterior. |
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.
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
| HTTP | Cuándo |
|---|---|
400 | El 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. |
401 | Access token inválido, ausente o revocado. |
404 | No hay un emisor con ese CUIT (data_errors.issuer_cuit), o el comprobante no existe. |
409 | Con 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_type | Comprobante |
|---|---|
1 | Factura A |
2 | Nota de Débito A |
3 | Nota de Crédito A |
6 | Factura B |
7 | Nota de Débito B |
8 | Nota de Crédito B |
11 | Factura C |
12 | Nota de Débito C |
13 | Nota 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
concept | Concepto |
|---|---|
1 | Productos |
2 | Servicios |
3 | Productos y servicios |
Condiciones frente al IVA
Se usan en receiver.vat_condition y en el emisor.
| Id | Condición |
|---|---|
1 | IVA Responsable Inscripto |
4 | IVA Sujeto Exento |
5 | Consumidor Final |
6 | Responsable Monotributo |
7 | Sujeto No Categorizado |
8 | Proveedor del Exterior |
9 | Cliente del Exterior |
10 | IVA Liberado - Ley N° 19.640 |
13 | Monotributista Social |
15 | IVA No Alcanzado |
16 | Monotributo Trabajador Independiente Promovido |
Alícuotas de IVA
Se usan en vat_items.id.
| Id | Alícuota |
|---|---|
3 | 0% |
4 | 10,5% |
5 | 21% |
6 | 27% |
8 | 5% |
9 | 2,5% |
Tipos de documento
Se usan en receiver.doc_type.
| Id | Documento |
|---|---|
80 | CUIT |
86 | CUIL |
87 | CDI |
89 | Libreta de enrolamiento |
90 | Libreta cívica |
91 | CI extranjera |
92 | En trámite |
93 | Acta de nacimiento |
94 | Pasaporte |
95 | CI Buenos Aires RNP |
96 | DNI |
99 | Sin identificar (consumidor final) |
Monedas
currency | Moneda |
|---|---|
PES | Pesos argentinos. Es la moneda por defecto. |
DOL | Dólares estadounidenses. Requiere exchange_rate. |