Agentic payment testing: 16 mandate test cases
Use this free test pack to review an agent’s spending authority before connecting a payment flow. It includes 16 synthetic cases, explicit expected results and a downloadable JSON fixture. Start with a permitted €30 purchase, then change the facts that should change the decision.
Scope: Original ZILLQ reference scenarios, version 1.0.0. These are test specifications, not results from the ZILLQ sandbox, an executable test runner, a regulatory certification or a provider API contract.
Download and use the test pack
Download the 16 cases as JSON ↓
No registration is needed. Copy the examples into a design review or adapt them to your test harness. The readable cases below contain the same IDs as the download, so a ticket can link to an individual case. Your browser’s Print command produces a clean review copy.
Reset to the baseline for each case. Merge the named field overrides into the baseline policy, state or request. The file explains its units and sequence semantics. Replay, race and recovery cases require a stateful adapter: evaluating a single boolean predicate cannot test them.
For a step-by-step view of exact replay, a changed payload and a lost response, see the payment retry simulator. It is a separate reference model with its own seven scenarios; it does not execute this pack or report results for it.
One explicit baseline
The owner owner-demo grants agent-office permission to buy office supplies from supplier-demo in EUR. The limit is €40 per payment and €200 for the UTC period from 1 October to 1 November 2026. The mandate is active and expires at the start of 1 November; that instant is excluded.
The baseline has €150 committed and €10 reserved for an unresolved payment. That leaves €40 available. The new request is €30 including all charges, evaluated at 10:00 UTC on 3 October. Amounts in the JSON are integer cents: €30 is 3000. Limits are inclusive. Zero and negative purchase amounts are invalid.
Budget invariant: committed amount + reserved amount + proposed reservation must not exceed the period limit. Check and reserve atomically for the mandate and budget period. Two requests must not both consume the same remaining authority.
Identity fields represent verified context, not an invitation to trust an owner ID submitted by the agent. Bind the reviewed supplier identity to the actual payment destination. A purpose field needs trustworthy supporting evidence; an agent can otherwise label any purchase “office supplies.”
The 16 cases and expected results
allow means this sample mandate permits the proposal. The payment still needs the provider’s applicable consent, authentication and execution controls. A scenario can fail several checks; the named reason identifies the boundary under review, not a mandatory order for every implementation.
| Case | Scenario and review point | Expected result |
|---|---|---|
| M01 Within the authority envelope | A €30 request fits the €40 transaction cap and €40 available period budget. Passing this policy check does not bypass the provider’s controls. | {"decision": "allow", "reason": "within_policy"} |
| M02 Exactly at the cap | The sample policy uses inclusive amount limits. A €40 request fits both limits exactly. | {"decision": "allow", "reason": "inclusive_limit"} |
| M03 One cent over the cap | €40.01 exceeds the per-payment cap; the remaining-budget check may also fail. Do not round it down. | {"decision": "deny", "reason": "per_payment_limit"} |
| M04 Aggregate budget exhausted | Only €10 remains available after reservations, so a €30 request must not pass. | {"decision": "deny", "reason": "period_budget"} |
| M05 Recipient substituted | A merchant display name or invoice instruction must not replace the approved recipient identity. | {"decision": "deny", "reason": "payee_not_allowed"} |
| M06 Different currency | A numerical amount under the cap is insufficient; this policy permits only EUR and defines no conversion rule. | {"decision": "deny", "reason": "currency_not_allowed"} |
| M07 Agent identity mismatch | Resolve the acting agent from trusted authentication, then compare it with the mandate. A claimed agent ID in a body is not authentication. | {"decision": "deny", "reason": "agent_mismatch"} |
| M08 Revoked before execution | Check current mandate status at the enforcement boundary, including after a queued proposal. | {"decision": "deny", "reason": "mandate_revoked"} |
| M09 Expiry boundary | The sample validity window excludes expires_at. A request at that instant has no remaining authority. | {"decision": "deny", "reason": "mandate_expired"} |
| M10 Different purchase purpose | The price and supplier alone do not authorize a purpose outside office supplies. Purpose classification needs trusted evidence, not only an agent label. | {"decision": "deny", "reason": "purpose_not_allowed"} |
| M11 Exact replay | Return or retrieve the existing result. Do not execute or reserve budget a second time. | {"new_payment_count": 1, "new_reservation_count": 1, "behavior": "return_existing_result"} |
| M12 Same key, changed payment | Bind the key to the payment details. A changed amount requires a deliberate new operation and authority check. | {"new_payment_count": 1, "second_decision": "conflict"} |
| M13 Two requests race for one budget | One request may reserve €30. The other must see insufficient budget. Either ordering is valid; allowing both is not. | {"allow_count": 1, "deny_count": 1, "new_reserved_minor": 3000} |
| M14 Provider result unknown | Keep the unresolved amount reserved and retrieve the original outcome. Do not infer failure from a timeout or generate a new payment key. | {"new_payment_count": 1, "new_reservation_retained_minor": 3000, "behavior": "reconcile_original_attempt"} |
| M15 Untrusted text asks to raise the limit | Supplier text has no authority to edit the mandate. Any changed authority must come through the owner’s trusted approval flow. | {"decision": "deny", "reason": "per_payment_limit", "policy_unchanged": true} |
| M16 Zero or negative amount | This purchase policy accepts only positive integer minor units. A refund is a separate operation, not a negative purchase. | {"decisions": ["deny", "deny"], "reason": "invalid_amount"} |
Record the evidence, not just “pass”
For each adapted case, retain the fixture version, mandate version, trusted actor context, final payment details, evaluation time and actual decision. For races, capture both operations and the resulting budget. For uncertain outcomes, show how the original provider reference survives recovery.
Record the expected result, observed result and supporting evidence separately. Mark untested cases as untested. A policy decision log is not proof of settlement, and this reference pack does not claim that ZILLQ passes these scenarios. Production assurance also requires controls beyond this small pack.
Extend the cases for your integration: owner-account isolation, changed payee account behind an unchanged merchant label, time-zone rollover, fees, partial capture, lost callbacks and the provider’s idempotency retention window. Choose expected behavior from a written contract before implementing the check.
Why these boundaries matter
The design rationale connects to IETF OAuth security guidance on token protection and privilege restrictions, and Rich Authorization Requests for expressing detailed authorization. Those standards do not define this fixture format or certify these cases.
For business terms, start with the agent payment mandate guide. For the bank-side boundary, read payment consent versus SCA. For timeout and settlement questions, use the pending-payment investigation guide.
Put the questions to a sandbox.
ZILLQ is an independent European payments sandbox with synthetic accounts and funds, agent mandate mechanisms, OAuth2/OpenID Connect authentication and EUDI wallet emulation. Use these references to frame your investigation; they do not certify that every control described here is implemented.
See the platform and its boundaries → · Open the synthetic sandbox →