⚡ API REST — v1.0

Documentación API VeriFactu

Todo lo que necesitas para integrar la firma VeriFactu en tu software, ERP o plataforma. Un endpoint, resultado instantáneo.

Contenido

  1. Inicio rápido
  2. Autenticación
  3. Endpoint: Firmar factura
  4. Parámetros de entrada
  5. Respuesta
  6. Códigos de error
  7. Ejemplos por lenguaje
  8. Encadenamiento de hashes
  9. Límites y planes
  10. Preguntas frecuentes

🚀 Inicio rápido

Puedes firmar tu primera factura con VeriFactu en menos de 2 minutos. Solo necesitas una API key y una llamada HTTP.

Paso 1: Obtén tu API key

Regístrate en la página de planes para obtener tu clave. El trial de 14 días es gratuito y no requiere tarjeta.

Paso 2: Envía tu primera factura

curl
curl -X POST https://declarapp.com/api/v1/sign.php \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nif": "B12345678",
    "nombre": "Mi Empresa SL",
    "numero": "F-2026-001",
    "fecha": "2026-04-01",
    "base_imponible": 1500.00,
    "tipo_iva": 21,
    "cliente": "Cliente SA",
    "concepto": "Servicios de consultoría"
  }'

Paso 3: Recibe el resultado

La API devuelve en menos de 200ms el hash SHA-256, el código QR verificable en la AEAT, y el XML oficial.

Producción real. Nuestra API conecta directamente con el entorno de producción de la AEAT (www2.agenciatributaria.gob.es). Los hashes generados cumplen con el RD 1007/2023.

🔒 Autenticación

Todas las peticiones requieren una API key enviada en la cabecera Authorization con el esquema Bearer:

Header HTTP
Authorization: Bearer vf_a1b2c3d4e5f6...
⚠️
Mantén tu clave segura. No la incluyas en código frontend, repositorios públicos ni URLs. Usa variables de entorno en tu servidor.

Tu API key se genera al suscribirte a un plan. Si la pierdes o se compromete, puedes revocarla y generar una nueva desde el panel de control.

📡 Endpoint: Firmar factura

Un único endpoint que recibe los datos de la factura y devuelve la firma VeriFactu completa.

POST https://declarapp.com/api/v1/sign.php

Content-Type: application/json

CORS: Habilitado (Access-Control-Allow-Origin: *). Soporta preflight OPTIONS.

📋 Parámetros de entrada

Envía un objeto JSON en el body de la petición con los datos de la factura:

CampoTipoObligatorioDescripción
nifstringNIF o CIF del emisor. Se convierte a mayúsculas automáticamente. Ej: B12345678
nombrestringNoNombre o razón social del emisor. Default: "Emisor"
numerostringNúmero de factura. Ej: F-2026-001
fechastringFecha de la factura en formato YYYY-MM-DD
base_imponiblenumberBase imponible en euros. Debe ser mayor que 0
tipo_ivanumberNoPorcentaje de IVA. Default: 21. Valores habituales: 21, 10, 4, 0
clientestringNoNombre del cliente o destinatario
cliente_nifstringNoNIF del cliente (para facturas B2B)
conceptostringNoDescripción del servicio o producto. Default: "Prestacion de servicios"
prev_hashstringNoHash de la factura anterior para encadenamiento. Ver encadenamiento
💡
La cuota de IVA y el total se calculan automáticamente. Solo necesitas enviar base_imponible y tipo_iva.

Respuesta

Cuando la firma es exitosa, la API devuelve un JSON con código 200:

Respuesta 200 OK
{
  "ok": true,
  "hash": "a3f9c7e2b1d4...64 caracteres hex",
  "prev_hash": "",
  "timestamp": "2026-04-01T10:30:45+02:00",
  "verify_url": "https://www2.agenciatributaria.gob.es/...",
  "qr_png": "data:image/png;base64,iVBOR...",
  "qr_svg": "<svg...>",
  "xml": "<soapenv:Envelope...>",
  "invoice": "F-2026-001",
  "test_mode": false,
  "usage": {
    "calls_today": 15,
    "limit": 500
  }
}
CampoTipoDescripción
okbooleantrue si la firma fue exitosa
hashstringHash SHA-256 de 64 caracteres hexadecimales. Este es el identificador único VeriFactu de la factura
prev_hashstringHash de la factura anterior en la cadena (vacío si es la primera)
timestampstringFecha y hora de la firma en formato ISO 8601 con zona horaria
verify_urlstringURL de la AEAT donde se puede verificar la factura escaneando el QR
qr_pngstringCódigo QR en formato PNG codificado en base64. Listo para usar en un <img src="...">
qr_svgstringCódigo QR en formato SVG vectorial
xmlstringXML VeriFactu completo en formato SuministroLR compatible con la AEAT
invoicestringNúmero de factura procesado
test_modebooleanfalse en producción, true en sandbox
usageobjectContador de llamadas del día y límite de tu plan

🚨 Códigos de error

Cuando algo falla, la API devuelve un JSON con ok: false y un mensaje descriptivo:

Respuesta de error
{
  "ok": false,
  "error": "Descripción del error",
  "code": 401
}
200Factura firmada correctamente
204Preflight CORS (OPTIONS) — sin contenido
400JSON inválido en el body de la petición
401Falta la cabecera Authorization o el formato es incorrecto
403API key inválida, revocada o desactivada
405Método HTTP no permitido. Solo se acepta POST
422Faltan campos obligatorios: nif, numero, fecha, base_imponible (>0)
429Límite de llamadas diarias alcanzado. Incluye limit y used en el body
500Error interno del servidor. Contacta con soporte si persiste

💻 Ejemplos por lenguaje

Copia y pega el ejemplo en tu lenguaje preferido. Sustituye TU_API_KEY por tu clave real.

Python 3
import requests

response = requests.post(
  "https://declarapp.com/api/v1/sign.php",
  headers={
    "Authorization": "Bearer TU_API_KEY",
    "Content-Type": "application/json"
  },
  json={
    "nif": "B12345678",
    "nombre": "Mi Empresa SL",
    "numero": "F-2026-001",
    "fecha": "2026-04-01",
    "base_imponible": 1500.00,
    "tipo_iva": 21,
    "cliente": "Cliente SA",
    "concepto": "Servicios de consultoria"
  }
)

data = response.json()
if data["ok"]:
  print(f"Hash: {data['hash']}")
  print(f"QR: {data['verify_url']}")
  # Guarda data["qr_png"] como imagen
  # Guarda data["xml"] para tus registros
else:
  print(f"Error: {data['error']}")
PHP 8+
<?php
$ch = curl_init('https://declarapp.com/api/v1/sign.php');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer TU_API_KEY',
    'Content-Type: application/json'
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'nif' => 'B12345678',
    'nombre' => 'Mi Empresa SL',
    'numero' => 'F-2026-001',
    'fecha' => '2026-04-01',
    'base_imponible' => 1500.00,
    'tipo_iva' => 21,
    'cliente' => 'Cliente SA',
    'concepto' => 'Servicios de consultoria'
  ])
]);

$data = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($data['ok']) {
  echo "Hash: " . $data['hash'];
  // $data['qr_png'] = imagen base64
  // $data['xml'] = XML para AEAT
} else {
  echo "Error: " . $data['error'];
}
Node.js (fetch)
const response = await fetch('https://declarapp.com/api/v1/sign.php', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer TU_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    nif: 'B12345678',
    nombre: 'Mi Empresa SL',
    numero: 'F-2026-001',
    fecha: '2026-04-01',
    base_imponible: 1500.00,
    tipo_iva: 21,
    cliente: 'Cliente SA',
    concepto: 'Servicios de consultoria'
  })
});

const data = await response.json();
if (data.ok) {
  console.log(`Hash: ${data.hash}`);
  // data.qr_png = imagen base64
  // data.xml = XML VeriFactu
} else {
  console.error(`Error: ${data.error}`);
}
C# (.NET 6+)
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer TU_API_KEY");

var body = new StringContent(
  JsonSerializer.Serialize(new {
    nif = "B12345678",
    nombre = "Mi Empresa SL",
    numero = "F-2026-001",
    fecha = "2026-04-01",
    base_imponible = 1500.00,
    tipo_iva = 21,
    cliente = "Cliente SA",
    concepto = "Servicios de consultoria"
  }),
  Encoding.UTF8, "application/json"
);

var resp = await client.PostAsync(
  "https://declarapp.com/api/v1/sign.php", body
);
var json = await resp.Content.ReadAsStringAsync();
// Deserializar y procesar el resultado

🔗 Encadenamiento de hashes

El sistema VeriFactu exige que cada factura incluya el hash de la factura anterior, formando una cadena criptográfica imposible de manipular. Esto garantiza la integridad de toda tu secuencia de facturación.

¿Cómo funciona?

Cuando firmas tu primera factura, el campo prev_hash está vacío. A partir de la segunda, debes enviar el hash de la factura anterior:

Flujo de encadenamiento
// Factura 1 (primera de la cadena)
{"numero":"F-001", ...} → hash: "a1b2c3..."

// Factura 2 (incluye hash anterior)
{"numero":"F-002", "prev_hash":"a1b2c3...", ...} → hash: "d4e5f6..."

// Factura 3
{"numero":"F-003", "prev_hash":"d4e5f6...", ...} → hash: "g7h8i9..."
💡
Consejo: Guarda el hash de cada respuesta en tu base de datos junto con la factura. Al crear la siguiente factura, recupera el último hash y envíalo como prev_hash.

Si no envías prev_hash, la API firma la factura igualmente pero sin encadenar. Para cumplimiento legal completo con la AEAT, se recomienda siempre encadenar.

📊 Límites y planes

Cada API key tiene un límite de llamadas diarias según tu plan. El contador se reinicia a las 00:00 UTC cada día.

PlanPrecioLlamadas/díaSoporteSLA
Básico19,99 €/mes500Email
Pro49,99 €/mes2.000Prioritario99,9%
Empresa99,99 €/mesIlimitadoTelefónico99,9%

Todos los planes incluyen 14 días de prueba gratuita sin tarjeta de crédito. Empieza tu prueba ahora →

⚠️
Cuando alcanzas el límite diario, la API devuelve 429 con los campos limit y used. Cada respuesta exitosa incluye el objeto usage para que puedas monitorizar tu consumo en tiempo real.

Preguntas frecuentes

¿Es obligatorio VeriFactu?

Sí. Según el RD 1007/2023, las empresas deben cumplir desde el 1 de enero de 2027 y los autónomos desde el 1 de julio de 2027 (fechas aplazadas por RD-ley 15/2025).

¿Es producción real o sandbox?

Producción real. Nuestra API conecta directamente con el entorno de producción de la AEAT (www2.agenciatributaria.gob.es), que está abierto desde abril de 2025.

¿Puedo usar la API desde un frontend (JavaScript)?

Técnicamente sí (CORS está habilitado), pero no lo recomendamos porque expondrías tu API key. Usa la API desde tu servidor backend.

¿Qué pasa si mi cadena de hashes se rompe?

Puedes empezar una nueva cadena enviando una factura sin prev_hash. No obstante, para cumplimiento legal completo, lo ideal es mantener la cadena continua.

¿Soporta facturas rectificativas?

Actualmente la API firma facturas ordinarias. Las facturas rectificativas y anulaciones estarán disponibles en la versión 1.1.

¿Hay SDK oficial?

Todavía no, pero la API es un único endpoint REST estándar que funciona con cualquier cliente HTTP. Los ejemplos de esta documentación son copy-paste y funcionan directamente.

¿Cómo contacto con soporte?

Escríbenos en el formulario de contacto o envía un email a gestion@securecore.es. Los planes Pro y Empresa tienen soporte prioritario.

🚀

Empieza a firmar facturas ahora

14 días gratis, sin tarjeta. Tu primera firma en menos de 2 minutos.

Empezar gratis → Ver planes