Transfer / Transaction / Signature Idempotency
When using either one of these Wallet endpoints: you can optionally specify anexternalId in the request body. This can be helpful for you if you want to create an ID on your side before the request, and store it on the created entity (Transfer Request, Transaction Request, Signature Request), in the externalId field. It can also be helpful if you need to re-submit the same API call, in case a network error (or other) prevented you to get our server’s response, even if your request has actually been processed by DFNS.
How it works
- If you re-submit the same request (same url, same body, including same
externalId), then we will respond with a200response containing the entity which was already created when you submitted it for the first time. - Otherwise, if you re-use the same
externalIdto make a new request to the API (sameexternalId, but different body, or using a different wallet), the request will fail with a409(“Conflict”) response, containing a body such as:
Terminal states and externalId
Once a transfer or transaction reaches a terminal status (Confirmed, Failed, or Rejected), the externalId is permanently bound to that entity. This applies even if the transaction failed on-chain.
If you resubmit a request with the same externalId after the original request has reached a terminal state, DFNS returns the existing entity with a 200 response—it does not create a new transaction or retry the failed one.
A
Failed status does not always mean the transaction reached the blockchain. A transfer can fail on-chain (signed, broadcast, and included in a block, then reverted, for example on insufficient balance or a contract revert) or off-chain, before broadcast (for example when you abort it, or if construction or signing fails). The txHash tells the two apart: present means it was broadcast on-chain, absent means it failed off-chain.In both cases the transfer did not move your assets, so you can safely retry with a new externalId. DFNS automatically frees any nonce it reserved for the failed transfer, so your next transfer reuses it and retries are never held up.Retrying failed transfers
If a transfer fails and you need to retry, you must use a newexternalId. The original externalId cannot be reused to create a new transfer.
Recommended pattern: Append a retry suffix to your base ID to maintain traceability:
- Track all attempts related to the same logical operation
- Correlate webhook events across retries
- Maintain audit trails in your system