Navegación

Factura Fácil API

API para crear comprobantes electrónicos de forma asíncrona. Enviás un POST, recibís 202 + job_id, y el resultado llega por webhook.


Autenticación
Bearer token por header Authorization.
Idempotencia
Usá ExternalId para evitar duplicados y reintentar con force.
Webhooks
Callback firmado con HMAC SHA-256 (opcional).

URL base

Ejemplos:

  • https://www.facil.com.ar/api

Autenticación

Todos los requests requieren:

Authorization: Bearer <TOKEN>
Content-Type: application/json
Scopes típicos: crearFactura (POST) y estadoFactura (GET).

Obtener token (24 horas)

El token se obtiene con POST /api/auth/token usando api_key y api_secret. El JWT dura 24 horas.

curl -X POST "https://www.facil.com.ar/api/auth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_API_KEY",
    "api_secret": "YOUR_API_SECRET"
  }'
Respuesta OK
{
  "access_token": "JWT_TOKEN",
  "token_type": "Bearer",
  "expires_in": 86400
}
Respuestas de error
HTTP error Detalle
400 MISSING_CREDENTIALS Faltan api_key o api_secret.
401 INVALID_CREDENTIALS Credenciales invalidas o cliente inactivo.
403 IP_NOT_ALLOWED La IP no esta en allowlist.
405 METHOD_NOT_ALLOWED Metodo no permitido (solo POST).
500 SERVER_MISCONFIG_JWT_KEY Servidor sin clave de firma JWT configurada.

Flujo

  1. Obtenés un JWT (Bearer token).
  2. Enviás POST /api/crearFactura con el payload.
  3. Recibís 202 Accepted con job_id.
  4. (Opcional) consultás estado por GET /api/facturas/estado/{jobId}.
  5. (Opcional) descargás el comprobante en PDF por GET /api/facturas/pdf/{jobId} cuando el job está en done.
  6. Cuando finaliza, Factura Fácil envía el resultado a tu callback_url.

POST /api/crearFactura

Asíncrono

Crea un job de facturación y lo encola para ser procesado por el worker.

Respuesta OK
HTTP 202 + job_id
Errores comunes
400 / 401 / 403 / 409 / 500
{
  "ok": true,
  "job_id": "12",
  "status": "queued",
  "attempt": 1,
  "forced": 0,
  "external_id": "TEST-API-002"
}

Payload

Campos principales
Campo Tipo Req. Descripción
ExternalId string Si Id externo para idempotencia (ej: ORD-123).
force bool No Si true, permite reintentar aunque ya exista done/error.
user_login int ID del usuario registrado en Facil a nombre de quien se factura. Debe estar habilitado en Facil.
ExternalIdCliente string No ID externo del receptor de la factura. Si no viene, se guarda vacío.
Fpago int ID de la Forma de pago. (ver en tabla FormasPago).
DocNro string Documento/CUIT/DNI del receptor.
CondicionIVAReceptor int Si en caso que options[Padron] sea false o no se envie ID del tipo de Condicion del receptor (ver en tabla CondicionIVAReceptor).
DocTipo int Si ID del tipo de documento (ver en tabla DocTipo).
NombreCliente string Nombre/Razón social del receptor.
DireccionCliente string Domicilio del receptor.
idProvincia int ID del Código de provincia (ver en tabla Provincias).
Email string No Email del receptor.
Puntovta string/int Punto de venta. Tiene que estar dado de alta en Facil.
Concepto int 1 productos, 2 servicios, 3 ambos.
Fecha string Fecha factura YYYY-MM-DD.
Cbte int No ID de comprobante (ver tabla Comprobantes). Ej: 1.
Moneda string No Default: PES.
Cambio number No Tipo de cambio en caso que Moneda sea distinto de PES, Default: 1.
productos array Productos a facturar. (ver apartado Productos).
options object No Opciones (ver apartado Options).
callback_url string No Webhook para recibir el resultado.
Opciones (options) - ejemplo
{
  "options": {
    "Padron": true,
    "SaveProd": true,
    "SaveMemo": true
  }
}
En PowerShell se puede enviar como: options = @(Padron = true; SaveProd = true; SaveMemo = true)
Options (options)
Campo Tipo Req. Descripcion
Padron bool No Si true, busca datos del padron en ARCA.
SaveProd bool No Si true, guarda los productos en la base de Facil.
SaveMemo bool No Si true, agrega "ExternalId numero: " en el campo observaciones dentro de la factura.
Productos
Campo Tipo Req. Descripción
Codigo string SKU o identificador externo.
Nombre string Nombre del producto/servicio.
Unidad int ID Unidad de medida (ver tabla Unidades).
Importe number Precio final con IVA.
IVA number Porcentaje de IVA (ej: 21).
Cantidad number Valor decimal de cantidades de unidades.

Tablas de referencia

Estos catalogos se obtienen de las tablas internas del sistema y pueden variar segun configuracion.

Formas de Pago (Fpago)
ID Descripcion
0 Contado
1 Cta. Cte.
2 Tarjeta Débito
3 Tarjeta Crédito
4 Cheque
5 Transferencia
6 Otro
DocTipos (DocTipo)
Codigo Descripcion
80 CUIT
86 CUIL
87 CDI
89 LE
90 LC
91 CI Extranjera
92 en trámite
93 Acta Nacimiento
95 CI Bs. As. RNP
96 DNI
94 Pasaporte
99 Doc (CONSUMIDOR FINAL)
Condicion IVA Receptor (CondicionIVAReceptor)
ID Descripcion
9 Cliente del Exterior
5 Consumidor Final
10 IVA Liberado – Ley N° 19.640
15 IVA No Alcanzado
1 IVA Responsable Inscripto
4 IVA Sujeto Exento
16 Monotributo Trabajador Independiente Promovid
8 Proveedor del Exterior
6 Responsable Monotributo
7 Sujeto No Categorizado
Provincias (idProvincia)
Codigo Provincia
1 Buenos Aires
0 Capital Federal
2 Catamarca
16 Chaco
17 Chubut
4 Corrientes
3 Córdoba
5 Entre Ríos
18 Formosa
6 Jujuy
21 La Pampa
8 La Rioja
7 Mendoza
19 Misiones
20 Neuquén
22 Río Negro
9 Salta
10 San Juan
11 San Luis
23 Santa Cruz
12 Santa Fe
13 Santiago del Estero
24 Tierra del Fuego
14 Tucumán
Monedas (Moneda)
Codigo Descripcion
PES Pesos Argentinos
DOL Dolar Estadounidense
002 Dolar Libre EEUU
007 Florines Holandeses
010 Pesos Mejicanos
011 Pesos Uruguayos
014 Coronas Danesas
015 Coronas Noruegas
016 Coronas Suecas
018 Dolar Canadiense
019 Yens
021 Libra Esterlina
023 Bolívar Venezolano
024 Corona Checa
025 Dinar Yugoslavo
026 Dolar Australiano
027 Dracma Griego
028 Florín (Antillas Holandesas)
029 Güaraní
031 Peso Boliviano
032 Peso Colombiano
033 Peso Chileno
034 Rand Sudafricano
036 Sucre Ecuatoriano
051 Dolar de Hong Kong
052 Dolar de Singapur
053 Dolar de Jamaica
054 Dolar de Taiwan
055 Quetzal Guatemalteco
056 Forint (Hungría)
057 Baht (Tailandia)
059 Dinar Kuwaiti
012 Real
030 Shekel (Israel)
035 Nuevo Sol Peruano
060 Euro
040 Lei Rumano
042 Peso Dominicano
043 Balboas Panameñas
044 Córdoba Nicaragüense
045 Dirham Marroquí
046 Libra Egipcia
047 Riyal Saudita
061 Zloty Polaco
062 Rupia Hindú
063 Lempira Hondureña
064 Yuan (Rep. Pop. China)
009 Franco Suizo
041 Derechos Especiales de Giro
049 Gramos de Oro Fino
Unidades (Unidad)
ID Descripcion
7 unidades
1 kilogramos
2 metros
3 metros cuadrados
4 metros cubicos
5 litros
6 1000 kWh
8 pares
9 docenas
10 quilates
11 millares
14 gramos
15 milimetros
16 mm cubicos
17 kilometros
18 hectolitros
20 centimetros
27 cm cubicos
29 toneladas
30 dam cubicos
31 hm cubicos
32 km cubicos
33 microgramos
34 nanogramos
35 picogramos
41 miligramos
47 mililitros
48 curie
49 milicurie
50 microcurie
51 uiacthor
52 muiacthor
53 kg base
54 gruesa
61 kg bruto
62 uiactant
63 muiactant
64 uiactig
65 muiactig
66 kg activo
67 gramo activo
68 gramo base
96 packs
Comprobantes (Cbte)
ID Descripcion
1 Factura A
2 Nota de Debito A
3 Nota de Credito A
4 Recibo A
5 Notas de Venta al contado A
6 Factura B
7 Nota de Debito B
8 Nota de Credito B
9 Recibo B
10 Notas de Venta al contado B
11 Factura C
12 Nota de Debito C
13 Nota de Credito C
15 Recibo C
34 Cbtes. A del Anexo I, Apartado A,inc.f),R.G.Nro. 1415
35 Cbtes. B del Anexo I,Apartado A,inc. f),R.G. Nro. 1415
39 Otros comprobantes A que cumplan con R.G.Nro. 1415
40 Otros comprobantes B que cumplan con R.G.Nro. 1415
49 Comprobante de Compra de Bienes Usados a Consumidor Final
60 Cta de Vta y Liquido prod. A
61 Cta de Vta y Liquido prod. B
63 Liquidacion A
64 Liquidacion B
51 Factura M
52 Nota de Débito M
53 Nota de Crédito M
54 Recibo M
19 Facturas de Exportación
20 Nota de Débito por Operaciones con el Exterior
21 Nota de Crédito por Operaciones con el Exterior
88 Remito Electrónico
89 Resumen de Datos
202 Nota de Débito electrónica MiPyMEs (FCE) A
203 Nota de Crédito electrónica MiPyMEs (FCE) A
206 Factura de Crédito electrónica MiPyMEs (FCE) B
207 Nota de Débito electrónica MiPyMEs (FCE) B
208 Nota de Crédito electrónica MiPyMEs (FCE) B
211 Factura de Crédito electrónica MiPyMEs (FCE) C
212 Nota de Débito electrónica MiPyMEs (FCE) C
213 Nota de Crédito electrónica MiPyMEs (FCE) C
201 Factura de Crédito electrónica MiPyMEs (FCE) A

Ejemplos

JSON de ejemplo
{
  "force": true,
  "ExternalId": "TEST-API-025",
  "user_login": 2,
  "ExternalIdCliente": "CLI-EXT-99",
  "Fpago": 1,
  "DocTipo": 80,
  "DocNro": "27256766316",
  "NombreCliente": "Juan Perez",
  "DireccionCliente": "Av Siempreviva 123",
  "idProvincia": 2,
  "Email": "juan@correo.com",
  "Puntovta": 2,
  "Concepto": 1,
  "Fecha": "2026-01-12",
  "Cbte": 1,
  "Moneda": "PES",
  "Cambio": 1,
  "options": {
    "Padron": true,
    "SaveProd": true,
    "SaveMemo": true
  },

  "productos": [
    { "Codigo": "SKU-001", "Nombre": "Producto1", "Unidad": 7, "Importe": 1210, "IVA": 21, "Cantidad": 1 },
    { "Codigo": "SKU-002", "Nombre": "Producto2", "Unidad": 7, "Importe": 2000, "IVA": 21, "Cantidad": 1 }
  ],

  "callback_url": "https://webhook.site/xxxx"
}
curl -X POST "http://localhost:8080/api/crearFactura" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "force": true,
    "ExternalId": "TEST-API-025",
    "user_login": 2,
    "ExternalIdCliente": "CLI-EXT-99",
    "Fpago": 1,
    "DocTipo": 80,
    "DocNro": "27256766316",
    "NombreCliente": "Juan Perez",
    "DireccionCliente": "Av Siempreviva 123",
    "idProvincia": 2,
    "Email": "juan@correo.com",
    "Puntovta": 2,
    "Concepto": 1,
    "Fecha": "2026-01-12",
    "Cbte": 1,
    "Moneda": "PES",
    "Cambio": 1,
    "options": {
      "Padron": true,
      "SaveProd": true,
      "SaveMemo": true
    },

    "productos": [
        { "Codigo": "SKU-001", "Nombre": "Producto1", "Unidad": 7, "Importe": 1210, "IVA": 21, "Cantidad": 1 },
        { "Codigo": "SKU-002", "Nombre": "Producto2", "Unidad": 7, "Importe": 2000, "IVA": 21, "Cantidad": 1 }
    ],
    "callback_url": "https://webhook.site/xxxx"
  }'
<?php
$token = 'YOUR_JWT_TOKEN';
$url   = 'http://www.facil.com.ar/api/crearFactura';

$payload = [
  "force" => true,
  "ExternalId" => "TEST-API-025",
  "user_login" => 2,
  "ExternalIdCliente" => "CLI-EXT-99",
  "Fpago" => 1,
  "DocTipo" => 80,
  "DocNro" => "27256766316",
  "NombreCliente" => "Juan Perez",
  "DireccionCliente" => "Av Siempreviva 123",
  "idProvincia" => 2,
  "Email" => "juan@correo.com",
  "Puntovta" => 2,
  "Concepto" => 1,
  "Fecha" => "2026-01-12",
  "Cbte" => 1,
  "Moneda" => "PES",
  "Cambio" => 1,
  "options" => [
    "Padron" => true,
    "SaveProd" => true,
    "SaveMemo" => true
  ],
  "productos" => [
    ["Codigo"=>"SKU-001","Nombre"=>"Producto1","Unidad"=>7,"Importe"=>1210,"IVA"=>21,"Cantidad"=>1],
    ["Codigo"=>"SKU-002","Nombre"=>"Producto2","Unidad"=>7,"Importe"=>2000,"IVA"=>21,"Cantidad"=>1],
  ],
  "callback_url" => "https://webhook.site/xxxx"
];

$json = json_encode($payload, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);

$ch = curl_init($url);
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => $json,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Content-Type: application/json',
    'Authorization: Bearer '.$token
  ]
]);

$res = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "HTTP $http\n";
echo $res;
import requests

token = "YOUR_JWT_TOKEN"
url = "http://www.facil.com.ar/api/crearFactura"

payload = {
  "force": True,
  "ExternalId": "TEST-API-025",
  "user_login": 2,
  "ExternalIdCliente": "CLI-EXT-99",
  "Fpago": 1,
  "DocTipo": 80,
  "DocNro": "27256766316",
  "NombreCliente": "Juan Perez",
  "DireccionCliente": "Av Siempreviva 123",
  "idProvincia": 2,
  "Email": "juan@correo.com",
  "Puntovta": 2,
  "Concepto": 1,
  "Fecha": "2026-01-12",
  "Cbte": 1,
  "Moneda": "PES",
  "Cambio": 1,
  "options": {
    "Padron": True,
    "SaveProd": True,
    "SaveMemo": True
  },
  "productos": [
    {"Codigo":"SKU-001","Nombre":"Producto1","Unidad":7,"Importe":1210,"IVA":21,"Cantidad":1},
    {"Codigo":"SKU-002","Nombre":"Producto2","Unidad":7,"Importe":2000,"IVA":21,"Cantidad":1}
  ],
  "callback_url": "https://webhook.site/xxxx"
}

r = requests.post(
  url,
  json=payload,
  headers={
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json"
  },
  timeout=20
)

print(r.status_code)
print(r.text)

GET /api/facturas/estado/{jobId}

Polling opcional

Devuelve el estado de un job. El job debe pertenecer al client_id del token.

curl -X GET "http://www.facil.com.ar/api/facturas/estado/12" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
<?php
$url = 'http://www.facil.com.ar/api/facturas/estado/12';
$token = 'YOUR_JWT_TOKEN';

$ch = curl_init($url);
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT => 20,
]);

$res = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "HTTP: $http\n";
echo $res;
import requests

url = "http://www.facil.com.ar/api/facturas/estado/12"
token = "YOUR_JWT_TOKEN"

r = requests.get(
    url,
    headers={"Authorization": f"Bearer {token}"},
    timeout=20,
)

print(r.status_code)
print(r.text)
{
  "ok": true,
  "job_id": "12",
  "external_id": "TEST-API-002",
  "status": "done",
  "error_msg": null,
  "result": {
    "FacturaNumero": "0002-00000123",
    "CAE": "72345678901234",
    "FchVtoCAE": "20260201"
  },
  "created_at": "2026-01-13 14:21:33",
  "updated_at": "2026-01-13 14:22:10"
}

GET /api/facturas/pdf/{jobId}

Descarga PDF

Devuelve el PDF del comprobante emitido para ese job. El job debe pertenecer al client_id del token y estar en estado done.

curl -L -X GET "http://www.facil.com.ar/api/facturas/pdf/12" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  --output comprobante_12.pdf
<?php
$url = 'http://www.facil.com.ar/api/facturas/pdf/12';
$token = 'YOUR_JWT_TOKEN';

$ch = curl_init($url);
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_TIMEOUT => 30,
]);

$pdf = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($http === 200 && $pdf !== false) {
  file_put_contents('comprobante_12.pdf', $pdf);
  echo "PDF guardado\n";
} else {
  echo "Error HTTP $http\n";
}
import requests

url = "http://www.facil.com.ar/api/facturas/pdf/12"
token = "YOUR_JWT_TOKEN"

r = requests.get(
    url,
    headers={"Authorization": f"Bearer {token}"},
    timeout=30,
)

if r.status_code == 200:
    with open("comprobante_12.pdf", "wb") as f:
        f.write(r.content)
    print("PDF guardado")
else:
    print("Error:", r.status_code, r.text)
Errores comunes: 404 JOB_NOT_FOUND, 409 JOB_NOT_DONE, 404 PDF_KEY_NOT_FOUND, 502 PDF_FETCH_FAILED.

Webhooks (callback_url) + Firma

Cuando el job finaliza, Factura Fácil envía un POST al callback_url con el resultado.

Headers
  • Content-Type: application/json
  • X-Facil-Webhook-Version: 1
  • X-Facil-Job-Id, X-Facil-External-Id, X-Facil-Attempt
  • X-Facil-Signature: sha256=<hmac> (si hay webhook_secret)
Verificación (PHP)
<?php
$secret = 'TU_WEBHOOK_SECRET';

$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_FACIL_SIGNATURE'] ?? '';

$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);

if (!hash_equals($expected, $sig)) {
  http_response_code(401);
  echo "INVALID_SIGNATURE\n";
  exit;
}

http_response_code(200);
echo "OK\n";
Verificación (Python / Flask)
from flask import Flask, request, abort
import hmac, hashlib

app = Flask(__name__)
SECRET = b"TU_WEBHOOK_SECRET"

@app.post("/webhook/facil")
def facil_webhook():
    raw = request.get_data()
    sig = request.headers.get("X-Facil-Signature","")

    expected = "sha256=" + hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, sig):
        abort(401)

    print("OK:", request.json)
    return "OK", 200
Probar callbacks firmados (cURL + Python para generar firma)

Este ejemplo genera la firma con Python y hace el POST al endpoint de tu webhook.

BODY='{"webhook_version":1,"event":"invoice.job.updated","job_id":"12","status":"done"}'
SECRET='TU_WEBHOOK_SECRET'
SIG=$(python - <<'PY'
import hmac,hashlib,os
body=os.environ["BODY"].encode()
secret=os.environ["SECRET"].encode()
print("sha256="+hmac.new(secret, body, hashlib.sha256).hexdigest())
PY
)

curl -X POST "https://tucliente.com/webhook/facil" \
  -H "Content-Type: application/json" \
  -H "X-Facil-Signature: '"$SIG"'" \
  -d "$BODY"

Versionado

  • X-Facil-Webhook-Version: 1
  • payload.webhook_version = 1
La versión v2 puede agregar campos, cambiar estructura del result, o incorporar nuevos eventos.

Errores

400 — VALIDATION_ERROR
{
  "error": "VALIDATION_ERROR",
  "fields": {
    "IdCliente": "required",
    "Email": "invalid_email"
  }
}
403 — IDCLIENTE_NOT_ALLOWED
{ "error": "IDCLIENTE_NOT_ALLOWED" }
409 — Idempotencia / reintentos
Según estado del último job y force, la API puede responder 409 para evitar duplicados o indicar reintento requerido.

Changelog

v1
POST crearFactura, GET estado, GET pdf, webhooks firmados (HMAC)
Actual