agreement.notification.triggered events. They use the same webhook subscription, signing, delivery, retry, and filtering system as agreement activity webhooks, but they are created by the notification rules attached to an agreement.
Use notification webhooks when Shodai should evaluate agreement notification rules while your backend owns the final side effect, such as sending email through your own SES account.
How notification webhooks work
There are two required setup steps:- Create a webhook subscription that includes
agreement.notification.triggered. - Deploy an agreement with an agreement-scoped
notificationTemplatewhose rules usenotification.channel: "external_webhook".
agreement.notification.triggered only after an external_webhook notification rule resolves at least one recipient.
Attach notification rules at deploy
PassnotificationTemplate to deployWithPermit:
__deploy notification rules can evaluate.
If the post-deploy state is not available, deploy-triggered notification evaluation is skipped for that deployment. Future agreement transitions can still evaluate matching notification rules.
onTransition rules
onTransition rules evaluate when an agreement transition event reaches the notification service.
onTransition triggers:
from,to, andinputsare optional arrays- omitted arrays act as wildcards
inputs: ["__deploy"]matches deploy notification replay when the deploy transition replay occursfromState,toState, andinputare available for interpolation- the webhook payload includes a
transitionblock
Temporal rules
Temporal rules evaluate while an agreement is in one of the configured states.| Field | Behavior |
|---|---|
states | States where the temporal rule is active. |
condition.type: "deadlineApproaching" | Fires when a date variable is within the threshold and still in the future. |
condition.type: "stateAge" | Fires when time in the current state reaches the threshold. |
condition.type: "elapsedSinceVariable" | Fires when elapsed time since a date variable reaches the threshold. |
threshold.unit | seconds, minutes, hours, days, or weeks. |
fireOnce | Defaults to true; when true, fires once per state visit. |
constraints.maxOccurrences | Caps temporal sends for the rule and agreement. |
constraints.cooldown | Requires a minimum time between temporal sends for the same rule and agreement. |
checkInterval is accepted and stored on temporal triggers, but current hosted evaluation uses a system-wide temporal sweep. Do not rely on checkInterval as a per-rule schedule or cadence guarantee.
Temporal notification payloads do not include a transition block.
Recipient resolution
Each notification rule hasrecipients. Shodai resolves those tokens before emitting notification webhook events.
| Recipient token | Resolution behavior |
|---|---|
Variable key, such as customerWalletAddress | Reads that variable value and resolves it to an email. |
* | Scans agreement variable values for wallet-address-shaped strings and resolves each one. |
@observers | Uses observer email addresses on the agreement. |
- participant email matching the wallet address or matching the variable key
- companion email variable, such as
customerEmailforcustomerWalletAddress - direct email value, when the raw value itself contains an email address
recipients. To notify a literal email address, pass it as an observer or as the value of a recipient variable.
Resolved email addresses are deduped case-insensitively. Unresolved recipients are skipped and logged.
Content interpolation
subject, title, and body support ${variable} interpolation.
For onTransition notifications, interpolation context includes the agreement variables plus:
agreementNameagreementIdfromStatetoStateinput
agreementNameagreementId
${variableName}.
Payload shape
AnonTransition notification webhook includes notification content and transition context:
transition:
agreement.notification.triggered event. That event is delivered as signed POST requests to each active webhook subscription that matches the event type and filters.
Filter notification events
Notification webhooks support these filters:| Filter | Matches |
|---|---|
agreementIds | data.agreementId |
templateIds | data.templateId |
ruleIds | data.ruleId |
inputIds | data.transition.inputId when present |
fromStates | data.transition.fromState when present |
toStates | data.transition.toState when present |
transition, so they do not match inputIds, fromStates, or toStates filters.
Handle notification events
Your receiver handles notification webhooks like any other Shodai webhook:- verify the signature with the subscription secret
- store and dedupe by event
id - return
2xxafter durable receipt - perform your final side effect asynchronously
external_webhook, lets hosted Shodai services evaluate transition and temporal rules, receives agreement.notification.triggered, and sends final email through its own AWS SES configuration.