Cómo crear una API de contabilidad que supere una auditoría
Una guía práctica sobre la seguridad y los controles de auditoría que una API financiera necesita antes de que las empresas neerlandesas confíen en ella para su contabilidad.
Una API de contabilidad que devuelve un 200 OK ante una operación de pago no te dice prácticamente nada. No ha confirmado que el libro mayor (ledger) haya registrado el asiento, que el usuario tuviera autorización para realizarlo, que el importe haya superado la validación o que ninguna persona con autoridad lo haya aprobado. Para las empresas en los Países Bajos, donde la autoridad fiscal exige que los registros puedan reconstruirse y conservarse durante siete años, esa brecha entre "la solicitud tuvo éxito" y "la contabilidad es correcta" es donde las auditorías fallan.
Estar preparado para una auditoría es un objetivo de diseño operativo, no un certificado. Significa que la API preserva una cadena completa: actor autenticado, acción autorizada, cambio de estado validado, aprobación, resultado en el libro mayor y evidencia a prueba de manipulaciones. Todo lo que se detalla a continuación trata sobre cómo construir esa cadena deliberadamente en lugar de asumir que la autenticación y TLS son suficientes.
Qué hace que una API de contabilidad esté "lista para auditoría"
Un auditor que reconstruye una transacción necesita responder a una secuencia específica de preguntas. ¿Quién la inició? ¿Tenía permiso para hacerlo? ¿Superó el cambio la validación contable? ¿Quién la aprobó? ¿Qué registró el libro mayor? ¿Puede alterarse ese registro a posteriori sin dejar rastro?
Si tu API no puede responder a las seis preguntas a partir de sus propios registros y modelo de datos, no está lista para una auditoría, sin importar lo limpio que parezca el código. La mayoría de las API manejan bien la primera pregunta y mal el resto.
Los controles que cierran esta brecha se dividen en varios grupos: estado contable explícito, autorización en capas, autenticación acotada, escrituras idempotentes, validación del lado del servidor, separación de funciones y registros a prueba de manipulaciones. Todos se refuerzan mutuamente. Una autorización débil socava un registro de auditoría sólido, ya que deja de ser posible confiar en que el actor registrado tuviera competencias para realizar la acción.
Modela los estados contables antes de modelar los endpoints
El error de diseño más común es tratar cada registro financiero como un objeto de edición libre con operaciones de creación, lectura, actualización y borrado (create, read, update, delete). La contabilidad no funciona así, y un auditor notará inmediatamente si un asiento de diario contabilizado puede sobrescribirse de forma silenciosa.
Cada recurso con relevancia financiera necesita una máquina de estados explícita. Un asiento de diario o un pago suele transicionar a través de los siguientes estados:
draft → submitted → approved → posted → settled
Las correcciones no retroceden por ese camino. Un asiento contabilizado que es erróneo recibe una anulación vinculada o un ajuste compensatorio. El original permanece intacto.
Un conjunto viable de reglas incluye lo siguiente:
- Los borradores pueden ser editados por usuarios autorizados.
- Los registros enviados solo pueden ser editados por roles permitidos o devueltos al estado de borrador.
- Los registros aprobados requieren una modificación controlada y una nueva aprobación.
- Los registros contabilizados no se pueden sobrescribir ni eliminar, solo anular o ajustar.
- Los cambios en periodos cerrados requieren una autorización elevada, un motivo justificado y un evento de auditoría.
Un intento de realizar una transición no permitida, como editar un asiento contabilizado, debe devolver un error estable y, aun así, escribir un registro de auditoría. El intento fallido también constituye evidencia.
Aquí es donde un libro mayor de partida doble inmutable demuestra su valor. El libro mayor de Nordlet está diseñado para que cada transacción llegue como un asiento equilibrado y permanente, cuyo balance se aplica mediante un disparador (trigger) de base de datos en el momento de la confirmación (commit), y las correcciones se realizan mediante anulaciones en lugar de reescrituras. Esa restricción se siente limitante durante el desarrollo y se convierte en aquello en lo que tu contable confía durante una auditoría.
Autoriza cada solicitud, no te limites a autenticarla
La autenticación demuestra quién realiza la llamada, pero no dice nada sobre si ese usuario puede acceder a una factura, un diario o una entidad legal en particular. El Proyecto de seguridad de API de OWASP sitúa la autorización rota a nivel de objeto en el primer puesto de su lista de riesgos, precisamente porque las API exponen identificadores de objetos que facilitan el acceso entre inquilinos cuando faltan controles.
Cada solicitud a una API financiera debe autorizarse frente a una combinación de factores, y no solo mediante un token:
- actor autenticado
- aplicación cliente o cuenta de servicio
- inquilino (tenant)
- entidad legal
- ID de recurso
- operación solicitada
- estado actual del recurso
- importe o umbral de transacción
Dos reglas prácticas importan más que el resto. En primer lugar, deriva el contexto del inquilino y del usuario a partir de la identidad autenticada, y rechaza cualquier reclamación (claim) de rol o inquilino proporcionada por el cliente que entre en conflicto con ella. Un interlocutor nunca debe poder afirmar en nombre de qué empresa está actuando. En segundo lugar, aplica el principio de denegación por defecto. Si ninguna directiva concede explícitamente una acción, esta falla.
Prueba ambas direcciones. El acceso horizontal, donde un inquilino accede a los datos de otro, y el acceso vertical, donde un usuario común accede a funciones de aprobación, contabilización o exportación. Ambas situaciones son comunes y catastróficas en datos contables.
El modelo de roles de Nordlet, que incluye roles de propietario, administrador, contable, gestor, desarrollador y visor en múltiples empresas bajo una misma cuenta, existe para hacer que esta separación sea aplicable y no una mera aspiración. Un rol de desarrollador con capacidad para crear borradores de facturas no debe poder emitir pagos.
Acota los tokens a capacidades de negocio, no a verbos CRUD
Para el acceso delegado, utiliza las directrices de seguridad actuales de OAuth 2.0 en lugar de contraseñas reutilizables o claves de API estáticas amplias. La norma RFC 9700 representa la práctica recomendada actual y establece requisitos claros para los clientes y servidores de autorización: URIs de redirección validadas, uso de PKCE cuando corresponda, comprobaciones de emisor y audiencia, tiempos de vida cortos para los tokens de acceso y rotación de tokens de actualización con revocación.
La decisión sobre los ámbitos (scopes) es donde se refleja el enfoque específico de la contabilidad. Los ámbitos genéricos como lectura (read) y escritura (write) son prácticamente inútiles para la separación de funciones. Los ámbitos deben mapearse a capacidades concretas:
journal:createyjournal:approveson ámbitos separados.- Crear una instrucción de pago no otorga permiso para liberarlo.
- El permiso de exportación es distinto del permiso de lectura, ya que la exportación masiva es una vía de fuga de datos.
Sé preciso acerca de dónde se ubica un producto determinado en esa escala. Las claves de API de Nordlet conllevan ámbitos por módulo, como sales:read y sales:write, que se comprueban en cada acción, lo que separa los módulos y la lectura de la escritura, aunque no la creación de la aprobación; si hoy necesitas esa división más fina, aplícala en tu propio servicio antes de realizar la llamada.
Para operaciones de alto valor, vale la pena evaluar si resulta aplicable el Perfil de seguridad FAPI 2.0. Fue diseñado para API que protegen datos financieros sensibles y ofrece mayores garantías que el OAuth básico. La mayoría de las integraciones contables para pymes no necesitarán el perfil completo, pero los flujos de emisión de pagos y conexión bancaria son los lugares donde debe considerarse.
El inicio de sesión sin contraseña de Nordlet mediante enlaces de un solo uso por correo electrónico elimina el problema de las contraseñas reutilizables para los usuarios humanos, lo que reduce los datos de acceso que hay que rotar, filtrar o exponer a la suplantación de identidad (phishing).
Haz que las escrituras financieras sean idempotentes
Las redes fallan a mitad de una solicitud. Un cliente envía una instrucción de pago, la conexión se interrumpe antes de que llegue la respuesta y el cliente lo reintenta. Sin protección, ahora tienes dos pagos.
Las claves de idempotencia resuelven este problema. El cliente envía una clave única con cada operación de escritura; el servidor registra la clave y su resultado. Un reintento con la misma clave devuelve el resultado original en lugar de crear un segundo asiento. Nordlet acepta una cabecera Idempotency-Key en cada llamada que modifica datos, reproduciendo la respuesta almacenada en caso de un reintento con la misma carga útil (payload) y rechazando la misma clave si la carga útil ha cambiado. Cualquier API de contabilidad que omita esta característica terminará produciendo asientos duplicados en el libro mayor que alguien tendrá que desentrañar a mano.
Combina esto con la validación del lado del servidor. Nunca confíes en que el cliente compruebe que los débitos son iguales a los créditos, que un tipo de IVA es válido para el país y el periodo, o que una cuenta existe. La validación se ejecuta en el servidor, antes de la transición de estado, y una escritura rechazada produce un error estable y un registro de auditoría.
Pistas de auditoría a prueba de manipulaciones y retención en los Países Bajos
El registro de auditoría es la capa de evidencia y tiene requisitos diferentes a los de los datos comerciales ordinarios. Debe registrar la decisión de autorización, la versión de la directiva, el actor, el objeto, la operación, el estado anterior y el nuevo, y el código de motivo, sin registrar nunca secretos ni credenciales de pago completas.
La propiedad fundamental es la resistencia a la manipulación. Si un administrador puede editar o eliminar silenciosamente los registros de auditoría, el registro no demuestra nada. El almacenamiento de solo adición (append-only), el encadenamiento criptográfico o la retención de escritura única abordan este problema. El punto clave es que cualquier modificación debe ser detectable.
La retención merece su propia política, separada de la eliminación de registros comerciales. En los Países Bajos, el periodo general de retención de registros administrativos es de siete años, y se extiende a diez años para los registros relacionados con bienes inmuebles. Tus flujos de trabajo habituales de eliminación de datos y supresión del RGPD no deben poder destruir registros ni evidencias de auditoría que sigan cubiertos por una norma de retención legal. Define las reglas de retención legal, archivo y eliminación de las evidencias de auditoría de forma independiente, y asígnalas a las jurisdicciones en las que operes.
El bloqueo de periodos respalda esto en la capa contable. Una vez que se cierra un mes, los asientos contenidos en él no pueden modificarse sin una autorización elevada y un motivo justificado. Nordlet aplica el bloqueo de periodos para que los meses cerrados permanezcan cerrados, rechazando cualquier apunte fechado dentro de un periodo bloqueado incluso a través de la API, lo cual es una de las primeras cosas que comprueba un auditor neerlandés.
Asegura los extremos: webhooks, exportaciones e integraciones
La API principal suele ser la parte mejor defendida del sistema. Los extremos presentan fugas.
Los webhooks conllevan un riesgo de solicitud falsificada. Un evento como sale_invoice.paid debe estar firmado para que el destinatario pueda verificar que proviene de ti, y los destinatarios deben tratar la entrega como un envío de al menos una vez (at-least-once) y utilizar el ID de evento para la desduplicación. Nordlet firma cada entrega de webhook con una firma HMAC sobre el cuerpo sin procesar y reintenta las entregas fallidas con retroceso exponencial (exponential backoff), por lo que el receptor debe verificar la firma y desduplicar por ID de evento en lugar de asumir una entrega exacta de una vez (exactly-once).
Las exportaciones representan una vía de fuga masiva de datos. Las exportaciones de informes en XLSX, PDF o JSON extraen grandes volúmenes de datos financieros en una sola operación, por lo que requieren su propio permiso, límites de velocidad (rate limits) y registro de auditoría. Las integraciones de terceros que utilices deben tratarse como entradas no confiables y validarse de la misma manera que validas las solicitudes directas de los clientes.
Lista de verificación de preparación para auditorías de una API de contabilidad neerlandesa
Utiliza esta lista antes de afirmar que una integración está lista para una auditoría:
- Máquina de estados explícita en cada recurso financiero; los asientos contabilizados no se pueden sobrescribir.
- Autorización a nivel de objeto y de entidad legal en cada solicitud, con denegación por defecto.
- Contexto de inquilino y rol derivado del token, no de las reclamaciones del cliente.
- OAuth 2.0 según RFC 9700; ámbitos basados en capacidades; separación entre creación y aprobación.
- Separación de funciones aplicada en los roles, no solo documentada.
- Claves de idempotencia en todas las escrituras financieras.
- Validación contable y de IVA del lado del servidor antes de las transiciones de estado.
- Registro de auditoría de solo adición y a prueba de manipulaciones con códigos de motivo.
- Reglas de retención y retención legal adaptadas a los periodos neerlandeses (siete años, diez para propiedades).
- Bloqueo de periodos en los meses cerrados.
- Webhooks firmados con desduplicación; exportaciones con ámbitos definidos, limitación de velocidad y registro.
Qué construiríamos primero
Si tuviéramos que integrar la contabilidad en una plataforma neerlandesa mañana, empezaríamos por el modelo de estados y la autorización a nivel de objeto antes de escribir un solo endpoint de negocio. Esas dos decisiones condicionan todo lo posterior, y adaptarlas a posteriori en un sistema que trataba los asientos del libro mayor como filas editables resulta verdaderamente complejo. La idempotencia y el registro de auditoría vienen a continuación, ya que su incorporación temprana es económica y tardía resulta costosa una vez que los datos fluyen.
El resto (tokens con ámbitos, webhooks firmados, bloqueo de periodos) resulta más fácil de implementar una vez que los cimientos se sostienen. Todo ello se puede probar en una empresa de pruebas (sandbox) antes de que toque ningún dato de producción.
FAQ
¿Significa una API lista para auditorías que la empresa cumple con la normativa?
No, y conviene ser precisos al respecto. La preparación para auditorías es una propiedad de diseño del sistema: el libro mayor, los controles y la cadena de evidencias se construyen para que una auditoría pueda tener éxito. El cumplimiento de un marco fiscal, contable o de seguridad específico es una evaluación independiente que asigna esos controles a un estándar determinado. Una API bien construida facilita el trabajo de cumplimiento, pero no lo sustituye.
¿Cuánto tiempo deben conservarse los registros contables en los Países Bajos?
La obligación general es de siete años para los registros administrativos, extendiéndose a diez años para los registros vinculados a bienes inmuebles. Crea reglas de retención y retención legal que tus flujos de trabajo habituales de eliminación no puedan anular.
¿Es suficiente una clave de API estática para una integración financiera?
Para la automatización de servidor a servidor con un ámbito muy limitado puede funcionar, pero las claves estáticas reutilizables son difíciles de rotar y peligrosas si se filtran. Para el acceso delegado y cualquier flujo orientado a usuarios humanos, OAuth 2.0 con tokens de vida corta y ámbitos basados en capacidades es la opción más sólida.
¿Por qué es tan importante la idempotencia específicamente para la contabilidad?
Porque una escritura duplicada en la mayoría de los sistemas es una molestia, pero una escritura duplicada en contabilidad es una cifra incorrecta en los libros que alguien tiene que encontrar y revertir. Las claves de idempotencia hacen que los reintentos sean seguros en lugar de arriesgados.
Lecturas adicionales
- Proyecto de seguridad de API de OWASP para conocer las categorías actuales de riesgo en API.
- RFC 9700: Mejores prácticas de seguridad para OAuth 2.0 para los requisitos de acceso delegado.
- IVA de la UE en tiempo real para desarrolladores en los Países Bajos sobre cómo es el panorama fiscal neerlandés en la práctica.
- Convenciones de API para ámbitos, idempotencia, errores y firma de webhooks.