agreement.transitioned events. Use them when your backend needs to react to agreement lifecycle changes without polling agreement state on a timer.
Treat each activity webhook as a compact signal: verify it, store and dedupe it, acknowledge it, and then read current agreement data from the Agreements API before updating your local mirror.
Before you start
Create a webhook subscription that includesagreement.transitioned:
When activity events are sent
Shodai sendsagreement.transitioned for API-managed agreements owned by the Shodai account when:
- the chain projection worker reconciles an agreement deployment into its initial state
- a mined input changes the agreement state
head - 20.
Deploy transitions use fromState: "", inputId: "__deploy", and sequence: 0. Those are payload values, not filter values: to subscribe to deploy transitions only, filter with inputIds: ["__deploy"] — a blank filter value such as fromStates: [""] is rejected with 400.
Input transition events are sent only when the mined input changes state. If an input is accepted but the agreement remains in the same state, no agreement.transitioned event is emitted for that input.
Payload shape
An activity event includes compact transition data:
The activity payload does not include the full agreement record, variables, participants, observers, or full input history.
Reconcile after receipt
After verification and dedupe, read the current agreement data before updating local state:GET /v0/agreements/{id} for the hosted agreement record, GET /v0/agreements/{id}/state for current lifecycle state, and GET /v0/agreements/{id}/inputs for input history.
This pattern keeps your integration resilient when events arrive more than once, arrive after your own write response, or do not contain enough data to update your local model directly.
Filter activity events
Activity webhooks support these filters:
Filter values are exact string matches. Multiple values inside one filter field act like OR. Different filter fields combine like AND.
Use
inputIds: ["__deploy"] to receive only deploy activity events for matching agreements and templates.
Idempotency expectations
Webhook delivery is at-least-once. Your receiver should:- store each event by
id - treat a repeated
idas already received - return
2xxafter durable receipt - process reconciliation asynchronously when possible
- make local mirror updates idempotent
sequence, ignore a sequence lower than the highest already applied, and use the current API state as the source of truth. Events emitted before sequence was introduced may omit it.