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 scoperesource:actionque la API key debe tener para llamar a la operación. Presente en todas las operaciones.x-irreversible—truesolo en las operaciones que no se pueden deshacer. Ausente (tratado comofalse) 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/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 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. Consulta Autenticación.
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, o rota
un secret. 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ía | Ejemplos | Scope |
|---|---|---|
| Borrados (individuales) | invoices.delete, products.delete, taxes.delete, webhook_endpoints.delete… | <resource>:delete |
| Borrados de subrecursos de catálogo | products.presentations.delete, products.variants.delete, products.supplier-offers.delete, price-lists.delete, price-lists.items.delete, price-lists.items.purge_retired | products:write / price_lists:write |
| Borrados masivos | invoices.bulk_delete, products.bulk_delete… | <resource>:delete |
| Emisión / numeración fiscal | invoices.send, invoices.mark_sent, invoices.assign_real_number, invoices.corrective, invoices.substitute_simplified | invoices:send / invoices:write |
| Void / anulación | invoices.void, invoices.annul | invoices:void |
| Conversiones terminales | quotes.convert, proformas.convert, delivery_notes.convert | <resource>:transition |
| Cancelar / firmar | delivery_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.revoke | verifactu:write |
| Secret / certificado | webhook_endpoints.rotate_secret, verifactu.certificates.revoke | webhooks:write / verifactu:write |
| Olvido GDPR | delivery_notes.signature_audits.forget | delivery_notes:gdpr_forget |
| Envío FacturaE (B2G) | invoices.face_submissions.submit, face_submissions.cancel | facturae:write |
| Sellado del cierre mensual | monthly_time_record_closes.seal | time_entries:write |
| Relanzamiento (reejecución) | automations.runs.replay, automations.runs.steps.replay, integrations.events.replay | automations:write / integration_events: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:
- Scope-check — ¿tiene la key el
x-required-scope? Si no, para en local (sin gastar un round trip). El CLI sale con4; consulta scope-check. - Confirmación de irreversibilidad — ¿es
x-irreversibletrue? 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.