Networks drop responses. Send an Idempotency-Key header with every write, and a retry returns the first result instead of doing the work again.
Use your own id for the business action — your payout id, your refund id. The body field idempotency_key is accepted too; the header wins.

Per endpoint

Same key, different body

A retry is the same request. Reusing a key on POST /transactions with another amount, wallet, network, recipient, queue or tags is refused:
The same holds for POST /events/{name}: a key reused on the same event with other inputs or another network is refused with 409 and code: idempotency_conflict, and no workflow starts. Comparison ignores key order and treats "7" and 7 as the same value. A key is unique within your organization, not within a network. The same key sent with another network is another request, so it gets 409 idempotency_conflict too — on POST /transactions and on the same event of POST /events/{name}. Your payout id names one payout, on one network.

Lost the response?

Read the transaction by the key you sent: GET /transactions/payout-981 answers with the operation, exactly as GET /transactions/{operation_id} would.

Without a key

POST /transactions without a key still works, but every call is a new transaction. Do not retry such a call blindly. Citadel then names the transaction itself: the response carries "idempotency_key": "intent:<uuid>", a fresh UUID for every call. GET /transactions/{id} finds the transaction by that value too. It names this one transaction only; a retry with it as Idempotency-Key returns this transaction, not a new one. POST /events/{name} without a key starts the workflows anew on every call.

Retrying after a failure

A failed transaction with failure.retryable: true provably moved nothing. Submit it again with a new key — the old key keeps naming the failed attempt.