PRÓXIMAMENTE afiPAPI ahora también como librería PHP — facturá ARCA desde tu propio hosting. Ver el adelanto →
Referencia

Todos los endpoints

Ruta, método, esquema con tipos y un ejemplo real del JSON de entrada y de la respuesta. El contrato es el mismo para cualquier lenguaje: solo cambia el cliente HTTP.

Base URL (desarrollo)http://localhost:5014
Prefijo/api/afip
FormatoJSON · { ok, data }
Content-Typeapplication/json
Cómo leer cada endpoint: el bloque esquema define el contrato con tipos (int, string, bool, decimal); el bloque ejemplo es un payload real listo para copiar. La respuesta se muestra con el sobre completo { "ok", "data" }.
Regla de oro: un HTTP 200 no implica éxito funcional. Revisá siempre ok; si es false, el detalle está en data.error / data.detail (forma única en Errores). Tras el login la API cachea el token y lo renueva sola: el cliente no maneja token ni sign.
¿Recién empezás? Antes del detalle técnico, leé la guía para novatos — qué hace cada endpoint en lenguaje simple, sin tecnicismos.

Autenticación y diagnóstico

POST/api/afip/login
Autentica un CUIT contra WSAA, registra el certificado y cachea token/sign. Se hace una vez por CUIT; después la API renueva sola.
request · esquema
{
  "cuit": int,
  "servicio": string,
  "certificadoPath": string,
  "certificadoPassword": string,
  "produccion": bool
}
request · ejemplo
{
  "cuit": 20238233195,
  "servicio": "wsfe",
  "certificadoPath": "C:\\Certificados\\cert.pfx",
  "certificadoPassword": "clave",
  "produccion": false
}
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "token": string,
    "sign": string,
    "expiration": string
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "token": "abc123",
    "sign": "xyz456",
    "expiration": "2026-03-20T12:00:00"
  }
}
GET/api/afip/status?cuit=&produccion=
Estado del token y del certificado de un CUIT. Parámetros por query string: cuit (int) y produccion (bool). Sin cuerpo.
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "cuit": int,
    "tokenActivo": bool,
    "certificadoRegistrado": bool,
    "expira": string,
    "minutosRestantes": int
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "cuit": 20238233195,
    "tokenActivo": true,
    "certificadoRegistrado": true,
    "expira": "2026-03-20T12:00:00",
    "minutosRestantes": 120
  }
}
GET/api/afip/health?produccion=
Salud de la API más el Dummy de ARCA (App/Db/AuthServer) y un resumen de la cache. Sin cuerpo.
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "api":   { "estado": string, "fecha": string },
    "afip":  { "AppServer": string, "DbServer": string, "AuthServer": string },
    "cache": { "cuitsRegistrados": int, "tokensActivos": int }
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "api":   { "estado": "OK", "fecha": "2026-03-18T10:00:00" },
    "afip":  { "AppServer": "OK", "DbServer": "OK", "AuthServer": "OK" },
    "cache": { "cuitsRegistrados": 2, "tokensActivos": 2 }
  }
}
GETPOST/api/afip/pingnuevo
Chequea la conectividad (conexión TCP + latencia) a los webservices de ARCA y, opcionalmente, a servidores propios (ej. tu MySQL). Sirve para decidir antes de operar si conviene conectarse. El chequeo corre solo en segundo plano y se cachea: la respuesta es instantánea.
📖 Explicación en lenguaje natural →
GET /api/afip/ping?produccion=false devuelve solo los webservices de ARCA (WSAA + WSFE), servidos de cache. Sin cuerpo. El POST agrega destinos propios.
request · POST · esquema
{
  "produccion": bool,
  "incluirAfip": bool,       // opcional (default true): incluye WSAA + WSFE
  "destinos": [
    {
      "nombre": string,      // opcional (etiqueta)
      "host": string,
      "puerto": int,
      "tipo": string         // "tcp" (default) | "mysql"
                             // sin tipo y puerto 3306 ⇒ mysql
    }
  ]
}
request · POST · ejemplo
{
  "produccion": false,
  "destinos": [
    { "nombre": "MySQL", "host": "10.0.0.5", "puerto": 3306, "tipo": "mysql" }
  ]
}
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "fecha": string,
    "produccion": bool,
    "afipAccesible": bool,       // agregado WSAA + WSFE
    "objetivos": [
      {
        "nombre": string,
        "grupo": string,         // "afip" | "custom"
        "host": string,
        "puerto": int,
        "tipo": string,          // "tcp" | "mysql"
        "accesible": bool,
        "latenciaMs": int,       // null si no accesible
        "servidor": string,      // extra (ej. versión MySQL); null si no aplica
        "error": string,         // motivo si no accesible; null si ok
        "fechaChequeo": string,
        "edadSegundos": int      // antigüedad del dato cacheado
      }
    ]
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "fecha": "2026-07-23T10:15:03",
    "produccion": false,
    "afipAccesible": true,
    "objetivos": [
      { "nombre": "WSAA", "grupo": "afip", "host": "wsaahomo.afip.gov.ar", "puerto": 443,
        "tipo": "tcp", "accesible": true, "latenciaMs": 84, "servidor": null,
        "error": null, "fechaChequeo": "2026-07-23T10:14:51", "edadSegundos": 12 },
      { "nombre": "MySQL", "grupo": "custom", "host": "10.0.0.5", "puerto": 3306,
        "tipo": "mysql", "accesible": true, "latenciaMs": 3, "servidor": "MySQL 8.0.36",
        "error": null, "fechaChequeo": "2026-07-23T10:14:51", "edadSegundos": 12 }
    ]
  }
}
Cache + chequeo recurrente: los webservices de ARCA se re-chequean solos cada ~30 s; la única llamada que espera es la primera de un destino propio nuevo, después sale de cache. Un destino propio deja de chequearse a los 15 min sin pedirlo. MySQL se chequea sin credenciales (abre la conexión y lee el saludo del server). Para decidir si te conectás, mirá afipAccesible o el accesible / latenciaMs de cada objetivo.
GET/api/afip/cache
Lista la cache de tokens/certificados por CUIT y ambiente. Útil para diagnóstico. Sin cuerpo.
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "total": int,
    "data": [
      { "cuit": int, "ambiente": string, "tokenActivo": bool }
    ]
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "total": 2,
    "data": [
      { "cuit": 20238233195, "ambiente": "Homologacion", "tokenActivo": true }
    ]
  }
}

Comprobantes

POST/api/afip/ultimo
Último número autorizado para un punto de venta + tipo de comprobante.
request · esquema
{
  "cuit": int,
  "puntoVenta": int,
  "tipoComprobante": int,
  "produccion": bool
}
request · ejemplo
{
  "cuit": 20238233195,
  "puntoVenta": 1,
  "tipoComprobante": 6,
  "produccion": false
}
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "puntoVenta": int,
    "tipoComprobante": int,
    "ultimoNumero": int
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "puntoVenta": 1,
    "tipoComprobante": 6,
    "ultimoNumero": 152
  }
}
POST/api/afip/consultarnuevo
Recupera un comprobante puntual ya emitido (datos + CAE). Si no existe, ARCA devuelve error (ej. código 602) y la respuesta viene con ok:false.
request · esquema
{
  "cuit": int,
  "produccion": bool,
  "puntoVenta": int,
  "tipoComprobante": int,
  "numero": int
}
request · ejemplo
{
  "cuit": 20238233195,
  "produccion": false,
  "puntoVenta": 1,
  "tipoComprobante": 6,
  "numero": 152
}
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "puntoVenta": int,
    "tipoComprobante": int,
    "numeroComprobante": int,
    "documentoTipo": string,
    "documentoNumero": string,
    "fechaComprobante": string,
    "importeTotal": decimal,
    "moneda": string,
    "cotizacion": decimal,
    "resultado": string,
    "CAE": string,
    "fechaVencimientoCAE": string
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "puntoVenta": 1,
    "tipoComprobante": 6,
    "numeroComprobante": 152,
    "documentoTipo": "80",
    "documentoNumero": "20111111112",
    "fechaComprobante": "20260318",
    "importeTotal": 121,
    "moneda": "PES",
    "cotizacion": 1,
    "resultado": "A",
    "CAE": "74328954736291",
    "fechaVencimientoCAE": "20260328"
  }
}
POST/api/afip/resumen-emitidosnuevo
Resumen de comprobantes propios emitidos en un rango (itera la consulta por número). Devuelve la lista + un totalizador.
request · esquema
{
  "cuit": int,
  "produccion": bool,
  "puntoVenta": int,
  "tipoComprobante": int,
  "desde": int,   // opcional — sin "desde" arranca en 1
  "hasta": int    // opcional — sin "hasta" usa el último autorizado
}
request · ejemplo
{
  "cuit": 20238233195,
  "produccion": false,
  "puntoVenta": 1,
  "tipoComprobante": 6,
  "desde": 1,
  "hasta": 50
}
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "puntoVenta": int,
    "tipoComprobante": int,
    "desde": int,
    "hasta": int,
    "cantidad": int,
    "autorizados": int,
    "conError": int,
    "importeTotal": decimal,
    "comprobantes": [ object ]
    // cada item con la forma de /consultar;
    // los fallidos: { "numeroComprobante": int, "error": string }
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "puntoVenta": 1,
    "tipoComprobante": 6,
    "desde": 1,
    "hasta": 50,
    "cantidad": 50,
    "autorizados": 48,
    "conError": 2,
    "importeTotal": 152340.50,
    "comprobantes": [ /* ...48 ok + 2 con error... */ ]
  }
}
Tope: 1000 comprobantes por consulta (cada número es una llamada SOAP). Cubre solo lo emitido por webservice — no incluye recibidos ni lo emitido por "Comprobantes en Línea" / controlador fiscal.
POST/api/afip/emitir
Emite un comprobante (WSFE) y devuelve CAE, vencimiento y número.
request · esquema
{
  "cuit": int,
  "produccion": bool,
  "puntoVenta": int,
  "tipoComprobante": int,
  "concepto": int,
  "documentoTipo": int,
  "documentoNumero": int,
  "importeTotal": decimal,
  "importeNoGravado": decimal,
  "importeExento": decimal,
  "importeGravado": decimal,
  "importeIva": decimal,
  "moneda": string,
  "cotizacion": decimal,
  "condicionIvaReceptorId": int,
  "alicuotaIvaId": int
  // concepto 2/3: fechaServicioDesde, fechaServicioHasta,
  //               fechaVencimientoPago  (string, yyyyMMdd)
  // NC/ND: "cbteAsoc": { "tipo": int, "puntoVenta": int, "numero": int,
  //                      "cuit": int (opc), "cbteFch": string (opc) }
}
request · ejemplo
{
  "cuit": 20238233195,
  "produccion": false,
  "puntoVenta": 1,
  "tipoComprobante": 6,
  "concepto": 1,
  "documentoTipo": 80,
  "documentoNumero": 20111111112,
  "importeTotal": 121,
  "importeNoGravado": 0,
  "importeExento": 0,
  "importeGravado": 100,
  "importeIva": 21,
  "moneda": "PES",
  "cotizacion": 1,
  "condicionIvaReceptorId": 1,
  "alicuotaIvaId": 5
}
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "resultado": string,
    "CAE": string,
    "fechaVencimientoCAE": string,
    "numeroComprobante": int
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "resultado": "A",
    "CAE": "74328954736291",
    "fechaVencimientoCAE": "20260321",
    "numeroComprobante": 153
  }
}
Hoy /emitir admite una sola alícuota de IVA y no envía tributos. Para concepto 2 o 3 (servicios) son obligatorias las tres fechas en formato yyyyMMdd.

Padrón

POST/api/afip/padron/constancianuevo
Consulta el padrón de ARCA por un CUIT y deriva su condición fiscal y si está habilitado a emitir Factura A. cuit = emisor con certificado; cuitConsultado = CUIT a buscar.
request · esquema
{ "cuit": int, "cuitConsultado": int, "produccion": bool }
request · ejemplo
{ "cuit": 20238233195, "cuitConsultado": 20111111112, "produccion": false }
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": {
    "cuitConsultado": int,
    "denominacion": string,
    "tipoPersona": string,
    "estadoClave": string,
    "domicilioFiscal": { "direccion": string, "localidad": string, "codigoPostal": string, "provincia": string },
    "esMonotributista": bool,
    "inscriptoIva": bool,
    "condicionFiscal": "MONOTRIBUTO | RESPONSABLE_INSCRIPTO | NO_INSCRIPTO_IVA",
    "puedeEmitirFacturaA": bool,
    "motivo": string,
    "impuestos": [ { "id": int, "descripcion": string, "estado": string } ]
  }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": {
    "cuitConsultado": 20111111112,
    "denominacion": "PEREZ JUAN",
    "tipoPersona": "FISICA",
    "estadoClave": "ACTIVO",
    "esMonotributista": true,
    "inscriptoIva": false,
    "condicionFiscal": "MONOTRIBUTO",
    "puedeEmitirFacturaA": false,
    "motivo": "Monotributista: emite Factura C, no Factura A.",
    "impuestos": []
  }
}
puedeEmitirFacturaA es una inferencia desde la condición fiscal, no un permiso explícito de ARCA: la validación definitiva la da /emitir. Requiere que el CUIT tenga habilitado el WS de padrón (ws_sr_padron_a5) en el Administrador de Relaciones de ARCA.

Tablas ARCA

Las 10 comparten el mismo request { cuit, produccion } y devuelven una lista { Id, Descripcion }. Las marcadas nuevo se agregaron en la última versión.

📖 Explicación en lenguaje natural →
Ruta (POST)Devuelve
/puntos-ventaPuntos de venta habilitados
/tipos-comprobanteTipos de comprobante
/tipos-documentoTipos de documento
/tipos-conceptoConceptos (prod/serv/ambos)
/tipos-ivaAlícuotas de IVA
/tipos-monedaMonedas habilitadasnuevo
/tipos-tributoTipos de tributonuevo
/tipos-opcionalCampos opcionalesnuevo
/condiciones-iva-receptorCondiciones IVA del receptor (RG 5616)nuevo
/actividadesActividades económicas del emisornuevo
request · esquema
{ "cuit": int, "produccion": bool }
request · ejemplo
{ "cuit": 20238233195, "produccion": false }
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": [
    { "Id": string, "Descripcion": string }
  ]
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": [
    { "Id": "5", "Descripcion": "21%" },
    { "Id": "4", "Descripcion": "10.5%" }
  ]
}

Moneda

POST/api/afip/cotizacionnuevo
Cotización oficial de una moneda. Útil para facturar en moneda extranjera con el valor que espera ARCA.
request · esquema
{ "cuit": int, "moneda": string, "produccion": bool }
request · ejemplo
{ "cuit": 20238233195, "moneda": "DOL", "produccion": false }
respuesta · ok:true · esquema
{
  "ok": bool,
  "data": { "moneda": string, "cotizacion": decimal, "fechaCotizacion": string }
}
respuesta · ok:true · ejemplo
{
  "ok": true,
  "data": { "moneda": "DOL", "cotizacion": 1045.50, "fechaCotizacion": "20260318" }
}

Tablas de códigos

Valores más usados en /emitir y /ultimo. La lista oficial completa se puede traer dinámicamente con los endpoints de tablas.

Tipos de comprobante — campo tipoComprobante

IdDescripción
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

Tipos de documento — campo documentoTipo

IdDescripción
80CUIT
86CUIL
96DNI
99Consumidor Final (sin identificar)
Para consumidor final sin datos: documentoTipo: 99 y documentoNumero: 0. La lista completa y actualizada se obtiene con POST /tipos-comprobante y POST /tipos-documento.

Alícuotas de IVA — campo alicuotaIvaId

IdAlícuota
30%
410.5%
521%
627%
85%
92.5%
Lista oficial completa con POST /tipos-iva.

Condición IVA del receptor — campo condicionIvaReceptorId (RG 5616)

IdDescripción
1Responsable Inscripto
4Sujeto Exento
5Consumidor Final
6Monotributo
13Monotributo Social
15No Alcanzado
Obligatorio en /emitir desde la RG 5616. Lista oficial completa con POST /condiciones-iva-receptor.

Errores

Cualquier endpoint puede responder con ok:false. La forma es siempre la misma — no se repite arriba por endpoint.

respuesta · ok:false · esquema
{
  "ok": bool,
  "data": {
    "error": string,
    "detail": string,
    "status": int
  }
}
respuesta · ok:false · ejemplo
{
  "ok": false,
  "data": {
    "error": "Certificado no registrado para el CUIT",
    "detail": "Ejecutá /login antes de operar.",
    "status": 500
  }
}

Seguir

Guía de integración › Guía completa Visual FoxPro › Descargas ›