Delivery and ordering
Repeat deliveries are normal. A message is sent every time the dispute is committed, and plenty of commits change nothing you read. Two common ones: an agent saves an edit that only touches internal fields, or routine background work runs against an open dispute. Both bump the dispute and both produce a message whose content is identical to the last one. An open dispute can produce about one of these a day.
What we already do about it: every message carries a deterministic identity built from the dispute and the exact commit it represents, and repeated sends of the same commit are collapsed before delivery. So a repeat you receive is always a real new commit, never the same one delivered twice.
What we would ask you to do: treat disputeUuid plus occurredAt as the identity of a message. If you have already processed that pair, drop it. If the pair is new but the content matches what you last saw, it is a commit that changed nothing you care about, and ignoring it is safe.
A single action can produce more than one message. Raising one information request writes the request and then its send result, so you may receive two messages carrying the same entry. Both are valid snapshots.
Retries. A failed delivery is retried up to 8 times over roughly 28 hours. An endpoint that fails continuously for 5 days is disabled automatically.
Ordering. Messages carry no sequence number. See "Ordering and missing messages" below.
Recovery. Every message carries the full dispute state, so a message you miss is corrected by the next one for the same dispute. This covers the dispute state and every outstanding action, but not notifications: those are sent once and are not repeated. See Reading requiredActions.
Reopening mints a new dispute. Reopening through the API creates a new dispute with its own disputeUuid, so the first message for it carries NOTIFICATION_KEY_DISPUTE_RECEIVED, not investigation started.
Ordering and missing messages
Messages carry no sequence number, so they can arrive out of order and you cannot detect a gap by counting. What that costs you depends on which part of the message you are reading.
Dispute state is safe
For the state of the dispute it costs nothing. data.dispute, timeline, and every outstanding entry are a full snapshot, so the message with the newest occurredAt is the truth whatever order they arrived in. Compare occurredAt, keep the newer, discard the older. A message you miss is corrected by the next one for the same dispute.
Notifications are not
For notifications it does matter, and you should design for it.
A notifyCustomer entry appears only in the message for the change that caused it, and is never repeated. Three things follow:
- A message that is lost takes its notification with it. The next message will not carry it again.
- Nothing in the payload today lets you detect that a notification went missing.
- Two messages arriving out of order can put member comms in the wrong sequence, for example a decision reaching the member before the credit that preceded it.
Store a notifyCustomer entry as soon as you receive it, before you acknowledge the delivery, and treat sending the member's message as a separate step you can retry. That keeps a failure on your side from turning into a lost notification.
If you need to detect gaps
Tell us. Carrying a per dispute sequence number is work on our side, but it is the thing that would let you spot a missing message rather than hear about it from a member. We would rather build it than have you discover the gap in production.