Serverless · AWS Lambda · AFIP WSFEv1

Facturación electrónica de AFIP
sin SOAP, sin sorpresas

Mandás un JSON con los datos del comprobante y recibís el CAE. FaelAPI se ocupa de la autenticación con certificado, del XML de AFIP, de la numeración, de los cálculos y de los reintentos.

curl -s https://api.faelapi.com.ar/FECAESolicitar \
  -H "x-api-key: $FAELAPI_KEY" \
  -d @factura.json
Qué resuelve

Todo lo que hay entre tu sistema y el CAE

Hablás JSON

La API traduce a SOAP/XML, firma el ticket de acceso y parsea las respuestas de AFIP. Nada de WSDL ni certificados en cada llamada de negocio.

Cálculos automáticos

Fecha del día, próximo número de comprobante, IVA como suma de alícuotas y total, todo redondeado a dos decimales. Vos mandás el neto.

Lotes de hasta 50

FECAESolicitarV2 emite varios comprobantes en una llamada. Un rechazo no arrastra a los demás: los siguientes se reprocesan solos.

Reintentos seguros

Reintenta ante errores transitorios de AFIP y numeración en conflicto. Nunca reenvía una solicitud que pudo haberse emitido.

Homologación y producción

Elegís el ambiente de AFIP por request con el campo env. Probá en homologación y pasá a producción sin cambiar nada más.

Estadísticas de uso

Cada comprobante emitido queda registrado con su resultado. Próximamente: panel con consumo por mes y por CUIT emisor.

Cómo funciona

Tres llamadas para facturar

  1. Autenticarse

    Una vez cada 12 horas, LoginCSM con tu certificado y clave. Guardá token y sign hasta expiration_time: AFIP no entrega otro ticket antes.

  2. Pedir el CAE

    FECAESolicitar con los datos del comprobante. No mandás fecha ni número: la API los resuelve. Para varios comprobantes, FECAESolicitarV2.

  3. Consultar cuando quieras

    FECompConsultar devuelve el detalle de cualquier comprobante emitido, con su CAE y estado.

Referencia

Endpoints

Base URL https://api.faelapi.com.ar. Todos son POST con cuerpo JSON. Los nombres de campo siguen a los del web service de AFIP.

POST

/LoginCSM

WSAA

Autenticación contra AFIP con el certificado digital del contribuyente. Devuelve token y sign, válidos 12 horas. AFIP entrega un ticket por certificado cada 12 horas: guardalos hasta expiration_time.

Request
{
  "cert": "<certificado PEM en base64>",
  "key":  "<clave privada PEM en base64>",
  "env":  "wsaahomo.afip.gov.ar"
}
Response
{
  "token": "PD94bWwgdmVy...",
  "sign": "X9VQ4Y5klZR...",
  "expiration_time": "2026-09-17T22:04:37.016-03:00"
}
POST

/FECAESolicitar

CAE

Solicita el CAE de un comprobante. La API pone la fecha del día, obtiene el próximo número, recalcula IVA y total y reintenta ante errores transitorios de AFIP.

Request
{
  "Env": "wswhomo.afip.gov.ar",
  "FECAESolicitar": {
    "Auth": { "Token": "...", "Sign": "...", "Cuit": "27268498511" },
    "FeCAEReq": {
      "FeCabReq": { "PtoVta": 1, "CbteTipo": 6 },
      "FeDetReq": {
        "FECAEDetRequest": {
          "Concepto": 1, "DocTipo": 99, "DocNro": "0",
          "ImpNeto": 100, "MonId": "PES", "MonCotiz": 1,
          "CondicionIVAReceptorId": 5,
          "Iva": { "AlicIva": [ { "Id": 5, "BaseImp": 100, "Importe": 21 } ] }
        }
      }
    }
  }
}
Response
{
  "Concepto": 1, "DocTipo": 99, "DocNro": 0,
  "CbteDesde": 605, "CbteHasta": 605,
  "Resultado": "A",
  "CAE": "86380904179223",
  "CbteFch": "20260917", "CAEFchVto": "20260927",
  "Observaciones": { "Obs": null }
}
POST

/FECAESolicitarV2

CAE · LOTE

Igual que FECAESolicitar, pero FECAEDetRequest es un array de hasta 50 comprobantes y la respuesta es un array en el mismo orden. Si AFIP rechaza uno, los siguientes se reprocesan renumerados automáticamente.

Request
{
  "Env": "wswhomo.afip.gov.ar",
  "FECAESolicitar": {
    "Auth": { "Token": "...", "Sign": "...", "Cuit": "27268498511" },
    "FeCAEReq": {
      "FeCabReq": { "PtoVta": 1, "CbteTipo": 6 },
      "FeDetReq": {
        "FECAEDetRequest": [
          { "Concepto": 1, "DocTipo": 99, "DocNro": "0", "ImpNeto": 50,   "...": "..." },
          { "Concepto": 1, "DocTipo": 99, "DocNro": "0", "ImpNeto": 75.5, "...": "..." }
        ]
      }
    }
  }
}
Response
[
  { "CbteDesde": 606, "CbteHasta": 606, "Resultado": "A", "CAE": "86380904179338", "...": "..." },
  { "CbteDesde": 607, "CbteHasta": 607, "Resultado": "A", "CAE": "86380904179342", "...": "..." }
]
POST

/FECompConsultar

CONSULTA

Detalle completo de un comprobante ya emitido: importes, IVA, tributos, CAE, estado y observaciones.

Request
{
  "env": "wswhomo.afip.gov.ar",
  "FECompConsultar": {
    "Auth": { "Token": "...", "Sign": "...", "Cuit": "27268498511" },
    "FeCompConsReq": { "CbteTipo": 6, "PtoVta": 1, "CbteNro": 605 }
  }
}
Response
{
  "CbteDesde": 605, "CbteHasta": 605, "CbteFch": "20260917",
  "ImpTotal": 121.15, "ImpNeto": 100.12, "ImpIVA": 21.03,
  "MonId": "PES", "MonCotiz": 1,
  "Resultado": "A", "CodAutorizacion": "86380904179223",
  "EmisionTipo": "CAE", "FchVto": "20260927",
  "...": "..."
}
POST

/FEParamGetTiposCbte

PARÁMETROS

Catálogo de tipos de comprobante habilitados por AFIP: facturas A, B, C, notas de crédito y débito, y más.

Request
{
  "token": "...",
  "sign": "...",
  "cuit": "27268498511",
  "env": "wswhomo.afip.gov.ar"
}
Response
[
  { "ID": 1,  "Desc": "Factura A",         "FchDesde": "20100917", "FchHasta": "NULL" },
  { "ID": 6,  "Desc": "Factura B",         "FchDesde": "20100917", "FchHasta": "NULL" },
  { "ID": 11, "Desc": "Factura C",         "FchDesde": "20100917", "FchHasta": "NULL" },
  { "ID": 3,  "Desc": "Nota de Crédito A", "FchDesde": "20100917", "FchHasta": "NULL" }
]

Reglas que aplica la API en FECAESolicitar

  • CbteFch se fija en la fecha del día (hora argentina), aunque venga en el request.
  • CbteDesde y CbteHasta salen del último comprobante autorizado + 1.
  • ImpIVA se recalcula como suma de AlicIva[].Importe; ImpTotal como neto + IVA + exento + no gravado + tributos. Todo a dos decimales.
  • Ante un error 502 de AFIP se reintenta una vez; ante un 10016 (número en uso) se renumera y se reintenta.
  • Si AFIP no responde después de enviada la solicitud, se devuelve 504 sin reintentar: consultá el último autorizado antes de volver a pedir.

API key

Cada cliente recibe una key para su ambiente de pruebas y otra para producción. Va en el header x-api-key en todas las llamadas. El cuerpo no cambia.

x-api-key: q7T…

Toda respuesta incluye X-Request-Id para seguimiento.

Ambientes de AFIP

El campo env del cuerpo indica contra qué AFIP se opera. Es independiente de la URL.

ServicioHomologaciónProducción
WSAA (LoginCSM)wsaahomo.afip.gov.arwsaa.afip.gov.ar
WSFE (resto)wswhomo.afip.gov.arservicios1.afip.gov.ar
Errores

Qué devuelve cuando algo falla

HTTPCuerpoSignificado
400Invalid request bodyEl cuerpo no es JSON válido. Texto plano.
400[{"Code": 10015, "Msg": "..."}]AFIP rechazó la operación. Uno o más errores con el código y mensaje de AFIP.
400Certificado expiradoLoginCSM: problema con el certificado o respuesta de error de WSAA. Texto plano.
401[{"Code": 401, "Msg": "API key inválida"}]La x-api-key no existe.
403[{"Code": 403, "Msg": "tenant suspendido"}]La cuenta está suspendida.
429[{"Code": 429, "Msg": "cuota mensual del plan agotada"}]Se superó la cantidad de llamadas del plan en el mes.
504[{"Code": 504, "Msg": "AFIP no respondió a tiempo en ..."}]AFIP no respondió. El mensaje indica si la solicitud de CAE ya había sido enviada, para consultar antes de reintentar.

Un comprobante rechazado por AFIP no es un error HTTP: llega con 200, Resultado: "R" y las observaciones que explican el rechazo.

¿Querés integrar tu sistema?

Escribinos y te damos una key de homologación para que pruebes con tu propio certificado.

Pedir acceso