efaturaefatura
Beta

Beta documentation. APIs may change before the stable release.

Adapters

The package exposes optional HTTP adapters through subpath exports. They live in src/presentation and depend on the public Efatura facade.

Do not mount these routes on a public path without authentication. The adapters can build fiscal XML, create ZIP payloads, render DFA PDFs, and submit files through configured transports.

Express

import express from 'express';
import { createEfatura } from '@akira-io/efatura';
import { efaturaRoutes } from '@akira-io/efatura/express';

const app = express();
const efatura = createEfatura(config, dependencies);

const requireEfaturaAccess: express.RequestHandler = (request, response, next) => {
  if (request.header('authorization') !== `Bearer ${process.env.EFATURA_ADAPTER_TOKEN}`) {
    response.sendStatus(401);
    return;
  }

  next();
};

app.use('/efatura', efaturaRoutes(efatura, { authorization: requireEfaturaAccess }));

Fastify

import Fastify from 'fastify';
import { createEfatura } from '@akira-io/efatura';
import { efaturaFastifyPlugin } from '@akira-io/efatura/fastify';

const fastify = Fastify();
const efatura = createEfatura(config, dependencies);

await fastify.register(efaturaFastifyPlugin, {
  efatura,
  authorization: async (request, reply) => {
    if (request.headers.authorization !== `Bearer ${process.env.EFATURA_ADAPTER_TOKEN}`) {
      return reply.code(401).send({ message: 'Unauthorized' });
    }
  },
});

Nest

import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { createEfatura } from '@akira-io/efatura';
import { EfaturaModule } from '@akira-io/efatura/nest';
import { EfaturaAdapterGuard } from './efatura-adapter.guard';

@Module({
  imports: [EfaturaModule.forRoot({ efatura: createEfatura(config, dependencies) })],
  providers: [{ provide: APP_GUARD, useClass: EfaturaAdapterGuard }],
})
export class AppModule {}

For Nest, use the standard guard system in the application that imports EfaturaModule. A route-specific guard or an APP_GUARD provider must reject unauthenticated requests before they reach the adapter controller.

Storage

Adapters do not own fiscal numbering. Configure the SequenceStore dependency on the shared Efatura instance before mounting any HTTP adapter.

See Storage for InMemorySequenceStore, FileSequenceStore, KnexSequenceStore, PrismaSequenceStore, the Prisma model copy command, and counter migration notes.

Routes

Adapters expose the same route set:

MethodPathPurpose
POST/dfe/xmlBuild DFE XML from invoice data and options
POST/event/xmlBuild official Event XML for FDC or UDN events
POST/dfe/zipBuild a ZIP payload from { iud, xml } files
POST/dfe/submit/middlewareSubmit a ZIP payload through the configured middleware transport
POST/dfe/validate/fiscal-readinessValidate local invoice rules plus optional PE and DNRE readiness checks
POST/dfaRender a DFA PDF from an IUD and optional invoice data
GET/dfa/:iudRender a DFA PDF for an IUD

Request payloads are validated with the shared Zod schemas documented in Validation And Zod.

Fiscal readiness accepts { invoice, options }. Without options.accessToken, external PE and DNRE checks return skipped; with a token, the configured fiscal authority clients validate taxpayers, registered software, and emitter authorization.

POST /dfa accepts { iud, invoice?, options? }. When invoice is present, the adapter validates it before rendering and includes the fiscal header, parties, line summary, taxes, totals, QR Code, and contingency notice in the PDF. options supports emissionMode, contingencyIuc, and title. The deprecated currency option remains accepted until v1.0.0; supplying it emits EFATURA_RENDER_DFA_CURRENCY_DEPRECATED once per process. Use prepareInvoiceToCve() and render the prepared invoice instead. GET /dfa/:iud remains available for IUD-only rendering.