Faxtal

Autenticación y seguridad

La API pública se autentica solo con API key. Esta página explica cómo enviarla, qué puede hacer cada clave y qué límites tiene.

Enviar la clave

Añade la cabecera X-API-Key a cada petición:

curl -s https://app.faxtal.com/api/v1.1/company \
  -H "X-API-Key: $FAXTAL_API_KEY"
  • Es la única forma de autenticarse: la API pública no admite Authorization: Bearer ni sesiones de usuario.
  • Llama siempre por HTTPS.
  • GET /api/v1.1/health es la única operación que no pide clave.

Formato de la clave

Una clave tiene esta forma (valor ficticio):

fctXXXXXXXX_YYYYYYYYYYYYYYYY
  • Tiene tres partes: el prefijo fct, un identificador y, tras un guion bajo, el secreto.
  • Envíala entera y sin espacios. El secreto también puede contener _ y -.
  • Faxtal no guarda el secreto en claro. Por eso no puede volver a mostrarte una clave.

Ciclo de vida

Las claves se gestionan en la aplicación, en Configuración → API Keys, con el rol Propietario o Admin. Los pasos están en Crear y gestionar API keys.

AcciónQué pasa
CrearLa clave se muestra una sola vez. Puedes darle una fecha de caducidad.
RotarSe crea una clave nueva. Decides si la anterior se revoca en ese momento o sigue funcionando hasta que la revoques.
RevocarLa clave deja de funcionar al momento.
CaducarAl llegar su fecha de caducidad, la clave deja de funcionar.

Una clave revocada, caducada o mal copiada recibe la misma respuesta, 401:

{
  "detail": {
    "code": "unauthorized",
    "message": "Invalid credentials",
    "request_id": "4f1c0a9e2b7d4e5f8a6b3c2d1e0f9a8b"
  }
}

Si falta la cabecera, message es Missing credentials.

Empresa de la clave

  • Cada clave pertenece a una empresa y la API trabaja siempre sobre ella. La empresa no va en la URL.
  • Los recursos de otra empresa no existen para tu clave: la API responde 404.
  • GET /api/v1.1/company te dice a qué empresa pertenece la clave.

Permisos (scopes)

Cada operación exige un permiso. Si la credencial no lo tiene, la API responde 403:

{
  "detail": {
    "code": "scope_missing",
    "message": "La credencial no tiene permiso para esta operación.",
    "scope": "invoices:issue",
    "request_id": "4f1c0a9e2b7d4e5f8a6b3c2d1e0f9a8b"
  }
}

Una clave sin permisos definidos tiene acceso completo.

:::info Los permisos y la lista de IP permitidas aún no se pueden configurar desde la aplicación. Las claves que creas allí tienen acceso completo desde cualquier IP. :::

PermisoQué permitePor ejemplo
invoices:readConsultar facturas, documentos, terceros y productos, y validar sin guardarGET /issued-invoices, GET /drafts/{invoice_id}, GET /issued-invoices/{invoice_id}/pdf, POST /issued-invoices/validate, GET /third-parties
invoices:writeGuardar y borrar borradores, enviar facturas por email y gestionar documentos de emitidasPUT /drafts, POST /drafts/batch, DELETE /drafts/{invoice_id}, POST /issued-invoices/{invoice_id}/send, POST /issued-invoices/{invoice_id}/documents
invoices:issueEmitir, importar, anular y borrar emitidasPOST /issued-invoices/{invoice_id}/issue, POST /issued-invoices/import, POST /issued-invoices/{invoice_id}/cancel, DELETE /issued-invoices/{invoice_id}
received:writeReconocer, registrar y borrar recibidas y sus documentosPUT /received-invoices, POST /received-invoices/import, POST /received-invoices/recognize, DELETE /received-invoices/{invoice_id}
parties:writeCrear y actualizar tercerosPUT /third-parties
payments:readConsultar los cobros de emitidas y los pagos de recibidasGET /issued-invoices/{invoice_id}/payments, GET /received-invoices/{invoice_id}/payments
payments:writeRegistrar, corregir y compensar cobros y pagosPOST /issued-invoices/{invoice_id}/payments, POST /received-invoices/{invoice_id}/payments/{payment_id}/reverse, POST /issued-invoices/{invoice_id}/payments/compensate
compliance:readConsultar certificados y el estado de VeriFactu y del SIIGET /certificates, GET /verifactu/submissions, GET /verifactu/incidents, GET /sii/pending
  • * concede todos los permisos. invoices:* concede todos los de invoices, y lo mismo con los demás prefijos.
  • GET /company y GET /companies no exigen permiso.
  • Cambiar la configuración de VeriFactu o del SII (PUT /verifactu/config, PUT /sii/config) y registrar eventos SIF (POST /verifactu/sif) exigen acceso completo.

Restricción por IP

  • Una clave puede llevar una lista de direcciones IP o rangos CIDR, IPv4 o IPv6, desde los que se admite.
  • Desde cualquier otra IP, la API responde 403 con ip_forbidden.

Límites de uso

Peticiones por minuto

  • Cada clave admite hasta 120 peticiones por minuto. El contador vuelve a cero al empezar cada minuto de reloj.
  • Al superarlo, la API responde 429 con rate_limited y estas cabeceras:
CabeceraValor
Retry-AfterSegundos que faltan para poder volver a llamar
X-RateLimit-LimitPeticiones admitidas por minuto
X-RateLimit-Remaining0
X-RateLimit-ResetMomento en que vuelve a cero el contador, en segundos Unix
  • Las respuestas correctas no llevan estas cabeceras.
  • Espera lo que indica Retry-After antes de reintentar. Para volúmenes grandes, usa los lotes: POST /drafts/batch y POST /issued-invoices/import/batch.

Plan

  • Si el plan de la empresa no incluye la API, cualquier llamada autenticada responde 402 con feature_outside_plan y "feature": "api_access".
  • Algunas funciones dependen además del plan, como el catálogo de productos. Si el plan no las incluye, 402 con feature_outside_plan y la funcionalidad en feature.
  • Si la empresa ha agotado el cupo anual de facturas de su plan, crear una factura nueva, también un borrador, responde 402 con quota_exceeded, limit y used. Emitidas y recibidas tienen cupos separados. Actualizar una factura que ya existe no consume cupo.

Buenas prácticas

  • Guarda la clave en tu servidor, en un gestor de secretos o en una variable de entorno. Nunca en el código fuente, en un repositorio ni en una aplicación que se ejecute en el navegador o en el móvil.
  • Usa una clave por integración. Así puedes revocar una sin parar las demás.
  • Ponle fecha de caducidad y rótala antes de que llegue.
  • Para rotar sin cortes: rota sin revocar la anterior, despliega la clave nueva y revoca la antigua.
  • Si sospechas que se ha filtrado, revócala en ese momento.
  • No escribas la clave en tus logs. Guarda el request_id de las respuestas de error.

Ver también

On this page