Webhooks
What Yutai's webhooks send: the kinds of change they tell a distributor about, what one delivery carries, how often a failed delivery is tried again, and how a delivery is checked. The values on this page are read from Yutai's own rules when the site is built, so they cannot drift from them.
Yutai does not deliver to real endpoints yet. The deliveries it records run on simulated data, so no change reaches a real address; the rules on this page are the ones its stored deliveries already follow.
Kinds of change
Every delivery tells a distributor about one change, and every change is one kind. A distributor asks for the kinds of change it wants to hear about; the kinds Yutai's registry names:
- Tier change
tier_changed - A holder's tier changed: the credential the holder carries now names another tier.
- Benefit unlock
benefit_unlocked - A benefit opened through a tier: the benefit and the tier that opens it.
- Claim confirmation
claim_confirmed - A claim a holder made is recorded: the claim and the benefit it was made on.
- Redemption record
redemption_recorded - A redemption of a claim is recorded.
What a delivery carries
One delivery carries three facts: the event id, the kind and the payload. The bounds are the contracts' own:
eventId- The change's own id. It names one change and never changes across attempts, so you can tell a repeat from a new change. It carries 1 to 256 characters of letters, digits, dot, underscore, colon and hyphen.
kind- The kind of change the delivery tells about: one of the four above.
payload- The change's own facts as flat entries. A key carries 1 to 64 characters of letters, digits, underscore, dot and hyphen. A value is a string of up to 512 characters, a finite number, a boolean or null. At most 32 entries.
Each kind names the payload it carries, as flat entries:
{
"asOf": "2026-10-08T12:00:00.000Z",
"credentialId": "crd_01J9ZQ4V8W7X6Y5Z4A3B2C1D0E",
"holderId": "hld_01J9ZQ4V8W7X6Y5Z4A3B2C1D0E",
"previousTier": "Holder",
"tier": "Steward"
}{
"benefitId": "bft_01J9ZQ5B7C8D9E0F1G2H3J4K5M",
"tier": "Steward"
}{
"claimId": "clm_01J9ZQ6N8P9Q0R1S2T3V4W5X6Y",
"benefitId": "bft_01J9ZQ5B7C8D9E0F1G2H3J4K5M"
}{
"redemptionId": "red_01J9ZQ7P9R0S1T2V3W4X5Y6Z8A",
"claimId": "clm_01J9ZQ6N8P9Q0R1S2T3V4W5X6Y"
}Delivery rules
How a delivery reaches an endpoint:
- At least once
- A distributor may receive the same change more than once: a retry after an answer that was slow, or a redelivery. Yutai never promises exactly once.
- One delivery per change
- A redelivered change is the same delivery: Yutai keeps one delivery per change and endpoint, so a repeat answers the same delivery with the same payload. Record the event ids you have processed and answer a repeat without acting on it again.
- No order promised
- Changes can arrive in any order, and a later change can arrive before an earlier one after a retry. A distributor that needs the current state reads it from Yutai with the calls the API reference names rather than replaying deliveries in arrival order.
Retries
Each attempt answers delivered or failed: a failed answer carries the reason it failed, a delivered one carries none. A failed attempt is tried again on the schedule below; a delivered one ends the delivery.
- Attempt 1
- when the change is sent
- Attempt 2
- 1 minute later
- Attempt 3
- 5 minutes later
- Attempt 4
- 30 minutes later
- Attempt 5
- 2 hours later
A delivery that has spent its 5 attempts stays failed and is not tried again on its own. Once it is, Yutai's team can send it again by hand, at most 3 times, each named beside the operator who pressed it.
The signature
A receiver checks a delivery's signature in the Yutai-Signature header. The value carries two parts joined by a comma: t is the whole number of unix seconds the delivery was signed at, and v1 is the signature itself, 64 lowercase hex characters. For example Yutai-Signature: t=1781000000,v1=3f9a1c7e5b2d8f04a6c1e9d3b7f5a2c8e4d6b0f2a8c6e1d3f5a7b9c0e2d4f6a8.
A receiver checks the timestamp first: only a header whose t sits within 300 seconds of the receiver's own clock, either way, is fresh, so a captured delivery cannot be replayed later and pass. The signature binds the delivery's own facts, the one message:
Yutai webhook delivery
Tenant: tnt_01J9ZQ4V8W7X6Y5Z4A3B2C1D0E
Event: tier-update-1
Kind: tier_changed
Endpoint: https://hooks.example.test/yutai
Payload: {"asOf":"2026-10-08T12:00:00.000Z","credentialId":"crd_01J9ZQ4V8W7X6Y5Z4A3B2C1D0E","holderId":"hld_01J9ZQ4V8W7X6Y5Z4A3B2C1D0E","previousTier":"Holder","tier":"Steward"}The real signing key is not issued yet. Until it is, the signature a stored delivery carries is the simulated digest proof over the same message, not the header above.