Guía para Desarrolladores

API FacturaE y VeriFactupara FileMaker, Access, PHP y más

Genera y firma facturas electrónicas conformes a FacturaE y VeriFactu desde cualquier sistema — FileMaker Pro, Microsoft Access, PHP, cURL — con una sola petición HTTP. Sin instalar librerías. Sin Java. Sin certificados locales.

🚀 Quick Start — en 3 pasos

  1. 1

    Obtén tu API Key

    En el DashboardAPI Keys → Nueva API Key. Se muestra una sola vez.

  2. 2

    Sube tu certificado P12 (opcional, solo si quieres firma)

    Dashboard → Mis Empresas → Subir P12. Lo almacenamos cifrado; la contraseña nunca se guarda.

  3. 3

    Haz tu primera petición

    Copia el ejemplo de abajo, reemplaza tu API Key y envía el JSON. Recibirás el XML FacturaE en la respuesta.

POSThttps://api.datapilotax.es/api/v1/facturae/json
Autenticado · Devuelve XML

Content-Type

application/json

X-API-KEY

txp_live_<tu_clave>

X-Certificate-Password

PIN_P12 (opcional)

Campos requeridos del JSON (*)

series, number, issueDate (YYYY-MM-DD)issuer → taxIdNumber, legalName, address completareceiver → taxIdNumber, legalName, address completalines[] → description, quantity, unitPrice, totalAmount, taxRatetotals → totalGrossAmount, totalTaxAmount, totalPayableAmount⚠ Usar taxIdNumber (NO taxId.number) · Usar lines (NO items)

🛡️ Seguridad e Infraestructura

🏢

Datos en España

Servidores en Oracle Cloud Infrastructure — Región Madrid (eu-madrid-1). Tus datos nunca salen del territorio nacional.

🔐

Certificados cifrados en reposo

Los certificados P12 se almacenan cifrados (AES-256). La contraseña del certificado jamás se persiste — se usa solo en memoria durante la petición.

🔒

Comunicación TLS 1.3

Todas las peticiones van cifradas con TLS 1.3. Las API Keys viajan en cabecera HTTP (nunca en URL). Tokens JWT con expiración y rotación.

🇪🇺

RGPD / LOPD compliant

Tratamiento de datos conforme al Reglamento General de Protección de Datos europeo y la LOPDGDD española. Datos fiscales retenidos según Ley General Tributaria.

📋

Normativa española

XML generado conforme a FacturaE 3.2.1 y VeriFactu (RD 1007/2023). Firma XADES-EPES con el certificado delegado del emisor.

🚫

Sin instalaciones

Cero dependencias en tu sistema. No necesitas Java, librerías de firma, certificados locales ni acceso al FNMT. Solo HTTP.

👋 ¿Por qué usar Data Pilot Tax?

Si programas en FileMaker Pro, Microsoft Access, Visual Basic o PHP, implementar la firma criptográfica XADES-EPES de un XML FacturaE son cientos de horas de trabajo especializado que tu sistema legacy no está diseñado para asumir.

Data Pilot Tax resuelve esto en 1 petición HTTP: envías el JSON con los datos de la factura, la API valida el formato, genera el XML FacturaE, lo firma con tu certificado delegado almacenado, lo guarda y te lo devuelve. Tu sistema legacy solo necesita saber hacer una llamada HTTP POST.

1 Autenticación con API Key

Añade la cabecera X-API-KEY a todas tus peticiones. La generas en Dashboard → API Keys → Nueva API Key. Se muestra una única vez — guárdala inmediatamente.

Cabecera obligatoria en todas las peticiones
X-API-KEY: txp_live_xxxxxxxxxxxxxxxxxxxxxx

2 Endpoint: JSON → XML FacturaE firmado

Envía el JSON con los datos de la factura. La API valida, convierte a XML FacturaE, firma con tu certificado (si incluyes el PIN) y devuelve el XML en el cuerpo de la respuesta. Si el PIN no se incluye, devuelve el XML sin firma.

POSThttps://api.datapilotax.es/api/v1/facturae/json

Cabeceras

  • // Obligatorias
  • Content-Type: application/json
  • X-API-KEY: <tu_api_key>
  • // Opcional — solo si quieres firma electrónica
  • X-Certificate-Password: <pin_de_tu_p12>

El PIN viaja cifrado por TLS 1.3, se usa en RAM solo durante el descifrado del certificado y nunca se persiste en ningún sistema de Data Pilot Tax.

JSON Payload completo y correcto

{
  "series":    "F2025",
  "number":    "0001",
  "issueDate": "2025-06-15",
  "currency":  "EUR",
  "version":   "3.2.1",

  "issuer": {
    "taxIdNumber":      "B12345678",
    "taxIdCountryCode": "ESP",
    "legalName":        "Mi Empresa SL",
    "address": {
      "address":     "Calle Gran Vía 1",
      "postCode":    "28013",
      "town":        "Madrid",
      "province":    "Madrid",
      "countryCode": "ESP"
    }
  },

  "receiver": {
    "taxIdNumber":      "A98765432",
    "taxIdCountryCode": "ESP",
    "legalName":        "Cliente Ejemplo SA",
    "address": {
      "address":     "Avenida Diagonal 100",
      "postCode":    "08019",
      "town":        "Barcelona",
      "province":    "Barcelona",
      "countryCode": "ESP"
    }
  },

  "lines": [
    {
      "description":            "Desarrollo módulo ERP — integración FacturaE",
      "quantity":               1,
      "unitPriceWithoutTax":    1500.00,
      "totalAmountWithoutTax":  1500.00,
      "taxRate":                21.0
    }
  ],

  "totals": {
    "totalGrossAmount":   1500.00,
    "totalTaxAmount":      315.00,
    "totalPayableAmount": 1815.00
  }
}

Snippets por plataforma

Código listo para copiar y pegar. Pensado para desarrolladores que ya conocen su entorno — el script de FileMaker se parece a FileMaker, el VBA se parece a Access, el PHP se parece a PHP.

cURL — Terminal / Bash

macOS · Linux · Git Bash (Windows)

La forma más directa de probar la API. Ideal para scripts de automatización en servidores Linux, CI/CD pipelines o verificar que tu JSON es correcto antes de integrarlo en tu ERP. La opción -o factura.xml guarda el resultado directamente en disco.

bash
# ──────────────────────────────────────────────────────────────
#  Data Pilot Tax — Generar factura FacturaE / VeriFactu
#  Requisitos: curl 7.x+  |  Compatible macOS, Linux, Git Bash
# ──────────────────────────────────────────────────────────────

curl -X POST "https://api.datapilotax.es/api/v1/facturae/json" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: txp_live_TU_CLAVE_AQUI" \
  -H "X-Certificate-Password: PIN_DE_TU_P12" \
  -o factura_firmada.xml \
  -d '{
    "series":    "F2025",
    "number":    "0001",
    "issueDate": "2025-06-15",
    "currency":  "EUR",
    "issuer": {
      "taxIdNumber":      "B12345678",
      "taxIdCountryCode": "ESP",
      "legalName":        "Mi Empresa SL",
      "address": {
        "address": "Calle Gran Vía 1", "postCode": "28013",
        "town": "Madrid", "province": "Madrid", "countryCode": "ESP"
      }
    },
    "receiver": {
      "taxIdNumber":      "A98765432",
      "taxIdCountryCode": "ESP",
      "legalName":        "Cliente SA",
      "address": {
        "address": "Diagonal 100", "postCode": "08019",
        "town": "Barcelona", "province": "Barcelona", "countryCode": "ESP"
      }
    },
    "lines": [{
      "description": "Servicio de consultoría",
      "quantity": 1,
      "unitPriceWithoutTax": 1500.00,
      "totalAmountWithoutTax": 1500.00,
      "taxRate": 21.0
    }],
    "totals": {
      "totalGrossAmount": 1500.00,
      "totalTaxAmount": 315.00,
      "totalPayableAmount": 1815.00
    }
  }'

# Respuesta 200 → el fichero factura_firmada.xml contiene el XML FacturaE listo
# Respuesta 4xx → revisar el JSON (campos requeridos marcados con * en Swagger)

📦 FileMaker Pro — VeriFactu y FacturaE

FileMaker Pro 19+ · FileMaker Server

Usa el paso de guion «Insertar desde URL» con las funciones JSON nativas de FileMaker (JSONSetElement). El script siguiente está estructurado como si lo vieras en el Espacio de trabajo de guiones de FileMaker — incluye los pasos, variables y la lógica condicional tal como los escribirías. Adapta los nombres de campo a tu solución.

Insertar desde URLJSONSetElementEstablecer VariablePatternCount✓ FacturaE 3.2.1✓ VeriFactu
FileMaker Script Workspace
╔══════════════════════════════════════════════════════════════════╗
║  Script FileMaker Pro: "Generar Factura FacturaE"               ║
║  Usando: Insertar desde URL  +  Funciones JSON nativas           ║
║  Probado en FileMaker Pro 19+ / FileMaker Server 19+             ║
╚══════════════════════════════════════════════════════════════════╝

# ── 1. Configuración (guardar en tabla "Config", no hardcodeada) ──
Establecer Variable [$url    ; "https://api.datapilotax.es/api/v1/facturae/json"]
Establecer Variable [$apikey ; Config::api_key]
Establecer Variable [$pin    ; Config::pin_certificado_p12]

# ── 2. Construir el JSON con funciones nativas de FileMaker ───────
Establecer Variable [$json ;
  JSONSetElement ( "{}" ;
    ["series"   ; Facturas::serie        ; JSONString] ;
    ["number"   ; Facturas::numero       ; JSONString] ;
    ["issueDate"; Text(Facturas::fecha;"YYYY-MM-DD") ; JSONString] ;
    ["currency" ; "EUR"                  ; JSONString] ;

    ["issuer.taxIdNumber"      ; Empresas::nif          ; JSONString] ;
    ["issuer.taxIdCountryCode" ; "ESP"                  ; JSONString] ;
    ["issuer.legalName"        ; Empresas::razon_social ; JSONString] ;
    ["issuer.address.address"  ; Empresas::direccion    ; JSONString] ;
    ["issuer.address.postCode" ; Empresas::cp           ; JSONString] ;
    ["issuer.address.town"     ; Empresas::ciudad       ; JSONString] ;
    ["issuer.address.province" ; Empresas::provincia    ; JSONString] ;
    ["issuer.address.countryCode"; "ESP"                ; JSONString] ;

    ["receiver.taxIdNumber"      ; Clientes::nif          ; JSONString] ;
    ["receiver.taxIdCountryCode" ; "ESP"                  ; JSONString] ;
    ["receiver.legalName"        ; Clientes::razon_social ; JSONString] ;
    ["receiver.address.address"  ; Clientes::direccion    ; JSONString] ;
    ["receiver.address.postCode" ; Clientes::cp           ; JSONString] ;
    ["receiver.address.town"     ; Clientes::ciudad       ; JSONString] ;
    ["receiver.address.province" ; Clientes::provincia    ; JSONString] ;
    ["receiver.address.countryCode"; "ESP"               ; JSONString] ;

    ["lines[0].description"           ; Lineas::concepto       ; JSONString] ;
    ["lines[0].quantity"              ; Lineas::cantidad        ; JSONNumber] ;
    ["lines[0].unitPriceWithoutTax"   ; Lineas::precio_unit     ; JSONNumber] ;
    ["lines[0].totalAmountWithoutTax" ; Lineas::base_imponible  ; JSONNumber] ;
    ["lines[0].taxRate"               ; Lineas::tipo_iva        ; JSONNumber] ;

    ["totals.totalGrossAmount"   ; Facturas::base_total   ; JSONNumber] ;
    ["totals.totalTaxAmount"     ; Facturas::cuota_iva    ; JSONNumber] ;
    ["totals.totalPayableAmount" ; Facturas::total_factura; JSONNumber]
  )
]

# ── 3. Llamada HTTP (Insertar desde URL) ──────────────────────────
Insertar desde URL [Seleccionar; Con diálogo: Desactivado;
  Destino: Facturas::xml_resultado;
  URL: $url;
  Verificar certificados SSL: Activado;
  Opciones cURL:
    "-X POST" &
    " --header "Content-Type: application/json"" &
    " --header "X-API-KEY: " & $apikey & """ &
    " --header "X-Certificate-Password: " & $pin & """ &
    " --data @$json"
]

# ── 4. Evaluar la respuesta ───────────────────────────────────────
Si [PatternCount(Facturas::xml_resultado ; "<Facturae") > 0]
  Establecer campo [Facturas::estado ; "FIRMADA"]
  Establecer campo [Facturas::fecha_firma ; Get(FechaActual)]
  Mostrar diálogo personalizado ["✅ Factura XML generada y almacenada correctamente."]
Si no
  Establecer campo [Facturas::estado ; "ERROR"]
  Establecer campo [Facturas::error_msg ; Facturas::xml_resultado]
  Mostrar diálogo personalizado ["❌ Error: " & Facturas::xml_resultado]
Fin Si

Para múltiples líneas de factura, genera el array JSON con un bucle Ir a registro / solicitud / página [Siguiente] y concatena cada elemento antes de la llamada HTTP.

📊 Microsoft Access — VBA y VeriFactu

Access 2016+ · VBA · MSXML2

Módulo VBA estándar para Microsoft Access. Usa MSXML2.ServerXMLHTTP.6.0 (disponible en Windows desde Office 2007). El código es un módulo real listo para pegar en Herramientas → Editor de Visual Basic → Módulo. Requiere activar en Herramientas → Referencias: Microsoft XML, v6.0.

MSXML2.ServerXMLHTTP.6.0TLS 1.2+DLookup Config✓ FacturaE 3.2.1✓ VeriFactu
VBA — modFacturaE.bas
'================================================================
'  Módulo: modFacturaE
'  Data Pilot Tax — Integración FacturaE / VeriFactu desde Access
'  Referencia COM requerida: Microsoft XML, v6.0  (MSXML2)
'  Herramientas > Referencias > marcar "Microsoft XML, v6.0"
'================================================================
Option Explicit

Public Sub GenerarFacturaFacturaE()

    '-- Configuración (mejor leerlo de tabla tConfig)
    Const API_URL   As String = "https://api.datapilotax.es/api/v1/facturae/json"
    Dim sApiKey     As String: sApiKey = DLookup("valor", "tConfig", "clave='API_KEY'")
    Dim sPinP12     As String: sPinP12 = InputBox("PIN del certificado P12:", "Firma Segura")
    If sPinP12 = "" Then Exit Sub   ' usuario canceló

    '-- Construir JSON (Access no tiene JSON nativo; usamos concatenación)
    Dim sSerie      As String: sSerie   = Forms!fFacturas!serie
    Dim sNumero     As String: sNumero  = Forms!fFacturas!numero
    Dim sFecha      As String: sFecha   = Format(Forms!fFacturas!fecha, "YYYY-MM-DD")

    Dim sJson As String
    sJson = "{" & _
        """series"":""" & sSerie & """," & _
        """number"":""" & sNumero & """," & _
        """issueDate"":""" & sFecha & """," & _
        """currency"":""EUR""," & _
        """issuer"":{" & _
            """taxIdNumber"":""" & Forms!fFacturas!nif_emisor & """," & _
            """taxIdCountryCode"":""ESP""," & _
            """legalName"":""" & Forms!fFacturas!razon_emisor & """," & _
            """address"":{" & _
                """address"":""" & Forms!fFacturas!dir_emisor & """," & _
                """postCode"":""" & Forms!fFacturas!cp_emisor & """," & _
                """town"":""" & Forms!fFacturas!ciudad_emisor & """," & _
                """province"":""" & Forms!fFacturas!prov_emisor & """," & _
                """countryCode"":""ESP""}}," & _
        """receiver"":{" & _
            """taxIdNumber"":""" & Forms!fFacturas!nif_receptor & """," & _
            """taxIdCountryCode"":""ESP""," & _
            """legalName"":""" & Forms!fFacturas!razon_receptor & """," & _
            """address"":{" & _
                """address"":""" & Forms!fFacturas!dir_receptor & """," & _
                """postCode"":""" & Forms!fFacturas!cp_receptor & """," & _
                """town"":""" & Forms!fFacturas!ciudad_receptor & """," & _
                """province"":""" & Forms!fFacturas!prov_receptor & """," & _
                """countryCode"":""ESP""}}," & _
        """lines"":[{" & _
            """description"":""" & Forms!fFacturas!concepto & """," & _
            """quantity"":" & Forms!fFacturas!cantidad & "," & _
            """unitPriceWithoutTax"":" & Forms!fFacturas!precio_unit & "," & _
            """totalAmountWithoutTax"":" & Forms!fFacturas!base_imp & "," & _
            """taxRate"":" & Forms!fFacturas!iva & "}]," & _
        """totals"":{" & _
            """totalGrossAmount"":" & Forms!fFacturas!base_total & "," & _
            """totalTaxAmount"":" & Forms!fFacturas!cuota_iva & "," & _
            """totalPayableAmount"":" & Forms!fFacturas!total_factura & "}" & _
    "}"

    '-- Petición HTTP con MSXML2 (soporta TLS 1.2+)
    Dim http As Object
    Set http = CreateObject("MSXML2.ServerXMLHTTP.6.0")

    On Error GoTo ErrHandler
    http.Open "POST", API_URL, False
    http.setRequestHeader "Content-Type", "application/json"
    http.setRequestHeader "X-API-KEY", sApiKey
    http.setRequestHeader "X-Certificate-Password", sPinP12
    http.send sJson

    '-- Evaluar respuesta
    If http.Status = 200 Then
        Dim sXml As String
        sXml = http.responseText

        '-- Guardar XML en disco
        Dim iFile As Integer: iFile = FreeFile
        Dim sRuta As String
        sRuta = CurrentProject.Path & "acturas" & sSerie & "-" & sNumero & ".xml"
        Open sRuta For Output As #iFile
            Print #iFile, sXml
        Close #iFile

        '-- Actualizar tabla
        CurrentDb.Execute "UPDATE tFacturas SET estado='FIRMADA', ruta_xml='" & _
            sRuta & "' WHERE serie='" & sSerie & "' AND numero='" & sNumero & "'"

        MsgBox "✅ Factura generada: " & sRuta, vbInformation
    Else
        MsgBox "❌ Error " & http.Status & ": " & http.responseText, vbCritical
    End If

    Set http = Nothing
    Exit Sub

ErrHandler:
    MsgBox "Error de conexión: " & Err.Description, vbCritical
    Set http = Nothing
End Sub

Si obtienes error de TLS en Windows antiguo, ejecuta en PowerShell: Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Name 'Enabled' -Value 1

🐘 PHP — WordPress, WooCommerce, Laravel

PHP 7.4+ · ext-curl

Script PHP puro con curl (disponible en prácticamente todos los hostings). Funciona en WordPress / WooCommerce (como plugin o función en functions.php), Laravel, Symfony, CodeIgniter o PHP plano. Las credenciales se leen de variables de entorno para no quedar hardcodeadas en el código.

ext-curlgetenv()json_encode()WordPress compatible✓ FacturaE 3.2.1✓ VeriFactu
datapilot-tax.php
<?php
/**
 * Data Pilot Tax — Generar factura FacturaE / VeriFactu
 * Compatibilidad: PHP 7.4+  |  WordPress, WooCommerce, Laravel, puro
 * Extensión requerida: ext-curl (activa en casi todos los hostings)
 */

// ── Configuración ─────────────────────────────────────────────────────────────
define('DPT_API_URL',  'https://api.datapilotax.es/api/v1/facturae/json');
define('DPT_API_KEY',  getenv('DPT_API_KEY') ?: 'txp_live_TU_CLAVE_AQUI');
define('DPT_PIN_P12',  getenv('DPT_PIN_P12')  ?: 'PIN_DE_TU_CERTIFICADO');
// ⚠️  Nunca hardcodear credenciales. Usa variables de entorno o wp-config.php

// ── Payload — estructura exacta requerida por el backend ──────────────────────
$payload = [
    'series'    => 'F2025',
    'number'    => '0001',
    'issueDate' => '2025-06-15',   // formato YYYY-MM-DD
    'currency'  => 'EUR',
    'version'   => '3.2.1',

    'issuer' => [
        'taxIdNumber'      => 'B12345678',   // NIF/CIF emisor — 9 chars
        'taxIdCountryCode' => 'ESP',
        'legalName'        => 'Mi Empresa SL',
        'address' => [
            'address'     => 'Calle Gran Vía 1',
            'postCode'    => '28013',
            'town'        => 'Madrid',
            'province'    => 'Madrid',
            'countryCode' => 'ESP',
        ],
    ],

    'receiver' => [
        'taxIdNumber'      => 'A98765432',   // NIF/CIF receptor
        'taxIdCountryCode' => 'ESP',
        'legalName'        => 'Cliente Ejemplo SA',
        'address' => [
            'address'     => 'Avenida Diagonal 100',
            'postCode'    => '08019',
            'town'        => 'Barcelona',
            'province'    => 'Barcelona',
            'countryCode' => 'ESP',
        ],
    ],

    // ⚠️ Clave correcta: "lines" (NO "items")
    'lines' => [
        [
            'description'           => 'Desarrollo módulo ERP integración FacturaE',
            'quantity'              => 1,
            'unitPriceWithoutTax'   => 1500.00,
            'totalAmountWithoutTax' => 1500.00,   // quantity * unitPrice
            'taxRate'               => 21.0,
        ],
    ],

    'totals' => [
        'totalGrossAmount'   => 1500.00,
        'totalTaxAmount'     =>  315.00,   // base * (taxRate/100)
        'totalPayableAmount' => 1815.00,   // gross + tax
    ],
];

// ── Petición cURL ──────────────────────────────────────────────────────────────
$ch = curl_init(DPT_API_URL);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'X-API-KEY: '              . DPT_API_KEY,
        'X-Certificate-Password: ' . DPT_PIN_P12,
    ],
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_SSL_VERIFYPEER => true,   // Nunca deshabilitar en producción
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr  = curl_error($ch);
curl_close($ch);

// ── Manejar resultado ──────────────────────────────────────────────────────────
if ($curlErr) {
    error_log('[DataPilotTax] cURL error: ' . $curlErr);
    throw new RuntimeException('Error de red: ' . $curlErr);
}

if ($httpCode === 200) {
    // $response contiene el XML FacturaE firmado
    $filename = 'factura_' . $payload['series'] . '_' . $payload['number'] . '.xml';
    file_put_contents(__DIR__ . '/facturas/' . $filename, $response);

    // Para WooCommerce / WordPress puedes adjuntarlo al pedido:
    // update_post_meta($order_id, '_factura_xml_path', $filename);

    echo "✅ Factura generada: {$filename}";
    return $response;
} else {
    error_log('[DataPilotTax] Error ' . $httpCode . ': ' . $response);
    throw new RuntimeException("Error API ({$httpCode}): {$response}");
}
?>

¿Listo para integrar FacturaE en tu sistema?

Accede al Dashboard, genera tu API Key y envía tu primera factura en minutos. Sin contratos, sin tarjeta en el plan gratuito.