figma guide

Designing breach settlement payment idempotency and duplicate submission prevention UI in Figma: IDMP-*, DUP-SUB-*, and safe resubmit gates

Design breach settlement payment idempotency UI in Figma with IDMP-* keys, DUP-SUB-* collision detection, resubmit previews, and audit-safe gates across SUB-*, WAVE-REX-*, and reissue flows.

Published
Updated
Sep 25, 2026
Read time
6 min
Level
Intermediate

Quick answer

Idempotency UI stops the most expensive settlement bug: two successful bank legs for one award. Design IDMP- keys* scoped to pay_id + action (SUB-* · REX-* · REISSUE-* · RECOVERY-), DUP-SUB- collision screens when operators double-click generate or replay webhooks, and resubmit preview modals that list in-flight SUB-, clearing items (CLR-EXC-*), and open TRACE-PEND- before allowing another attempt. Treasury consoles should show “effective payment state” (not just latest button click); auditors need LOG-IDMP-* proving why a second SUB-* was blocked or intentionally superseded. Pair with ACK/NACK, re-export, void/recall, and returned payment modules. Start from the Figma guides hub and use modals, inline alerts, and Dev Mode handoff.


Who this is for

  • Product designers on disbursement flows where “Submit again” is the default fix for slow processors.
  • Engineers implementing idempotent APIs but lacking operator-visible collision UX.
  • Auditors and counsel reviewing clawback cases caused by duplicate SUB-* rather than claimant fraud.

IDMP-* key model

IdempotencyRecord — IDMP-992-8841 · scope: pay_id PAY-992-4412 · action: SUBMIT_FILE
├── Key composition (display + API):
│   ├── pay_id or batch_id · action_enum · intent_hash (FILE-NACHA-* hash or ROW-PATCH-* set)
│   ├── client_request_id (browser) · server_idempotency_key
│   └── superseded_by optional (when court-ordered replacement SUB-* allowed)
├── States:
│   ├── pending → committed | failed | superseded | blocked_duplicate
│   ├── DUP-SUB-* when second request matches committed pending leg
│   └── BLOCK-IDMP-* when void/recall or CLR-EXC-* forbids new attempt
├── Linked artifacts:
│   ├── SUB-* · SUB-ACK-* · FILE-NACHA-* ([NACHA preview](/designing-breach-settlement-payment-file-generation-and-nacha-preview-ui-in-figma/))
│   ├── WAVE-REX-* ([re-export](/designing-breach-settlement-payment-re-export-and-batch-correction-ui-in-figma/))
│   ├── REISSUE-* ([returned payment](/designing-breach-settlement-returned-payment-and-reissue-ui-in-figma/))
│   └── RECOVERY-* ([clearing exceptions](/designing-breach-settlement-ach-clearing-exception-and-settlement-failure-ui-in-figma/))
└── Audit:
    ├── LOG-IDMP-* every block/allow decision
    └── Counsel override OVR-IDMP-* rare · requires APR-PAY-* or court doc id
ActionIdempotency scopeBlock if
SUB-*FILE hash + waveSUB-ACK pending · duplicate hash
WAVE-REX-*Patched pay_id setSame patch already in flight
REISSUE-*pay_id + RET-*Prior REISSUE committed unsettled
VOID-*pay_id + SUB-*Conflicting active TRACE-*
RECOVERY- batch*recovery_plan_idOverlapping pay_ids in pending SUB-*

Verdict: Show operators the key and the blocking reason—hidden idempotency fails under shift handover.


DUP-SUB-* collision UX

DuplicateSubmission — DUP-SUB-992-033 · attempted_by: ops_user_44 · blocked_at: 2026-09-25T14:02Z
├── Header ([inline alert](/designing-inline-alerts-and-banners-in-figma/)):
│   ├── “This submission was already started” · severity=blocking
│   ├── Link to active SUB-* · SUB-ACK status · FILE-NACHA-* version
│   └── Do not offer “submit anyway” without OVR-IDMP-* path
├── Comparison table:
│   ├── Row: attempted now vs in-flight (hash · pay count · dollar)
│   ├── Highlight diff if operator changed BENE since first SUB-*
│   └── CTA: View [NACK queue](/designing-breach-settlement-payment-submission-acknowledgment-and-processor-nack-remediation-ui-in-figma/) · Open [payee correction](/designing-breach-settlement-payee-correction-and-beneficiary-update-ui-in-figma/)
├── Safe next steps (radio):
│   ├── Wait for SUB-ACK / TRACE-PEND-*
│   ├── Cancel in-flight via [void/recall](/designing-breach-settlement-stop-payment-void-and-in-flight-recall-ui-in-figma/) then new IDMP-*
│   ├── Create WAVE-REX-* for rejected subset only
│   └── Escalate to counsel (OVR-IDMP-*)
└── Footer: Copy idempotency key for support ticket · LOG-IDMP-* id

For double-click on “Generate NACHA,” disable button after first IDMP-* pending—show loading states on the wave card.


Resubmit preview modal (before second SUB-*)

ResubmitPreview — modal · trigger: RESUB-* or “Retry submission”
├── Effective payment state per pay_id:
│   ├── last SUB-* outcome · clearing_state · RET-* open?
│   ├── [GATE-PAY-*](/designing-breach-settlement-disbursement-hold-release-and-payment-gate-ui-in-figma/) · [FIN-AWD-*](/designing-breach-settlement-award-restatement-and-fin-awd-version-history-ui-in-figma/) version
│   └── Fraud FRD-* hold?
├── Idempotency section:
│   ├── New IDMP-* preview key · collision risk badge
│   ├── List pay_ids that will be skipped (already settled)
│   └── Dollar total of *new* legs only
├── Confirm checklist:
│   ├── ☑ Prior SUB-* terminal or superseded
│   ├── ☑ No duplicate FILE hash unless NACK cleared
│   ├── ☑ [PAY-VAL-*](/designing-breach-settlement-pre-export-payment-validation-and-exception-queue-ui-in-figma/) pass or OVR-EXC-*
│   └── ☑ Counsel APR-PAY-* if OVR-IDMP-*
└── Primary CTA: Commit RESUB-* · Secondary: Cancel

Use steppers when RESUB-* spans multiple operator roles (ops → counsel → treasury).


Comparison: idempotency vs fraud duplicate detection

SystemQuestion it answersUI surface
IDMP-*Did we submit twice?DUP-SUB-* · resubmit modal
FRD-*Did claimant double-claim?Fraud prevention
REC-*Does bank ledger match?Fund reconciliation
FIND-*Did QA sample fail?Post-disbursement QA

Best for: Training—idempotency is operational safety, not fraud scoring.


Integration across the payment pipeline

  1. Pre-export validation attaches intent_hash to VAL-PASS-* so SUB-* cannot drift from validated rows.
  2. Counsel approval stores APR-PAY-* id on IDMP-* when batch-level submit requires it.
  3. Bank confirm commits settlement—subsequent REISSUE-* must use new IDMP-* keys, not replay old SUB-*.
  4. Clawback links to LOG-IDMP-* to prove duplicate leg vs claimant error.
  5. Claimant timeline never displays idempotency keys—only human states from hold release notifications.

Webhook retries from processors: show read-only “duplicate webhook ignored” in SUB-ACK detail with matching IDMP-* receipt id.


Handoff checklist (Dev Mode)

  • IdempotencyRecord — idmp_id (IDMP-*), scope_type_enum, scope_id, action_enum, intent_hash, state_enum, superseded_by optional.
  • DuplicateSubmissionBlock — dup_sub_id (DUP-SUB-*), blocked_request_id, active_idmp_id, reason_code_enum.
  • IdempotencyOverride — ovr_idmp_id (OVR-IDMP-*), idmp_id, apr_pay_id or court_doc_id, reason_text.
  • IdempotencyAuditLog — log_idmp_id (LOG-IDMP-*), decision_enum, actor, correlation_id.
  • ResubmitPreview — resub_preview_id, proposed_idmp_key, pay_id_list_json, skip_list_json.

Common mistakes

MistakeWhy it hurtsFix
Idempotency only on APIOps bypass in UIDUP-SUB-* screens
Key = pay_id aloneCollides SUB vs REISSUEaction_enum in key
“Submit anyway” buttonDouble payOVR-IDMP-* only
No intent_hashSame wave, changed rowsFILE hash / patch set
Hide in-flight SUB-*Repeat clicksDisable + link
Webhook retries create SUB-*Ghost attemptsProcessor id on IDMP-*
Supersede without auditCourt discovery gapLOG-IDMP-* + doc id
Claimant-triggered resubmitFraud vectorAdmin-only RESUB-*

  1. Add IDMP- badge* on every SUB-* and WAVE-REX-* row in treasury tables.
  2. Design DUP-SUB- as blocking modal*—not toast— with safe next-step radios.
  3. Build resubmit preview into NACK remediation RESUB-* path.
  4. Wire OVR-IDMP- to counsel queue* with APR-PAY-* attachment requirement.
  5. Document public_copy_key rules so portals never leak technical keys.

FAQ

Same FILE-NACHA-* hash submitted twice?

Block with DUP-SUB-* unless first SUB-* failed with FILE-NACK-* and RESUB-* policy allows supersede.

WAVE-REX-* vs full new SUB-*?

REX uses patch intent_hash · full SUB-* uses whole-file hash—preview must show non-overlapping pay_ids.

Returned payment reissue idempotency?

New IDMP- per REISSUE-** · block if prior REISSUE still in clearing (CLR-EXC-*).

Partial SUB-ACK and IDMP-*?

One IDMP- per SUB-** · partial outcomes split pay_id states—do not mint second SUB-* for accepted rows.

OVR-IDMP-* when is it allowed?

Court order · processor duplicate file acceptance · documented VOID-* completion—never for operator convenience alone.


Next steps

Share on X

§ Keep reading

Related guides.