Skip to main content

Webhook lifecycle states and event sequences

The lifecycle states that DALP webhook events send, the sequences an endpoint receives, and the states the platform reserves.

Every DALP webhook event reports a fact and the lifecycle state of that fact: how far the fact has progressed and whether a later event can replace it. The event catalogue lists events and triggers. The consuming page covers deduplication, ordering and retries.

The states live events carry

An event the platform sends has one of four lifecycle states: pending, provisional, final or retracted. The state is the envelope field lifecycle_state. Read the field, because the name does not always end in the state. funding.requirement.raised has state final, and trading-venue.price-alert.triggered has state provisional. Two retractions, token.corporate-action.retracted and trading-venue.trade.retracted, also have state final.

Subscription patterns such as *.final match the name suffix, not the field. The subscriptions page covers them.

A chain reorganisation replaces recent blocks with a competing set of blocks. The finality depth is the number of blocks that must follow a block before the platform treats it as final. On a network whose node reports finality through the finalized block tag, the platform uses a recommended depth for a known chain, such as 65 blocks on Ethereum mainnet, and 64 blocks for any other. On a network without one, the depth is the number of confirmations set in the network's configuration, which can be 0.

State
What it means
What your system does
pending
A transaction request entered a broadcast state with a transaction hash. The request has no outcome.
Track the request by transactionId and wait for its outcome. This event does not confirm a token movement.
provisional
The platform reports a fact that can still change. A chain reorganisation can still remove the block that holds a fact read from a chain log. A trading-venue order status or price alert reports activity without confirming trade settlement.
Record the fact as unconfirmed and keep the record reversible. A later event follows only for some facts, as the worked sequences show.
final
For a chain log, the source block has reached chain finality. For a change recorded inside the platform, such as opening a funding requirement, the platform has committed the change.
Apply the reported fact once. A later trading-venue.trade-settled.retracted can reverse trading-venue.trade-settled.final, so final does not exclude a later business reversal.
retracted
An earlier reported fact no longer stands. A chain reorganisation or a trade bust can trigger this state.
Match supersedes when present. If it is absent or unknown, match by the payload identifiers and reverse only effects you applied.

Read type for the event name and version for its version. Retractions caused by a chain reorganisation include supersedes, the earlier event's evt_id. For platform-recorded events with state retracted, this field is optional. It names the earlier event when the platform queued it for your endpoint, even if delivery never succeeded.

token.corporate-action.retracted has state final and no envelope supersedes. Match it by corporateActionId. trading-venue.trade.retracted also has state final. It reports a bust, the reversal of a trade whose delivery was still pending. That delivery has no trading-venue.trade.final event. Match it by venueTradeId.

A transaction request outcome has state final, including a failure or cancellation. This state reports the request's outcome, not the chain finality of a token movement. The transaction request events describe those outcomes.

The state recalled is reserved: the platform sends no new event with it. A Replay can resend a recalled event that DALP 3.1 stored.

bank-rail.credit.recalled carries lifecycle_state: "final". It reports that completed bank recalls cover the whole credit. Its name describes the bank outcome, and the envelope state describes the committed observation. See the bank rail catalogue.

Worked sequences

Each table lists the events for one case, with what your system does at each step. The tables assume your endpoint subscribes to the named events and deduplicates each one by evt_id.

A transfer that finalises

When the platform indexes a token transfer, it creates a provisional event and a final event. It queues the provisional event for delivery at once and holds the final event until the finality depth passes the block of the transfer.

Step
Event
State
What your system does
1
token.transfer.provisional
provisional
Record the transfer as unconfirmed. A chain reorganisation can still remove its block.
2
token.transfer.final, version 2
final
Confirm the record. Match it to the provisional event by chainId, transactionHash and logIndex in the payload.

A transfer that a chain reorganisation removes

A chain reorganisation retracts a provisional event only when the platform recorded a successful delivery of that event to your endpoint. The platform cancels the held final event for the removed block, so no final event follows.

Step
Event
State
What your system does
1
token.transfer.provisional
provisional
Record the transfer as unconfirmed.
2
token.transfer.retracted, version 2
retracted
Find the record whose evt_id is in supersedes and reverse it.

This rule applies to chain observations generally: without a recorded successful delivery, the platform cancels the provisional event and sends no retraction. Your handler can have applied an event even when its HTTP acknowledgement was lost. Keep those effects provisional: absence of a retraction does not confirm that the observation stayed on the canonical chain. Reconcile an uncertain observation against the current canonical transaction receipt and its logs before confirming your record. Reverse only provisional effects whose corresponding observation is no longer present.

token.transfer.retracted has two versions. Version 2 replaces a provisional transfer. Version 1 replaces a version 1 token.transfer.final event. The platform sends token.transfer.final in version 2 only.

An issuance

An issuance mints new token units for a recipient. The platform also sends the token transfer events for the same movement. The issuance payload gives the source_id of the matching token.transfer.final event in transferSourceId, so you can book the movement once. Step 2a and step 2b are alternatives.

Step
Event
State
What your system does
1
asset.issuance.provisional
provisional
Record the issuance as unconfirmed.
2a
asset.issuance.final
final
Confirm the issuance. The platform sends this event after the finality depth passes the block.
2b
asset.issuance.retracted
retracted
Reverse the issuance whose evt_id is in supersedes. No asset.issuance.final event follows for the removed block.

A role grant

The platform sends a role grant only as a provisional event. It sends no final event, and no later event confirms the grant.

Step
Event
State
What your system does
1
access-control.role-granted.provisional, version 2
provisional
Record the grant as unconfirmed. Unless a retraction follows, this event is the only notice of the grant.
2, only after a chain reorganisation
access-control.role-granted.retracted, version 2
retracted
Reverse the grant whose evt_id is in supersedes.

Role revocations follow the same pattern: access-control.role-revoked.provisional pairs with access-control.role-revoked.retracted.

The platform sends the retraction only when it recorded a successful delivery of the provisional event. If your acknowledgement was lost, a chain reorganisation can cancel the event and send no retraction. Reconcile an uncertain role against the current canonical transaction receipt and its logs. Retractions states the rule.

Identity registration has a separate final confirmation. identity.registration.provisional reports the registration before chain finality. identity.status.final follows with change set to registered after finality, unless a chain reorganisation removes the observation first. If a chain reorganisation removes the registration after a recorded successful provisional delivery, identity.registration.retracted names that provisional event in supersedes. Finality confirms the reported registration status. It does not change a pending registration into an active registration.

A funding requirement

A funding requirement records funding needed by a paused write. Its events have state final although their names end in raised, resolved and expired. Each name reports one status change, and the platform sends it as final when it records that change. Step 2a and step 2b are alternatives.

Step
Event
State
What your system does
1
funding.requirement.raised
final
Track the active requirement by requirementId and arrange funding. The platform sends one raised event for each requirement.
2a
funding.requirement.resolved
final
Close the funding task for this requirement. The observed balance reached the required amount.
2b
funding.requirement.expired
final
Close the funding task for this requirement. Expiration can follow the deadline or cancellation of the last waiting write.

A requirement ends in resolved or expired, never both, because the platform changes only a requirement that is still active. No retraction event exists for a funding requirement.

A settled trade that a bust reverses

A bust is an approved reversal of a settled trade. The platform sends step 1 when the settlement transaction confirms, without waiting for chain finality. Step 2 follows only after a bust, once the reversal is complete on chain.

Step
Event
State
What your system does
1
trading-venue.trade-settled.final, and one trading-venue.trade-fee.final for each charged side
final
Book the trade as settled and book each fee.
2
trading-venue.trade-settled.retracted, and one trading-venue.trade-fee.retracted for each fee charged
retracted
Reverse the trade and each fee. supersedes names the earlier event when the platform queued it for your endpoint. Otherwise match the trade by tradeId and the fee by feeId.

Delivery failures and event state

A delivery attempt is an HTTP request for an event. A failed attempt does not make the event retracted, and retrying it keeps the same evt_id and lifecycle state. Verify the signature before processing the event, as the setup guide describes.

Return a 2xx status after processing, or for an event id you already processed. Which responses the platform retries, the attempt timeout and the three-day retry window are delivery limits, not a change to the fact's lifecycle state. The consuming reference defines them, with the receipt rules.

Reserved states

The platform reserves one value of lifecycle_state. No new event has that value. Your endpoint receives it only when a Replay resends a recalled event that DALP 3.1 stored. Acknowledge such an event and change nothing.

  • recalled: reserved for an event that withdraws an earlier delivery on purpose, as opposed to a chain reorganisation.

The event catalogue lists the reserved event names. token.transfer.pending is still a reserved name even though the live transaction.request.broadcast event uses state pending.

  • Event catalogue: the events of every domain except token sales, trading venues and XvP settlements, when the platform sends each one and what to do with it.
  • Market and settlement events: the events of token sales, trading venues and XvP settlements, when the platform sends each one and what to do with it.
  • Subscriptions: the patterns that select events, and the events the default subscriptions skip.
  • Consuming webhooks: identifiers, deduplication, ordering, retries and retraction handling.
  • Platform event: the concept page, with the figure of the lifecycle states.

Was this page helpful?