Facta API

TypeScript / JavaScript SDK

Official client

Use the typed Facta client. The client never calculates fiscal amounts or signs documents; the API does that.

Install

Use the local @facta/api package

Methods

Example

// hola-factura — una factura real, sellada por Hacienda, en veinte líneas.
//
// Es la medida del §9 de `docs/plan/tareas/sdks-de-la-api.md`: si no cabe en
// veinte líneas legibles, la API pide demasiado y se corrige la API, no el
// ejemplo. Cuéntalas: de `const facta` al `console.log` hay dieciséis.
//
//   Node:  FACTA_API_KEY=facta_test_… FACTA_SIGN_KEY=factask_… \
//            node --experimental-strip-types sdks/typescript/examples/hola-factura.ts
//   Deno:  FACTA_API_KEY=facta_test_… FACTA_SIGN_KEY=factask_… \
//            deno run --allow-net --allow-env sdks/typescript/examples/hola-factura.ts

import { Facta, FactaError } from "../mod.ts";

// Las dos salen del gestor de secretos del entorno, nunca del repositorio — y
// a ser posible de sitios distintos: el token autentica, y la de firma es lo
// único que abre tu vault de firma. Juntas en el mismo .env se pierde la mitad
// de la defensa. La tercera, FACTA_UNLOCK_KEY, no aparece aquí porque no viaja.
// deno-lint-ignore no-explicit-any
const g = globalThis as any;
const env = (name: string): string => g.Deno?.env.get(name) ?? g.process?.env?.[name];

const facta = new Facta({ apiKey: env("FACTA_API_KEY"), signKey: env("FACTA_SIGN_KEY") });

try {
  const dte = await facta.emitir({
    tipoDte: "03",
    receptor: { customerId: "374114b6-e957-4c7a-8911-dd6381b1e0ea" },
    items: [{ descripcion: "Integración de la API", cantidad: 1, precioUni: 25 }],
  });
  // `totales` solo existe en el sellado: un 202 de contingencia todavía no
  // tiene veredicto. La estrechez del tipo lo obliga, que es lo que se quiere.
  console.log(dte.estado, dte.numeroControl);
  if (dte.estado === "sellado") console.log("sello:", dte.selloRecibido, dte.totales.totalPagar);
} catch (error) {
  if (error instanceof FactaError && error.isRejection) {
    // Hacienda lo leyó y lo negó: el número YA se gastó, y el §167 permite
    // corregir con ese mismo número.
    console.error("rechazado:", error.message, "· número gastado:", error.spent?.numeroControl);
  } else throw error;
}

See the HTTP reference for every operation.