Guía de integración

Una API. Cualquier lenguaje.

afiPAPI es HTTP + JSON. Elegí tu entorno y copiá el ejemplo: el flujo es siempre el mismo.

Conceptos base

Base URL (desarrollo)http://localhost:5014
Prefijo de endpoints/api/afip
FormatoJSON · { ok, data }
Autenticaciónlogin una vez por CUIT
Regla de oro: un HTTP 200 no implica éxito. Revisá siempre ok; si es false, el detalle está en data.error y data.detail. Tras el login, la API cachea el token y lo renueva sola — no hace falta autenticar en cada operación.

Inicio rápido

Mismo flujo en todos los lenguajes: login → (último) → emitir, y leer el CAE de la respuesta.

bash
# 1) Login (una vez por CUIT)
curl -X POST http://localhost:5014/api/afip/login \
  -H "Content-Type: application/json" \
  -d '{"cuit":20238233195,"servicio":"wsfe","certificadoPath":"C:\\Certificados\\cert.pfx","certificadoPassword":"clave","produccion":false}'

# 2) Último número (Factura B, punto de venta 1)
curl -X POST http://localhost:5014/api/afip/ultimo \
  -H "Content-Type: application/json" \
  -d '{"cuit":20238233195,"puntoVenta":1,"tipoComprobante":6,"produccion":false}'

# 3) Emitir
curl -X POST http://localhost:5014/api/afip/emitir \
  -H "Content-Type: application/json" \
  -d '{"cuit":20238233195,"produccion":false,"puntoVenta":1,"tipoComprobante":6,
       "concepto":1,"documentoTipo":99,"documentoNumero":0,
       "importeTotal":121,"importeGravado":100,"importeIva":21,
       "moneda":"PES","cotizacion":1,"condicionIvaReceptorId":5,"alicuotaIvaId":5}'
C# · .NET
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;

var http = new HttpClient { BaseAddress = new Uri("http://localhost:5014") };

// 1) Login (una vez por CUIT)
await http.PostAsJsonAsync("/api/afip/login", new {
    cuit = 20238233195L, servicio = "wsfe",
    certificadoPath = @"C:\Certificados\cert.pfx",
    certificadoPassword = "clave", produccion = false
});

// 2) Emitir
var resp = await http.PostAsJsonAsync("/api/afip/emitir", new {
    cuit = 20238233195L, produccion = false,
    puntoVenta = 1, tipoComprobante = 6, concepto = 1,
    documentoTipo = 99, documentoNumero = 0,
    importeTotal = 121m, importeGravado = 100m, importeIva = 21m,
    moneda = "PES", cotizacion = 1m,
    condicionIvaReceptorId = 5, alicuotaIvaId = 5
});

using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var root = doc.RootElement;
if (root.GetProperty("ok").GetBoolean())
    Console.WriteLine("CAE: " + root.GetProperty("data").GetProperty("CAE").GetString());
Python · requests
import requests
BASE = "http://localhost:5014/api/afip"

# 1) Login (una vez por CUIT)
requests.post(f"{BASE}/login", json={
    "cuit": 20238233195, "servicio": "wsfe",
    "certificadoPath": r"C:\Certificados\cert.pfx",
    "certificadoPassword": "clave", "produccion": False,
})

# 2) Emitir
r = requests.post(f"{BASE}/emitir", json={
    "cuit": 20238233195, "produccion": False,
    "puntoVenta": 1, "tipoComprobante": 6, "concepto": 1,
    "documentoTipo": 99, "documentoNumero": 0,
    "importeTotal": 121, "importeGravado": 100, "importeIva": 21,
    "moneda": "PES", "cotizacion": 1,
    "condicionIvaReceptorId": 5, "alicuotaIvaId": 5,
})

res = r.json()
print("CAE:", res["data"]["CAE"]) if res["ok"] else print("Error:", res["data"]["error"])
JavaScript · fetch (Node 18+ / navegador)
const BASE = "http://localhost:5014/api/afip";

const post = (path, body) =>
  fetch(`${BASE}${path}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  }).then(r => r.json());

// 1) Login (una vez por CUIT)
await post("/login", {
  cuit: 20238233195, servicio: "wsfe",
  certificadoPath: "C:\\Certificados\\cert.pfx",
  certificadoPassword: "clave", produccion: false,
});

// 2) Emitir
const res = await post("/emitir", {
  cuit: 20238233195, produccion: false,
  puntoVenta: 1, tipoComprobante: 6, concepto: 1,
  documentoTipo: 99, documentoNumero: 0,
  importeTotal: 121, importeGravado: 100, importeIva: 21,
  moneda: "PES", cotizacion: 1,
  condicionIvaReceptorId: 5, alicuotaIvaId: 5,
});

if (res.ok) console.log("CAE:", res.data.CAE);
else console.error("Error:", res.data.error);
PHP · cURL
<?php
$BASE = "http://localhost:5014/api/afip";

function afip(string $path, array $payload): array {
    global $BASE;
    $ch = curl_init($BASE . $path);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => ["Content-Type: application/json"],
        CURLOPT_POSTFIELDS     => json_encode($payload),
    ]);
    $res = json_decode(curl_exec($ch), true);
    curl_close($ch);
    return $res;
}

// 1) Login (una vez por CUIT)
afip("/login", [
    "cuit" => 20238233195, "servicio" => "wsfe",
    "certificadoPath" => "C:\\Certificados\\cert.pfx",
    "certificadoPassword" => "clave", "produccion" => false,
]);

// 2) Emitir
$res = afip("/emitir", [
    "cuit" => 20238233195, "produccion" => false,
    "puntoVenta" => 1, "tipoComprobante" => 6, "concepto" => 1,
    "documentoTipo" => 99, "documentoNumero" => 0,
    "importeTotal" => 121, "importeGravado" => 100, "importeIva" => 21,
    "moneda" => "PES", "cotizacion" => 1,
    "condicionIvaReceptorId" => 5, "alicuotaIvaId" => 5,
]);

echo $res["ok"] ? "CAE: " . $res["data"]["CAE"] : "Error: " . $res["data"]["error"];
Visual FoxPro
* Cliente en 3 capas: AfipApi / FacturadorAfip / AfipHelpers
loFact = NEWOBJECT("FacturadorAfip", "FacturadorAfip.prg", "", ;
   "http://localhost:5014", 20238233195, .F., ;
   "C:\Certificados\cert.pfx", "clave")

loFact.Inicializar()                && /login (registra cert + token)

loEmi = loFact.EmitirFactura( ;
   1, 6, 1, 99, 0, ;               && PV, tipo, concepto, docTipo, docNro
   121, 0, 0, 100, 21, ;           && total, noGrav, exento, gravado, IVA
   "PES", 1, 5, 5, "", "", "")     && moneda, cotiz, condIVA, alicIVA, fechas

IF loEmi.Ok
   ? "CAE:", loEmi.CAE
ENDIF
VFP tiene guía dedicada. Las clases completas, todos los endpoints y las tablas de códigos están en la guía de implementación para Visual FoxPro ›

Endpoints principales

Todos cuelgan de /api/afip. Los POST de tablas toman { cuit, produccion }.

Autenticar un CUITPOST /login
Estado del tokenGET /status
Salud API + AFIPGET /health
Último número autorizadoPOST /ultimo
Emitir comprobantePOST /emitir
Consultar un comprobantePOST /consultar
Resumen de emitidosPOST /resumen-emitidos
Cotización de monedaPOST /cotizacion
Tablas (comprobante, doc, IVA…)POST /tipos-*
Para el detalle de cada request/response y la lista completa de tablas, ver la guía VFP (la estructura JSON es la misma para todos los lenguajes) o el Swagger de la API.

Seguir

Guía completa Visual FoxPro › Descargas › Volver al inicio ›