ALLOW from Attesso and executing it against your own PSP. The pattern is the same for every provider: authorize first, execute second, then report finality.
The core pattern
external_action_reference— your idempotency key for the PSP call.provider_transaction_reference— the PSP’s transaction/charge ID (on commit).
Step 1 — Authorize the proposed action
can_execute is exactly true and before execute_before. A DENY or INDETERMINATE means do not call your PSP.
Step 2 — Execute on your PSP
Now bind theALLOW to a real action on your rail. The request you send to your PSP must be derived from the same immutable proposed action you sent to Attesso — never rebuild it from mutable UI or agent state.
Stripe example
Adyen example
Step 3 — Report finality
After the PSP returns a definite result, report it to Attesso. This is what closes the loop and produces the evidence.Commit (the PSP accepted the action)
Cancel (the PSP rejected, or you aborted)
Idempotency and safety
- Use a separate idempotency key per boundary: one for the authorization, one for the PSP call, one for the commit/cancel.
- Retries must reuse the same key only when the operation and bytes are logically identical. Never turn a changed operation into a retry.
- If the PSP call times out, reconcile before committing or canceling — a timeout is not proof the provider did nothing. See the reconciliation guide.
What this buys you
- Spending control: the agent cannot exceed the user-signed bounds.
- Verifiable evidence: the signed bundle proves the user approved the exact mandate and the agent stayed inside it — anyone can verify it without trusting Attesso (see verify evidence).
- No float, no license, no provider-adapter matrix: you keep your PSP, your funds, and your compliance responsibility.

