@mexapi/sdk
v0.3.0
Published
Official TypeScript SDK for the mexapi REST API
Readme
@mexapi/sdk
Official TypeScript SDK for the mexapi REST API — the fiscal API for Mexico. Download CFDIs via the SAT's Descarga Masiva, verify invoices, check the Lista Negra 69-B (EFOS), and more, with a fully-typed client.
npm install @mexapi/sdk
# or: pnpm add @mexapi/sdkQuickstart
import { Mexapi } from "@mexapi/sdk";
const client = new Mexapi({ apiKey: process.env.MEXAPI_KEY! });
// baseUrl defaults to https://api.mexapi.com
// List CFDIs (paginated)
const { data, meta } = await client.cfdi.list({ limit: 50 });
console.log(meta.data_status); // "complete" | "incomplete" | "degraded"
// Get one CFDI with flat fields + line items (conceptos)
const { data: cfdi } = await client.cfdi.get("CEE4BE01-ADFA-4DEB-8421-ADD60F0BEDAC");
console.log(cfdi.subTotal, cfdi.totalIvaTrasladado);
for (const c of cfdi.conceptos ?? []) {
console.log(c.descripcion, c.importe, c.ivaTrasladado);
}Use a mx_test_ key to get mock data without a FIEL; mx_live_ returns real data.
Authentication
Pass your API key to the constructor. All requests send
Authorization: Bearer <apiKey>.
const client = new Mexapi({
apiKey: "mx_live_...",
baseUrl: "https://api.mexapi.com", // optional
maxRetries: 2, // optional
timeout: 30_000, // optional (ms)
});Resources
| Resource | Methods |
| --- | --- |
| client.cfdi | list, get, getXml, getStatus, verify |
| client.imports | create, get, list, ensure |
| client.credentials | upload / manage FIEL credentials |
| client.webhooks | manage webhook endpoints |
CFDIs
// Paginated list with filters
const page = await client.cfdi.list({
limit: 100,
cursor: undefined,
rfc: "AAA010101AAA", // either direction
issuerRfc: "AAA010101AAA",
recipientRfc: "BBB020202BB2",
});
// Detail: flat fields + conceptos + raw parsedData
const { data } = await client.cfdi.get(uuid);
// Bulk detail — up to 100 UUIDs in one request (1 credit per CFDI returned).
// Lean by default (no parsedData); pass includeParsedData for the full blob
// (caps the batch at 25). UUIDs not found / not authorized come back in
// `notFound` and cost nothing.
const { data: batch } = await client.cfdi.batch({
uuids: [uuid1, uuid2, uuid3],
});
for (const cfdi of batch.results) console.log(cfdi.uuid, cfdi.amount);
console.log(batch.notFound, batch.creditsCharged);
// Original signed XML (string)
const xml = await client.cfdi.getXml(uuid);
// Real-time SAT status (vigente / cancelado / EFOS) — no FIEL needed
const { data: status } = await client.cfdi.getStatus(uuid);The detail response exposes both normalized fields (subTotal, formaPago,
metodoPago, pre-aggregated tax totals, and a conceptos[] array with per-line
taxes) and the raw parsedData blob (the CFDI 4.0 XML parsed to an object, for
fields not yet promoted to columns: Complementos, full TimbreFiscalDigital, etc.).
Prefer the flat fields + conceptos — they're typed and numeric. See the
CFDI API reference for the
full response shape, the parsedData structure, and gotchas.
Imports (historical / on-demand)
const job = await client.imports.create({
credentialId: "cred_...",
startDate: "2026-01-01",
endDate: "2026-01-31", // max 31 days per job
});
// Idempotent: only creates jobs for missing months/directions
await client.imports.ensure({ credentialId: "cred_...", months: ["2026-01", "2026-02"] });Webhook signature verification
import { verifyWebhookSignature } from "@mexapi/sdk";
const ok = verifyWebhookSignature({
payload: rawBody,
signature: req.headers["x-mexapi-signature"],
secret: process.env.MEXAPI_WEBHOOK_SECRET!,
});Error handling
import { MexapiError, MexapiRateLimitError, MexapiTimeoutError } from "@mexapi/sdk";
try {
await client.cfdi.get(uuid);
} catch (err) {
if (err instanceof MexapiRateLimitError) { /* back off */ }
else if (err instanceof MexapiError) { console.error(err.code, err.message); }
}Documentation
Full docs: https://mexapi.com/docs
License
MIT
