Toda llamada lleva un header X-Api-Key
factura.com.do no usa Bearer ni OAuth para integraciones máquina-a-máquina. Una llave de aplicación viaja en el header X-Api-Key y se valida en cada request.
El header X-Api-Key
| Campo | Valor |
|---|---|
| Nombre | X-Api-Key |
| Ubicación | Header HTTP en cada request |
| Formato | Cadena base64 url-safe (~43 caracteres, sin prefijo legible) |
| Generación | Configuración → Acceso API → «Agregar», en la app |
| Plan | Solo el plan Corporativo; en otros planes la llave recibe 403 |
| Validación | El servidor exige IsActive == true y ValidUntil >= ahora |
Cómo obtener tu llave
La llave se emite desde la app: en Configuración → Acceso API, pulsa «Agregar» y, en «Crear nueva llave API», escribe el nombre de la aplicación (por ejemplo, ERP — producción) y la fecha de expiración. La llave queda en la tabla de credenciales, con un botón «Copiar»; guárdala en tu gestor de secretos. La sección solo está disponible en el plan Corporativo.
No existe un endpoint público de auto-emisión. Si necesitas rotar una llave en automático, conversa con el equipo para coordinar el flujo.
Tu primera llamada autenticada
El siguiente snippet lista clientes del espacio de trabajo usando la llave inyectada como variable de entorno.
GET /api/v1/customers
curl https://tuempresa.factura.com.do/api/v1/customers \ -H "X-Api-Key: $FACTURA_API_KEY"// list-customers.tsconst res = await fetch( "https://tuempresa.factura.com.do/api/v1/customers", { headers: { "X-Api-Key": process.env.FACTURA_API_KEY! } },);const { items, totalCount } = await res.json();# list_customers.pyimport osimport httpx
with httpx.Client(headers={"X-Api-Key": os.environ["FACTURA_API_KEY"]}) as c: r = c.get("https://tuempresa.factura.com.do/api/v1/customers") r.raise_for_status() print(r.json())<?php// list_customers.php$ch = curl_init("https://tuempresa.factura.com.do/api/v1/customers");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["X-Api-Key: " . getenv("FACTURA_API_KEY")],]);$response = curl_exec($ch);curl_close($ch);echo $response;Cómo se ve un 401
Si la llave no llega o no es válida, el servidor responde con un 401 Unauthorized sin cuerpo. El filtro ApiKeyFilter retorna Results.Unauthorized() y ASP.NET cierra la respuesta con Content-Length: 0; tu cliente debe diferenciar el caso por el código HTTP, no por el cuerpo.
HTTP/1.1 401 UnauthorizedContent-Length: 0Plan Corporativo: el 403
El acceso a la API REST es exclusivo del plan Corporativo. Si la llave es válida pero el espacio de trabajo tiene otro plan (o bajó de plan después de emitirla), las rutas de comprobantes, notas, gastos, clientes, proveedores, certificación y firma responden 403 Forbidden con este cuerpo. Las rutas de catálogo (productos, impuestos, monedas, RNC y consultas *-lookup) hoy validan solo la llave; no construyas tu integración sobre esa diferencia.
HTTP/1.1 403 ForbiddenContent-Type: application/json
{ "error": "El acceso a la API REST está disponible solo en el plan Corporativo." }