Business Accounts are in early access. Transaction quorum currently covers EVM. Solana and Bitcoin transaction support is coming soon. See Approvals for signing.
Introduction
This cookbook covers a treasury wallet on a business account that pays an allowlisted vendor. The payment has to pass three policy rules before the wallet can sign:- The account allows only that vendor’s address.
- The wallet caps how much one transaction can send.
- At or above the amount named in a quorum policy, two admins have to approve. The member who starts the payment does not count as one of them.
Event types
Here are the events the payment moves through, in order.
What each event tells you in context comes up in the sections below. The full payload shapes are in Policy violation webhooks, Business account proposal webhooks, and Transaction events.
Subscribe to the payment
One webhook covers the whole flow. Subscribe it to every event in the table.- Dashboard
- CLI
- API
Open Developer > Webhooks, create a webhook pointing at your HTTPS endpoint, and select the
businessAccount.proposal.* events, waas.policy.violation, and the wallet.transaction.* events.ping test payload when the webhook registers. See Setting up webhooks for the full procedure.
Record each step
Before trusting a message, check two things. The signature:x-dynamic-signature-256 should be the HMAC-SHA256 of the raw body, computed with the webhook’s secret. And whether you have seen it before: messages arrive at least once, so keep a record of each messageId you process and drop the repeats. Both mechanics are covered in Setting up webhooks and Event delivery & best practices.
notify and mark calls stand in for your own code. Map the Dynamic user IDs to your members, and send the notification over whatever channel they watch: email, Slack, or your own push.
Three payload details matter while the approvals are still open:
evaluationSummary.isSatisfiedtells you whether the wallet can sign;minimumAdditionalApprovalstells you how many approvals are still missing. Do not add uprequiredCountacrossruleEvaluations: a single approval counts toward every rule its approver is eligible for. See Reading a proposal payload for the full field list.- Once a proposal reaches
vetoed,expired, orexecuted,pendingEligibleApprovers,mandatoryApprovers, andruleEvaluationsreport empty. Capture your routing targets oncreatedandapproved, not at close. businessAccount.proposal.expiredfires shortly after thecompleteBydeadline, not at the deadline itself, and carriesexpiredAtinstead of an actor.
timestamp and the final status over what came in when: an executed you never saw an approved for is still the signature; a completed you never saw a broadcasting for is still the landing.
Confirm the payment landed
businessAccount.proposal.executed means the approvals are in and the wallet signed. What you hold at that point is a signed transaction that has not reached the chain yet. How it gets there decides which events you will see:
- Dynamic broadcasts it on the gas-sponsored EVM path. Then
wallet.transaction.completedmeans it landed,revertedmeans the chain saw it but the contract refused it, andfailedmeans it never arrived.broadcastingandconfirmingcan be skipped, so only those three count. - Your application broadcasts it. Then none of the
wallet.transaction.*events fire at all, and your own chain watcher is what confirms the landing.
proposalId to the transaction.
Reconcile missed events
Messages get missed: an endpoint outage, a disabled webhook, a deploy at the wrong moment. The events feed is the same stream, pulled instead of pushed, so poll it on a schedule or after re-enabling a webhook to replay what was missed.resourceType picks which events you want by matching the start of the event name: businessAccount.proposal for the approvals, waas.policy for a block, wallet.transaction for a payment Dynamic broadcast.
startDatecan look back at most 30 days, and events are kept for 30 days in sandbox and 90 days in live.- Results are unordered, so sort by
timestampyourself. - The same
eventIdcan show up in both the feed and a delivered webhook, so dedupe both against the same seen set.
POST /environments/{environmentId}/webhooks/{webhookId}/messages/{messageId}/redeliver.
Show an admin their approval queue
The webhook tells you the payment is waiting. The admin’s own inbox should use the SDK, which returns only the proposals that member can act on.serializedTransaction is the unsigned payment your application prepared, and walletAccount is the treasury wallet that will sign it.
BusinessAccountProposal tells you its status (pending, executed, vetoed, or expired), its completeBy deadline, approvalRequirements, and intent. To see whether it can still be satisfied, read approvalRequirements[].satisfied rather than counting who has already approved: that approvals list includes people whose approval no longer counts. Resuming the signature is covered in Quorum policies.
Operational notes
- Your endpoint must respond within 15 seconds or the delivery counts as failed and is retried. Accept messages fast and process them asynchronously.
- If deliveries keep failing, Dynamic switches the webhook off: 200 failures in a row, or 250 in sandbox and 1500 in live within 30 days. Turning it back on is manual, so alert on that state and reconcile through the events feed once it is back.
- An environment supports 10 webhooks, and messages are retained for 30 days in sandbox and 90 days in live. The full delivery contract is in Event delivery & best practices.