Facturación electrónica argentina, por API
Emití facturas A/B/C, notas de crédito y notas de débito autorizadas por ARCA directo desde tu sistema — e-commerce propio, ERP, o cualquier backend que ya tengas. Mismo motor que usa el dashboard de SimpleComm, sin pasar por él.
Introducción
La API de SimpleComm te deja emitir comprobantes electrónicos válidos ante ARCA (ex AFIP) con una sola llamada HTTP: mandás el monto, los datos del comprador y el tipo de comprobante, y recibís de vuelta el CAE, el número de comprobante y el PDF listo para descargar. No hace falta que manejes certificados ni te conectes vos mismo a los webservices de ARCA — eso ya lo resuelve SimpleComm.
Autenticación
Todas las llamadas requieren una API key en el header Authorization, formato Bearer. Generá la tuya desde Configuración → API en tu dashboard — se muestra una única vez al crearla, así que guardala en un lugar seguro.
Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInicio rápido
La URL base de la API es:
https://simplecomm-production.up.railway.appUn ejemplo completo — emitir una Factura B a un consumidor final:
curl -X POST https://simplecomm-production.up.railway.app/v1/invoices/issue \
-H "Authorization: Bearer sc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "pedido-10234",
"invoice": {
"total_amount": 15000,
"invoice_letter": "B"
},
"buyer": {
"full_name": "Consumidor Final"
}
}'const res = await fetch("https://simplecomm-production.up.railway.app/v1/invoices/issue", {
method: "POST",
headers: {
"Authorization": "Bearer sc_live_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
idempotency_key: `pedido-${orderId}`,
invoice: {
total_amount: 15000,
invoice_letter: "B",
},
buyer: {
full_name: "Consumidor Final",
},
}),
});
const data = await res.json();
console.log(data.invoice_number, data.cae);{
"status": "issued",
"invoice_id": "clx4k9j8e0001abc123",
"invoice_number": "0004-00000123",
"cae": "75312457896541",
"cae_due_date": "20261015",
"pdf_base64": "JVBERi0xLjQKJcOkw7zDtsO..."
}Emitir un comprobante
Emite una Factura A, B o C. El monto se interpreta distinto según la letra: para Factura A es el neto (sin IVA, que se suma aparte); para B y C es el total (con IVA incluido en B, sin IVA en C porque los monotributistas no lo discriminan).
Body — invoice
| Campo | Tipo | Descripción | |
|---|---|---|---|
total_amount | number | requerido | Neto para Factura A, total (con IVA) para B/C. |
invoice_letter | "A" | "B" | "C" | opcional | Por defecto "B". Tu condición fiscal en ARCA determina qué letras podés emitir. |
iva_rate | number | opcional | 21, 10.5, 27 o 0 (exento). Por defecto 21. |
concept | 1 | 2 | 3 | opcional | 1=Productos (default), 2=Servicios, 3=Ambos. Si es 2 o 3, ARCA exige el período facturado. |
description | string | opcional | Detalle que aparece en el PDF del comprobante. |
pto_vta | number | opcional | Punto de venta a usar. Por defecto, el punto de venta principal de tu cuenta. |
service_date_from | string | opcional* | YYYY-MM-DD. Requerido si concept es 2 o 3. |
service_date_to | string | opcional* | YYYY-MM-DD. Requerido si concept es 2 o 3. |
payment_due_date | string | opcional* | YYYY-MM-DD. Requerido si concept es 2 o 3. |
currency | "PES" | "DOL" | opcional | Por defecto pesos. |
exchange_rate | number | opcional* | Requerido y mayor a 1 si currency es "DOL". |
Body — buyer
| Campo | Tipo | Descripción | |
|---|---|---|---|
full_name | string | requerido | Nombre o razón social del comprador. |
doc_type | string | opcional | "CUIT", "CUIL", "DNI" o "CONSUMIDOR_FINAL". Por defecto "CONSUMIDOR_FINAL". Factura A requiere CUIT. |
doc_number | string | opcional | Solo dígitos. Por defecto "0". |
email | string | opcional | No se usa para enviar el comprobante — el envío por email es responsabilidad tuya. |
address | string | opcional | Aparece en el PDF si se provee. |
Body — nivel raíz
| Campo | Tipo | Descripción | |
|---|---|---|---|
idempotency_key | string | requerido | Ver Idempotencia. 1-255 caracteres. |
external_ref | string | opcional | Tu propio ID de referencia (ej. número de pedido) — se guarda pero no se usa para nada más. |
source_app | string | opcional | Identificador libre de tu integración, útil para tus propios logs. |
metadata | object | opcional | Cualquier dato adicional que quieras asociar al comprobante. |
Respuesta
201 si se emitió, o 200 si ya la habías emitido antes con esa misma idempotency_key.
{
"status": "issued", // o "duplicate" si ya existía
"invoice_id": "clx4k9j8e0001abc123",
"invoice_number": "0004-00000123",
"cae": "75312457896541",
"cae_due_date": "20261015", // YYYYMMDD
"pdf_base64": "..." // PDF del comprobante, en base64
}Ejemplo — Factura A a un Responsable Inscripto
curl -X POST https://simplecomm-production.up.railway.app/v1/invoices/issue \
-H "Authorization: Bearer sc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "pedido-10235",
"invoice": {
"total_amount": 50000,
"invoice_letter": "A",
"iva_rate": 21,
"description": "Servicio de consultoría — septiembre"
},
"buyer": {
"full_name": "Comercial del Sur S.A.",
"doc_type": "CUIT",
"doc_number": "30712345671"
}
}'Consultar un comprobante
Devuelve el estado actual de un comprobante emitido por vos, identificado por el invoice_id que te devolvió /v1/invoices/issue.
{
"invoice_id": "clx4k9j8e0001abc123",
"status": "issued", // "issued" | "pending" | "error"
"invoice_number": "0004-00000123",
"invoice_number_int": 123,
"pto_vta": 4,
"invoice_type": 6, // código AFIP: 1=Fact.A, 6=Fact.B, 11=Fact.C
"cae": "75312457896541",
"cae_due_date": "20261015",
"total_amount": 15000,
"net_amount": 12396.69,
"iva_amount": 2603.31,
"concept": 1,
"buyer_name": "Consumidor Final",
"buyer_doc_type": "CONSUMIDOR_FINAL",
"buyer_doc_number": "0",
"created_at": "2026-09-11T14:32:08.000Z",
"error": null
}Nota de crédito
Anula por completo un comprobante ya emitido. La letra, el receptor, el punto de venta y el monto se toman directo de la factura original — no hace falta (ni se puede) reenviarlos. Hoy solo soporta notas de crédito totales, no parciales.
| Campo | Tipo | Descripción | |
|---|---|---|---|
idempotency_key | string | requerido | Igual que en la emisión — usá una nueva por cada intento real. |
source_app | string | opcional | Identificador libre de tu integración. |
curl -X POST https://simplecomm-production.up.railway.app/v1/invoices/clx4k9j8e0001abc123/credit-note \
-H "Authorization: Bearer sc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "idempotency_key": "nc-pedido-10234" }'La respuesta tiene la misma forma que la de emisión.
Nota de débito
A diferencia de la nota de crédito, esta no anula nada — suma un cargo adicional asociado a una factura ya emitida (ej. intereses por mora, un ajuste de precio). Vos definís el monto y el motivo; la letra, el receptor y el punto de venta se toman de la factura original.
| Campo | Tipo | Descripción | |
|---|---|---|---|
idempotency_key | string | requerido | |
amount | number | requerido | Monto del cargo, mayor a cero. Interpretado igual que total_amount en la emisión (neto para A, total para B/C). |
reason | string | requerido | Motivo del cargo — queda impreso en el comprobante. 1-255 caracteres. |
source_app | string | opcional |
curl -X POST https://simplecomm-production.up.railway.app/v1/invoices/clx4k9j8e0001abc123/debit-note \
-H "Authorization: Bearer sc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "nd-pedido-10234",
"amount": 1500,
"reason": "Intereses por pago fuera de término"
}'Idempotencia
Todo endpoint que emite un comprobante requiere idempotency_key. Si repetís la misma llamada con la misma key (por ejemplo, porque tu request original tuvo timeout y reintentaste), la API no emite un comprobante duplicado — te devuelve el mismo resultado de la primera vez, con status: "duplicate" y código 200 en vez de 201.
`pedido-${orderId}`). No generes una key nueva en cada reintento: ahí perdés la protección contra duplicados.Errores
| Código | Significa |
|---|---|
| 400 | Payload inválido — el body no cumple el formato esperado. El campo details de la respuesta indica qué falló. |
| 401 | API key faltante, inválida o revocada. |
| 402 | Alcanzaste el cupo mensual de tu API key. Ver Límites. |
| 404 | El comprobante (o la factura original, en notas de crédito/débito) no existe o no te pertenece. |
| 502 | Error al emitir contra ARCA — el body incluye un mensaje explicando la causa (rechazo de ARCA, timeout, etc.). |
{
"error": "Payload inválido",
"details": {
"invoice": ["Required"]
}
}Límites del Plan API
El acceso directo por API es independiente del plan de tu dashboard — tiene su propio cupo mensual de comprobantes, que ves reflejado en Configuración → API junto a cada key. El cupo se resetea el primer día de cada mes.
Si lo superás, vas a recibir 402 hasta el próximo reseteo. Si tu volumen creció y necesitás más, escribinos a soporte@simplecomm.com.ar.
Buenas prácticas
- Guardá siempre
invoice_id,invoice_numberycaeapenas los recibís — son los datos que después necesitás para una nota de crédito/débito o para mostrarle el comprobante al comprador. - Descargá y guardá el
pdf_base64en tu propio storage si necesitás servirlo después — la API no lo re-expone enGET /v1/invoices/:id. - Verificá el campo
statusde la respuesta: un"duplicate"no es un error, es la protección de idempotencia funcionando. - Para Factura A siempre mandá
doc_type: "CUIT"con un CUIT válido — ARCA la rechaza sin eso. - Manejá el 502 con reintento manual, no automático inmediato: un rechazo de ARCA casi nunca se resuelve reintentando al instante con los mismos datos.
¿Listo para integrar?
Generá tu API key desde el dashboard y emitís tu primer comprobante en minutos.