Factuarea APIDevelopers

Scopes e irreversibilidad

Cómo leer el scope requerido y la irreversibilidad de cada endpoint desde la especificación OpenAPI — las extensiones x-required-scope y x-irreversible — y el catálogo de operaciones irreversibles.

Cada endpoint público declara dos piezas de metadata de seguridad en la especificación OpenAPI: el scope exacto que enforza y si la operación se puede deshacer. Los clientes (el CLI, los agentes, tu propio tooling) las leen para fallar pronto — bloquear una llamada cuando la key carece del scope, confirmar antes de una acción irreversible — en lugar de descubrir el problema por un 403 o una mutación irrecuperable.

Leerlo desde la especificación

Cada operación en la especificación OpenAPI lleva dos extensiones personalizadas:

{
  "operationId": "public-api.v1.invoices.delete",
  "x-required-scope": "invoices:delete",
  "x-irreversible": true
}
  • x-required-scope — el único scope resource:action que la API key debe tener para llamar a la operación. Presente en todas las operaciones salvo GET /v1/me, que no necesita ningún scope: cualquier credencial válida puede consultarse a sí misma.
  • x-irreversible — true solo en las operaciones que no se pueden deshacer. Ausente (tratado como false) en todo lo demás.

Son extensiones de proveedor x-*, así que un visor OpenAPI genérico puede no renderizarlas — pero cualquier cliente que parsee la especificación (como el CLI) las lee directamente. Genera un cliente desde la especificación y heredas ambas.

Scopes

Los scopes son resource:action (p. ej. invoices:read, contacts:delete) — el mismo catálogo cerrado que usan la REST API y las API keys. Una petición cuya key carece del scope devuelve 403 con code: insufficient_scope. Pide solo los scopes que tu integración necesita.

Una operación exige un segundo scope además de x-required-scope cuando un campo amplía lo que lee: POST /v1/companies/{company}/purchase-invoices con source_purchase_invoice_id necesita también purchase_invoices:read, porque copia las líneas de otro documento. Consulta Líneas de compra medidas.

Las operaciones de control horario llevan sus propios scopes — employees:*, time_entries:*, work_schedules:*, absences:*, presence:read, holidays:read y payroll_exports:read — todos tras el módulo control_horario. Consulta Control horario.

Las automatizaciones hacen lo mismo con automations:read, automations:write, automations:delete y automation_runs:read, tras el módulo automations. Consulta Automatizaciones.

El modelo de cuentas añade sus propios scopes. account:read, account:write y account:owner cubren la propia cuenta (sus keys, su consumo y su titularidad), members:*, invitations:* y nif_transfers:* su equipo y sus traspasos de NIF (necesitan el módulo user_management), y companies:* su cartera de NIF. Consulta Autenticación › Administración de la cuenta.

Dos scopes son privilegiados: accounts:read y accounts:write. Permiten que una cuenta aprovisione, administre y cobre cuentas gestionadas para sus clientes, y funcionan distinto de cualquier otro scope: el super-scope * no los cubre, Factuarea concede el privilegio cuenta a cuenta y lo comprueba en cada petición (403 privileged_scope_required si falla), y el consentimiento OAuth nunca los concede, así que usa una API key. Consulta Scopes privilegiados y Cuentas gestionadas.

Los documentos de control (DeCA) usan transport_documents:read, transport_documents:write (borradores y envío por email), transport_documents:delete (solo borradores) y transport_documents:transition (emitir, modificar, cerrar, reabrir, anular y sustituir), tras el módulo transport_documents, que a su vez requiere delivery_notes. El PDF de cada versión exige pdfs:read; el justificante de emisión (GET /v1/companies/{company}/transport-documents/{transport_document}/issuance-proof) no es un PDF del documento sino la exportación de su registro de emisión, así que exige transport_documents:read. Consulta Documento de control (DeCA).

Los proyectos y las tareas usan projects:read|write|delete, tasks:read|write|delete, users:read y notifications:read|write. projects:* y tasks:* están tras el módulo tasks al emitir la credencial: una key con esos scopes para una empresa sin el módulo se rechaza con scope_not_allowed_by_plan, y sin el scope cada petición recibe insufficient_scope. users:read y notifications:* son transversales y no pertenecen a ningún módulo. Los dos scopes de borrado son solo de API key: un consentimiento OAuth nunca los concede. Facturar las horas de un proyecto (POST /v1/companies/{company}/projects/{project}/time-invoices) exige invoices:write, no un scope de proyectos, porque crea una factura. Consulta Proyectos y tareas.

El catálogo completo — cada scope, qué concede, y los sensibles — está en Scopes y permisos. Un scope no siempre se deriva del nombre del recurso: algunos endpoints enforzan un scope distinto del que adivinarías (las descargas de PDF enforzan pdfs:read, los métodos de pago enforzan invoices:read, las transiciones de estado enforzan un scope :transition, las acciones de VeriFactu enforzan verifactu:*). Lee siempre x-required-scope en lugar de inferirlo.

Una API key puede tener el super-scope *, que satisface cualquier x-required-scope salvo los privilegiados accounts:read y accounts:write. * no cubre accounts:*: una key que solo tenga * responde 403 insufficient_scope en esas operaciones, por amplia que parezca. Lista accounts:* de forma explícita, en una cuenta que tenga el privilegio. Consulta el super-scope.

Operaciones irreversibles

Una operación marcada x-irreversible: true no tiene deshacer: borra datos, emite un registro fiscal, transiciona un documento a un estado terminal, rota o revoca un secret, o cambia quién es titular de una cuenta, quién la alcanza o quién la paga. El CLI pide una confirmación tipada antes de ejecutar una; tu propio tooling debería protegerlas igual.

Estas son las categorías que llevan x-irreversible: true:

CategoríaEjemplosScope
Borrados (individuales)contacts.delete, invoices.delete, products.delete, purchase_invoices.delete, webhook_endpoints.delete…<resource>:delete
Borrados de subrecursos de catálogoproducts.presentations.delete, products.variants.delete, products.supplier-offers.delete, price-lists.delete, price-lists.items.delete, price-lists.items.purge_retiredproducts:write / price_lists:write
Borrados masivosinvoices.bulk_delete, contacts.bulk_delete, products.bulk_delete…<resource>:delete
Borrados de tareas y proyectostasks.delete, tasks.bulk_delete, tasks.comments.delete, tasks.attachments.delete, tasks.time_entries.delete, task_labels.delete, projects.delete, projects.columns.delete, projects.custom_fields.delete: las nueve operaciones irreversibles del módulotasks:delete / projects:delete
Emisión / numeración fiscalinvoices.send, invoices.mark_sent, invoices.assign_real_number, invoices.corrective, invoices.substitute_simplifiedinvoices:send / invoices:write
Void / anulacióninvoices.void, invoices.annulinvoices:void
Conversiones terminalesquotes.convert, proformas.convert, delivery_notes.convert<resource>:transition
Cancelar / firmardelivery_notes.cancel, delivery_notes.sign, recurring_invoices.cancel, recurring_invoices.generate<resource>:transition / :write
VeriFactu (AEAT)invoices.verifactu_create, verifactu.records.subsanar, verifactu.settings.update, verifactu.certificates.revokeverifactu:write
Secret / certificadowebhook_endpoints.rotate_secret, verifactu.certificates.revokewebhooks:write / verifactu:write
Traspaso de NIFaccount.nif_transfers.create, account.nif_transfers.accept, account.nif_transfers.revokenif_transfers:write
Titularidad y equipo de la cuentaaccount.owner.transfer, account.members.deleteaccount:owner / members:write
Keys y webhooks de la cuentaaccount.api_keys.revoke, account.api_keys.rotate_secret, account.webhooks.delete, account.webhooks.rotate_secretaccount:write / webhooks:delete / webhooks:write
Cuentas gestionadas (privilegiado)managed_accounts.create, managed_accounts.claim_tokens.create, managed_accounts.management.end, managed_accounts.plan.update, managed_accounts.imports.createaccounts:write
Olvido GDPRdelivery_notes.signature_audits.forgetdelivery_notes:gdpr_forget
Documentos de controltransport_documents.issue, transport_documents.modify, transport_documents.cancel, transport_documents.supersede, transport_documents.sendtransport_documents:transition / transport_documents:write
Envío FacturaE (B2G)invoices.face_submissions.submit, face_submissions.cancelfacturae:write
Sellado del cierre mensualmonthly_time_record_closes.sealtime_entries:write
Relanzamiento (reejecución)automations.runs.replay, automations.runs.steps.replay, integrations.events.replayautomations:write / integration_events:write

Quitar de una tarea una relación, un enlace externo, un vínculo con una entidad o una etiqueta no es irreversible —cada uno se puede volver a crear— y solo necesita tasks:write.

Esta lista es el resumen legible. La fuente de verdad legible por máquina es x-irreversible en la especificación — un cliente que la lee se mantiene correcto aunque el catálogo crezca.

Juntándolo todo

Un cliente seguro hace dos comprobaciones antes de una mutación:

  1. Scope-check — ¿tiene la key el x-required-scope? Si no, para en local (sin gastar un round trip). El CLI sale con 4; consulta scope-check. Una operación sin la extensión (GET /v1/me) no necesita comprobación, y para accounts:* el scope es necesario pero no suficiente: la cuenta también debe tener el privilegio, que GET /v1/me informa en account.is_provider y account.privileged_scopes.
  2. Confirmación de irreversibilidad — ¿es x-irreversible true? Si lo es, confirma antes de llamar. El CLI requiere --confirm <id>; consulta operaciones irreversibles.

Los SDKs oficiales y el CLI hacen ambas por ti. Si generas tu propio cliente desde la especificación, cablea estas dos comprobaciones tú mismo desde las extensiones.

Permisos de tiendas

La gestión de tiendas usa stores:read y stores:write; los scopes del proveedor son woocommerce_store:read, woocommerce_store:write, shopify_store:read y shopify_store:write. Las pruebas de conexión requieren el scope de escritura del proveedor. Estos scopes se asignan a API keys y quedan fuera del consentimiento OAuth. Consulta la tabla de operaciones de tiendas.

En esta página

¿Te echamos una mano?Contactar con soporte