Skip to main content

When is approval required?

The Mandate policy engine can require human approval before a transaction proceeds. Seven conditions trigger an approval request. If any one matches, the intent enters approval_pending state and waits for the owner’s decision. You configure the first three triggers in the Policy Builder. The remaining four are system-level checks that Mandate runs automatically on every transaction.

How does the SDK signal an approval requirement?

When a transaction passes policy checks but requires human sign-off, the SDK throws an ApprovalRequiredError. This is not a rejection. The intent is created and waiting for a decision. Your code catches the error, extracts the intentId, and polls until the owner approves or rejects.

Handling approval workflows

When a transaction requires human approval, the SDK throws an ApprovalRequiredError. Catch it and poll for the decision:
The owner receives a notification via their configured channel (dashboard, Telegram, or Slack webhook) and can approve or reject with an optional note. See Approvals Dashboard and Notifications.

Catching ApprovalRequiredError

Here is the full pattern using MandateClient directly. This gives you maximum control over the wait behavior.
The waitForApproval() method polls GET /api/intents/{intentId}/status at the specified interval. It resolves when the status becomes approved or confirmed. It throws a MandateError if the approval is rejected (failed) or times out (expired).

waitForApproval options

MandateWallet shortcut

MandateWallet provides transferWithApproval() and sendTransactionWithApproval() that handle the entire flow: validate, wait for approval if needed, sign, broadcast, and confirm. No manual try/catch required.
If the policy does not require approval, these methods skip the wait and proceed directly. Your code works the same regardless of whether approval is needed.

How owners approve

When a transaction enters approval_pending, the owner receives a notification through their configured channels:
  • Dashboard: The Approvals page shows pending requests with agent name, amount, action, reason, and risk level. One-click approve or reject with an optional note.
  • Telegram bot: Sends a formatted message with transaction details. The owner replies with approve or reject.
  • Slack webhook: Posts to the configured channel with action buttons.
Each channel shows the same information: who is the agent, what it wants to do, how much, why, and the assessed risk level. The owner can add a note when approving or rejecting, which becomes part of the audit trail.
Configure notification channels in Dashboard > Notifications. You can enable multiple channels simultaneously. The first decision from any channel takes effect.

Approval TTLs

Pending approvals expire after 1 hour by default. This matches the waitForApproval() default timeout of 3600000ms. After expiry, the intent transitions to expired state. The agent must call validate() again to create a new approval request. You cannot extend the TTL programmatically. If your workflow requires longer decision windows, contact support to adjust the server-side configuration.
Do not retry a timed-out approval by re-polling the same intentId. The intent is terminal once expired. Call validate() again to start a fresh approval request.

Next Steps

Approvals Dashboard

Review and manage pending approval requests from your agents.

Notifications

Configure Telegram, Slack, and dashboard notification channels.

Approval Triggers Reference

Full reference for all 7 approval trigger conditions and their policy fields.

MandateWallet

High-level SDK with built-in approval handling via transferWithApproval().