Scopes & irreversibility
How to read the required scope and irreversibility of each endpoint from the OpenAPI spec — the x-required-scope and x-irreversible extensions — and the catalog of irreversible operations.
Every public endpoint declares two pieces of safety metadata in the OpenAPI
spec: the exact scope it enforces and whether the operation can be undone.
Clients (the CLI, agents, your own tooling) read them to fail
fast — block a call when the key lacks the scope, confirm before an irreversible
action — instead of discovering the problem from a 403 or an unrecoverable
mutation.
Reading it from the spec
Each operation in the OpenAPI spec carries two custom extensions:
{
"operationId": "public-api.v1.invoices.delete",
"x-required-scope": "invoices:delete",
"x-irreversible": true
}x-required-scope— the singleresource:actionscope the API key must hold to call the operation. Present on every operation.x-irreversible—trueonly on operations that cannot be undone. Absent (treated asfalse) on everything else.
These are x-* vendor extensions, so a generic OpenAPI viewer may not render
them — but any client that parses the spec (like the CLI) reads them directly.
Generate a client from the spec and you inherit both.
Scopes
Scopes are resource:action (e.g. invoices:read, clients:delete) — the
same closed catalog the REST API and the API keys use. A request whose key
lacks the scope returns 403 with code: insufficient_scope. Request only the
scopes your integration needs.
The full catalog — every scope, what it grants, and the sensitive ones — is in
Scopes & permissions. A scope is not always derivable
from the resource name: some endpoints enforce a different scope than you'd
guess (PDF downloads enforce pdfs:read, payment methods enforce
invoices:read, state transitions enforce a :transition scope, VeriFactu
actions enforce verifactu:*). Always read x-required-scope rather than
inferring it.
An API key may hold the super-scope *, which satisfies any
x-required-scope. See Authentication.
Irreversible operations
An operation marked x-irreversible: true has no undo: it deletes data,
emits a fiscal record, transitions a document to a terminal state, or rotates a
secret. The CLI asks for a typed
confirmation before running one; your own tooling should guard them the same
way.
These are the categories that carry x-irreversible: true:
| Category | Examples | Scope |
|---|---|---|
| Deletes (single) | clients.delete, invoices.delete, products.delete, taxes.delete, webhook_endpoints.delete… | <resource>:delete |
| Bulk deletes | invoices.bulk_delete, clients.bulk_delete, products.bulk_delete, suppliers.bulk_delete… | <resource>:delete |
| Fiscal emission / numbering | invoices.send, invoices.mark_sent, invoices.assign_real_number, invoices.corrective, invoices.substitute_simplified | invoices:send / invoices:write |
| Void / annul | invoices.void, invoices.annul | invoices:void |
| Terminal conversions | quotes.convert, proformas.convert, delivery_notes.convert | <resource>:transition |
| Cancel / sign | 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 / certificate | webhook_endpoints.rotate_secret, verifactu.certificates.revoke | webhooks:write / verifactu:write |
| GDPR forget | delivery_notes.signature_audits.forget | delivery_notes:gdpr_forget |
| FacturaE (B2G) submit | invoices.face_submissions.submit, face_submissions.cancel | facturae:write |
This list is the human-readable summary. The machine-readable source of
truth is x-irreversible in the spec — a client that reads it stays correct
even as the catalog grows.
Putting it together
A safe client does two checks before a mutation:
- Scope-check — does the key hold
x-required-scope? If not, stop locally (no wasted round trip). The CLI exits4; see scope-check. - Irreversibility confirm — is
x-irreversibletrue? If so, confirm before calling. The CLI requires--confirm <id>; see irreversible operations.
The official SDKs and the CLI do both for you. If you generate your own client from the spec, wire these two checks yourself from the extensions.