Skip to content

Certificados ​

Toda llamada a los endpoints de VERI*FACTU de la AEAT se autentica con un certificado de cliente (mTLS). Esta página cubre cómo obtener, formatear y pasar el certificado al SDK.

Qué tipo de certificado se requiere ​

La AEAT acepta:

  • Certificado de representante de persona jurídica — emitido por la FNMT o cualquier prestador de servicios de confianza cualificado listado en la Sede electrónica. Es la opción habitual para proveedores SaaS que actúan como representantes de sus clientes.
  • Certificado de sello electrónico — para sistemas de back-office desatendidos. Encamina a un pool de URLs separado (*10*) que el SDK selecciona automáticamente cuando configuras withSeal: true.
  • Certificado de persona física — para autónomos que emiten sus propias facturas.

El certificado debe:

  • Estar emitido por una CA en la que la AEAT confíe (FNMT, Camerfirma, Firmaprofesional, ANCERT, IZENPE, …).
  • Estar vigente (no caducado, no revocado).
  • Tener las extensiones de uso de clave firma digital y autenticación de cliente.

Cargar desde PKCS#12 (.pfx / .p12) ​

Es el formato más habitual. El SDK acepta el Buffer en bruto y la passphrase:

ts
import { readFileSync } from 'node:fs';
import { VerifactuClient, Environment } from 'verifactu-sdk';

const client = new VerifactuClient({
  environment: Environment.Preproduction,
  mode: 'verifactu',
  certificate: {
    pfx: readFileSync('./cert.pfx'),
    passphrase: process.env.CERT_PASS ?? '',
  },
  /* ... */
});

No subas nunca el .pfx o la passphrase al control de versiones. Inyéctalos mediante variables de entorno, un gestor de secretos (AWS Secrets Manager, HashiCorp Vault, Bitwarden, …) o un volumen montado.

Cargar desde PEM ​

Si mantienes la clave y el certificado en ficheros PEM separados, pásalos como cadenas o Buffers:

ts
import { readFileSync } from 'node:fs';

const certificate = {
  cert: readFileSync('./cert.pem', 'utf8'),
  key: readFileSync('./key.pem', 'utf8'),
  passphrase: process.env.KEY_PASS, // opcional, sólo si la clave está cifrada
};

Los ficheros PEM suelen contener una cadena de intermediarios. El SDK pasará el blob PEM completo a undici — es la maquetación recomendada porque la AEAT valida la cadena completa en el servidor.

Sello electrónico ​

La AEAT enruta los envíos con sello electrónico por un pool de URLs separado (prewww10.aeat.es / www10.agenciatributaria.gob.es). Indica al SDK que lo use con withSeal: true:

ts
const client = new VerifactuClient({
  environment: Environment.Production,
  mode: 'verifactu',
  withSeal: true,
  certificate: { pfx: readFileSync('./seal.pfx'), passphrase: '...' },
  /* ... */
});

Actuar en representación de otro obligado ​

Cuando envías facturas en nombre de un cliente (el caso más habitual en SaaS), configura tanto taxpayer (el cliente) como representative (tú):

ts
const client = new VerifactuClient({
  /* ... */
  taxpayer: { nif: 'B11111111', legalName: 'Customer SL' },
  representative: { nif: 'B99999999', legalName: 'Eloi Baulenas' },
});

El certificado que pases debe estar emitido a nombre del representante — la AEAT cruza el subject del certificado con el bloque <Representante> del sobre.

Certificados de pre-producción ​

La AEAT publica un sandbox en prewww1.aeat.es. No hay un certificado de pruebas gratuito aparte que solicitar — preproducción acepta los mismos tipos de certificado que producción (de representante, de sello o de persona física; ver arriba), apuntando simplemente al pool de URLs de preproducción. Un envío ahí no tiene efecto fiscal, así que es seguro desarrollar contra ella con el certificado real que acabarás usando:

ts
const client = new VerifactuClient({
  environment: Environment.Preproduction, // ← pool de URLs de pre-prod
  /* ... */
});

El endpoint de pre-producción acepta los mismos payloads que producción pero no afecta al censo real. Mantén la suite de pruebas e2e (bun run test:e2e) apuntando allí.

Resolución de problemas ​

SíntomaCausa probable
NetworkError: unable to verify the first certificateFaltan intermediarios en el bundle de CA — pasa la cadena completa en el PEM.
SoapFaultError: 401 UnauthorizedLa AEAT no confía en tu CA, o el certificado está revocado.
SoapFaultError: NIF del certificado…El subject del certificado no coincide con taxpayer.nif / representative.nif.
Error: PFX file truncatedEl .pfx se descargó como texto — vuelve a descargarlo en modo binario.

Consulta la FAQ de la AEAT para la lista completa de diagnósticos: https://sede.agenciatributaria.gob.es/Sede/ayuda/consultas-informaticas.html.

Siguiente ​

Released under the MIT license.