Two-step confirmations
When the MCP client's approval is not enough, which tools can be put behind a second lock and how a pending action gets completed.
The default: direct execution
When an agent calls emit_document, it emits.
Facturia does not interpose an approval step of its own, because the MCP client's tool-approval UI —
the thing that shows you "Claude wants to call emit_document, allow?" — is the human in the
loop. Adding a second Facturia-side confirmation on top of that, for every write, would be redundant
on the vast majority of calls and would defeat half the point of an agent interface.
Where that is not enough
There are two distinct failure modes, and the client's approval only solves one:
The agent tries to do something the person did not ask for. The client's own approval step solves it — that is exactly what it exists for.
The person reflexively approves everything their chat client asks them, and something with real financial consequence — filing a tax return, an irreversible claim — goes out because someone clicked "allow" on autopilot and not because they deliberately reviewed that figure. The client's approval does not solve this: it is the same click in both cases.
require_confirmation attacks the second.
Turning it on
It is a per-empresa flag in automation_settings, next to auto_emit_46 and friends. It ships
off, like every automation.
curl -X PATCH https://api.facturia.cl/v1/empresas/emp_01K2R6.../automation_settings \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Content-Type: application/json" \
-d '{"require_confirmation": true}'It is a REST field, not an MCP-only setting: REST callers and the dashboard see and control the same flag. The REST API described in the rest of these docs does not change behavior because you turned it on.
Which tools it covers
emit_document, file_f29, emit_tipo46 and reclaim_received_document — the "emit / file /
claim" set.
Every other write (accept_received_document, for instance) stays direct even with the flag on:
accepting already matches the legal default that silence would produce anyway, so putting a lock on
it protects nothing.
What it looks like
// → file_f29
{ "empresa": "77928532-4", "period": "2026-07", "confirm_total_payable": 1373000 }
// ← pending_confirmation (la empresa tiene require_confirmation: true)
{
"status": "pending_confirmation",
"confirmation_id": "conf_01K2SD3P7Q",
"confirmation_url": "https://app.facturia.cl/aprobar/conf_01K2SD3P7Q?token=mcpapv_9lQpV3fA…",
"action": "file_f29",
"summary": "File F29 for período 2026-07 — CLP 1.373.000 payable, due 2026-08-20.",
"expires_at": "2026-08-14T14:45:00Z"
}Nothing was filed. The agent hands you the summary and the link, and stops there.
Who completes it: you, on a page
You open confirmation_url, see which empresa, which action and with what figure, and press
Confirm or Reject. No sign-in needed: the link carries a single-use token, valid for those 15
minutes and for that action and no other. Only then is the F29 (Chile's monthly VAT return) filed —
with exactly the data that was summarized when the agent proposed it, not with whatever the world
looks like at that moment.
The agent cannot complete it, and that is the point
There is no MCP tool that closes a pending action. There was one — confirm_action — and it was
withdrawn: if the agent can complete it by saying "the user told me yes", then the record of your
approval is the agent's word for it, which is exactly what this flag exists to refuse. If you tell
the agent you already approved, have it verify by reading (get_document_status, or file_f29 with
a filing_id).
Confirming twice replays the original result instead of executing twice — the same guarantee
Idempotency-Key gives a REST caller. Rejecting twice is not an error either: you wanted it not to
happen, and it is not happening.
An approval expires after 15 minutes unclaimed. Once expired, the page says so and the agent has to propose the action again to mint a new one.
Sandbox: this is where you rehearse it
The two-step works the same in sandbox: turn require_confirmation on for a test empresa and the
emission is parked, the link is minted, and the /aprobar page opens exactly as it does live —
marked as a test, so nobody mistakes the rehearsal for the real thing.
This could not be rehearsed before
Until September 2026 the sandbox ignored the flag: the API accepted it, reported it as on, and emitted directly anyway. Which meant the most consequential bridge in the product — the one where an agent hands a decision to a person — could only be seen for the first time with real documents. Now it can be exercised at zero risk.
The sixty-second demo is unchanged: the flag defaults to off, so a freshly created sandbox empresa still issues in a single call.
The states that are not errors
Two behaviors of this layer worth being clear about in the client:
- A rate limit and a pending confirmation are not failures. The equivalent of a
429and thepending_confirmationresponses are ordinary tool results with a clearstatusfield, not thrown errors. An agent should read them and decide what to say next, not treat them as something broken. - Every tool description declares its own likely failure modes. An agent choosing between
emit_documentanddraft_document, or deciding whether it is safe to retry after asii_error, should never have to consult external documentation mid-conversation. That is whyretriabletravels with every rejection reason.