@facta-dte/api — TypeScript SDK
The official TypeScript and JavaScript client for Facta's electronic tax document API. The server remains the fiscal authority. The SDK submits DTE data, handles credentials and retries, resolves encrypted local catalog snapshots, and can archive exact issued bytes for restart-safe recovery.
Install the official client from npm · @facta-dte/api. Source, examples, releases and issues are maintained in GitHub · Facta-DTE/facta-api-sdk. This reference describes version 0.1.1; check the published npm version before using newer methods. The latest tag selects the approved stable release. See the Spanish SDK guide.
Runtime support and installation
The portable entry supports Node.js 22+, Deno, and Bun. @facta-dte/api/node adds Node-only encrypted file archives and config loading. The @facta-dte/api/file-archive entry is also Node-only. Use a source checkout for unreleased capabilities; installing the published package does not make those methods available.
import { Facta, type DteRequest } from "@facta-dte/api";
const facta = new Facta({
apiKey: process.env.FACTA_API_KEY!,
signKey: process.env.FACTA_SIGN_KEY!,
});
const sale: DteRequest = {
tipoDte: "01",
items: [{ descripcion: "Sample item", cantidad: 1, precioUni: 10 }],
};
const result = await facta.issue(sale, { idempotencyKey: "order-1042" });Public SDK identifiers are English. Fiscal payload properties and values such as tipoDte, codigoGeneracion, sellado, and contingencia retain the API's Spanish wire contract.
Public methods
The Facta client provides status and diagnostics: status(), diagnose(), getContract(). Synchronization and catalog methods: syncDestinations(), syncCatalog(), catalogState(), listCustomers(), getCustomer(), searchCustomers(), listProducts(), getProduct(), searchProducts(). DTE operations: issue(), prepare(), sign(), getDocumentStatus(), listDocuments(), invalidate(), listHolding(), downloadDocument(). Durable archive operations: issueAndArchive(), recoverOperation(), listPendingOperations(), invalidateAndArchive(), recoverInvalidation(), listPendingInvalidations(), replicateArchive(), diagnoseDestinations(). Managed storage: getStorageStatus(), getDocumentCopies(), retryDocumentStorage(). Local printing: print().
The English method reference documents each method's arguments, return values, required scope, side effects, errors, and retry/recovery behavior. The Spanish method reference retains the existing Spanish documentation. The API contract is authoritative for HTTP fields and responses.
Safe issuance and recovery
Every operation that can reserve a fiscal control number needs a stable idempotencyKey. Reuse the same key with the same request after a timeout; a changed request with that key is rejected. An AbortSignal stops local waiting and retries but cannot prove the server cancelled an accepted request.
For process-restart recovery, use issueAndArchive with a durable archive, operationId, and idempotencyKey. It journals the request and key before sending. recoverOperation resumes the same operation without rotating its idempotency key. Remote storage copies and printing are explicit adapter operations; a returned print status means a job was submitted, not that a physical page was printed.
Error handling
| FactaErrorCode |
|---|
unauthorized |
invalid_api_key |
key_revoked |
key_expired |
key_inactive |
forbidden_scope |
dte_type_not_allowed |
ip_not_allowed |
environment_not_allowed |
sign_key_required |
sign_key_invalid |
sign_vault_locked |
sign_vault_missing |
invalid_request |
validation_failed |
not_found |
method_not_allowed |
idempotency_key_required |
idempotency_key_reuse |
idempotency_in_flight |
prepare_token_invalid |
rate_limited |
amount_limit |
mh_rejected |
mh_unreachable |
correlative_unavailable |
service_unavailable |
no_storage_destination |
storage_unsupported |
storage_unavailable |
storage_contract_invalid |
internal_error |
operation_outcome_unknown |
archive_integrity_error |
network_error |
Classify FactaError by its stable code, status, details, isRejection, and spent fields. Do not infer fiscal success from a localized message. A contingencia result is accepted for reconciliation and is not a FactaError. Local validation and adapter failures may throw standard or adapter-specific errors.
TypeScript types
Public request and result types use English names, including DteRequest, DteType, Recipient, Address, LineItem, IssueResult, PreparedDte, DocumentStatus, and InvalidationRequest. Their JSON properties intentionally retain the external Facta API field names. The method reference and package declarations list the complete public surface.
Inline archive options
issueAndArchive preserves the exact signed JSON/PDF returned by issuance and does not download them again. Older responses fall back only for missing artifacts. includeTicket:false archives JSON/PDF/JWS without requesting a ticket; do not combine it with an explicit ticketPaperWidthMm. The default remains includeTicket:true. Recovery preserves the original choice.
Managed storage in the next source release
These methods describe source capabilities, not a completed server deployment or a new npm release. Confirm the deployed server contract before using them. The API server writes exact managed JSON/PDF copies; the SDK never receives bucket credentials or a web user session.
| Method | Contract and effect |
|---|---|
getStorageStatus(options?) | ManagedStorageStatus; download scope. capabilityVersion:1, managed coverage/capacity/readiness and verified BYOS readiness. No fiscal work. accessUntil describes read access, not proven backups. |
getDocumentCopies(options?) | ManagedDocumentCopy[]; download scope. Optional generationCode and signal; issuer/environment-scoped JSON/PDF receipts, including pending/failed copies. No document content or storage paths. |
retryDocumentStorage(generationCode, options?) | ManagedStorageReceipt; download scope. Repairs copies of an existing sealed UUID without signing, reissuing or spending a control number. Missing original bytes remain an explicit failure. |
const capability = await facta.getStorageStatus();
const copies = await facta.getDocumentCopies({ generationCode });
if (copies.some(copy => copy.state === "pending" || copy.state === "failed")) {
const receipt = await facta.retryDocumentStorage(generationCode);
// Inspect JSON/PDF states; never create a new fiscal identity to repair files.
}diagnose() uses positive managed readiness to satisfy durable destination checks without a BYOS vault; signing and catalog reference checks remain independent. Malformed present capability blocks issuance. Missing older routes are explicitly unknown. storage_unsupported identifies missing older routes; storage_contract_invalid identifies invalid capabilities/receipts; storage_unavailable identifies unavailable storage service.
Fiscal success and copy success are independent. An invalid attached receipt is omitted and produces storageErrorCode: "storage_contract_invalid" while preserving the sealed result. The encrypted file journal keeps this pending; recovery checks repaired receipt hashes/bytes against exact local files. A stored receipt proves a durable copy, not temporary holding.
The SDK workflow examples in source file examples/workflows.ts are invoked explicitly. issueWithCopies combines managed receipts with a local encrypted archive and optional BYOS outcomes. recoverAfterRestart reuses the saved operation. These require the corresponding source version. Managed invoice storage covers JSON/PDF; ticket regeneration and invalidation event journals use separate contracts. Example and fixture checks do not claim live validation of every fiscal DTE variant.
To verify a managed copy while temporary holding still exists, use downloadDocument(generationCode, "pdf", { source: "managed" }) (also accepts json). It requires storageSource === "managed" without holding fallback. Tickets reject this option before HTTP. Missing source proof on an older server returns storage_unsupported; a contradictory source returns storage_contract_invalid. Default download selection is unchanged.