Verifying a payment
Transfer statuses, finality on Solana, polling, and how to check a payment against the chain yourself.
A transfer's status tells you whether a payment landed and whether it can still be undone. This page covers each status, when a payment is safe to act on, and how to check it against the chain.
Status lifecycle
A wallet transfer, sent or received, has one of these statuses:
| Status | Meaning |
|---|---|
processing | Outbound and in flight: SDP is signing and submitting it, or waiting for the chain. signature can still be null. |
confirmed | The transaction landed in a block that a supermajority of the cluster voted for. signature and slot are set. Not yet irreversible. |
finalized | The block is finalized. Irreversible. |
failed | The transfer never reached the network, or the network rejected it. The recipient was not paid; error says why. |
POST /v1/payments/transfers waits for finality, so a successful request usually answers finalized. If the wait runs out, it answers processing, and SDP moves the transfer to confirmed, finalized or failed as the chain settles. A processing transfer that never got a signature fails after 5 minutes, unless it is waiting on a custody approval.
Inbound payments differ. A paid payment request is recorded at finalized. An observed row (from includeObserved=true) shows confirmed or failed and never finalized, because SDP rebuilds it from chain history on each read. Check its finality yourself; see Independent verification.
finalized and failed are final. Transfers that other modules create document their own lifecycle.
Finality on Solana
Act on finalized for anything irreversible: releasing custody, shipping high-value goods, posting to your general ledger. A confirmed transaction has a supermajority vote but can, rarely, still be dropped. Use it for low-stakes steps, such as a status email or a "paid" badge.
Polling cadence
SDP sends no settlement webhooks, so poll:
GET /v1/payments/transfers/{transferId}for one recorded transfer.GET /v1/payments/transfersfor a time window or one wallet's activity. See Indexing and reconciliation.
Start from these ranges:
- Active checkout (someone is watching the payment screen): every 2–5 seconds for up to a minute, then back off.
- Background reconciliation (no one is waiting): every 15–30 seconds, or on each worker tick.
- After the fact: one read when your application needs the answer, with no loop.
Every poll counts against your key's rate limit. Reads with includeObserved=true also count against their own quota of 30 a minute per API key, so spread them across your open orders.
Independent verification
Once a transfer has a signature, you can check it against the network yourself:
signature: open it on Solana Explorer, or look it up withgetSignatureStatuseson your own RPC.slot: the slot the transaction landed in.blockTime: the block's timestamp (ISO 8601). It is oftennullon transfers SDP sends;confirmedAtrecords when SDP saw the transaction land.fee: the network fee in lamports, when known.
If you run your own indexer, compare its view of each signature with SDP's status.
Failure handling
When status is failed:
- Read
errorfor the reason. - Decide whether to try again. The failed transfer stays failed, and its
Idempotency-Keyreplays the failure. To retry, send a new request with a new key; it creates a new transfer with its ownidandsignature. - Tell whoever needs to know: the merchant, the customer, your operations team.
Related
- Accept overview: payment requests and shared addresses.
- Indexing and reconciliation: list and match many transfers.
- Concepts: the transfer data model: every transfer field.