Skip to main content

Lifecycle

Tesouro tracks accepted transfers through two states: Hard failures at initial submission return a 4xx and no transfer record is created — the caller never sees a “failed transfer” object in the list. A transfer’s state is what Tesouro has observed from the upstream banking core. Because ACH returns can land days after a transfer first appears COMPLETED, surface SUBMITTED rather than COMPLETED to the business customer until the return window for ACH has closed. Tesouro does not currently surface ACH returns as a separate status — partners that need return-level visibility must reconcile against statements externally.

Reading transfer state

Read transfer state by listing the source account’s transfers:
Each entry carries the transfer’s current status and the reference it was created with:
This list call drives reconciliation. Any PENDING transfer is checked against the upstream banking core, and ACH transfers the core reports as settled are updated to COMPLETED as part of the read. RTP and FedNow transfers go through the same check, but the upstream source has no record of them, so they stay in the state they were written at acceptance. Poll the list endpoint on a cadence appropriate to the rail — same-day for ACH; every few minutes is more than enough for the real-time rails.

Idempotency

Treat the idempotencyKey as required in production. Without it, a request that times out and is retried creates a second transfer, and on RTP and FedNow that duplicate is irrevocable.
Every money-movement endpoint accepts an idempotencyKey. Submitting the same key twice with the same parameters returns the original transfer (201 Created with the original body) — useful for retrying a request after a timeout without creating a duplicate. Submitting the same key with different parameters returns 409 Conflict with errorCode: MONEY_MOVEMENT_IDEMPOTENCY_KEY_CONFLICT. Generate the key once per logical transfer attempt and reuse it across any retries for the same attempt.

Reference

Every money-movement endpoint also accepts an optional reference: a string of your own that Tesouro stores against the transfer and echoes back unchanged on the create response and on the transfers list. Use it to tie a transfer back to a record in your own system, such as an invoice number or an order id. It is limited to 40 characters. A transfer created without one reads back as null. Ledger webhooks carry the reference too, but only when Tesouro can tie the event back to your transfer. Read LEDGER_TRANSACTION before you depend on it, and reconcile against this list when correlation has to be reliable.
The reference is not unique and does not deduplicate. Two transfers can carry the same one, so a retried request that reuses a reference still creates a second transfer. Reach for the idempotencyKey to make a retry safe; reach for the reference only to correlate a transfer with your own records.