Skip to main content
POST https://api.trustware.io/api/v1/route-intent/:intentId/receipt After you broadcast the source transaction, commit it to its intent with this call. Trustware tracks the route from the commit through to final settlement. Commit soon after broadcast. Retries are safe, and a commit that arrives late still works. See committing late.

Path parameters

Request

Send exactly one of txHash and userOpHash. Sending neither or both returns 400 with hash_required. The request body is limited to 64 KiB. Commit the userOp hash in userOpHash as soon as the bundler accepts the userOp. You don’t need to wait for inclusion.

The Idempotency-Key header

The header is optional. A retry with the same key and a byte-identical body gets back the first response exactly: the same HTTP status and the same body, byte for byte.
  • The key must be sent once, as 1 to 255 visible ASCII characters. Anything else returns 400 with invalid_request.
  • A key is scoped to your SDK project and the intent, and is kept for 24 hours.
  • Only a final response is stored: a 200 or a final refusal. A 5xx or a retryable refusal is not stored, so a retry with the same key runs the commit again.
  • A retry with the same key while the first request is still running returns 409 with idempotency_key_in_flight. Retry shortly. A request that has held the key for 2 minutes without finishing is treated as dead, and the next request with the key takes over.
  • The same key with a body that differs in any byte returns 422 with idempotency_key_reused. A change in whitespace or property order counts.
@trustware/sdk sends the transaction hash as the key. Without a key, retries are still safe, because the hash identifies the commit.

Response

Retries

Committing the same hash again returns 200 with the same transaction_id, whatever state the receipt is in. If a commit call fails or times out, send it again with the same hash. Retry a 5xx response the same way.

Committing late

If you broadcast before expiresAt but couldn’t commit in time, commit anyway. Until /status reports "expired", Trustware handles a late commit like an on-time one. Once the intent is expired, Trustware accepts a commit only when it can see the transaction on-chain from the right payer:
  • On an EVM chain, the transaction is readable on-chain and its sender is verified as the intent’s payer.
  • On Solana, the transaction is confirmed and its fee payer is the intent’s payer.
  • For a sponsored route, the bundler has included the userOp.
If Trustware can’t see the transaction yet, you get 409 with tx_not_visible. Retry shortly.

Replaced transactions

If the wallet speeds up or replaces an EVM transaction, commit the new hash. Trustware accepts it once it can see the new transaction on-chain from the same payer and nonce. Until then you get 409 with replacement_not_visible, so retry shortly. The receipt keeps the old hash as history, and committing the old hash again returns 200. Read the current hash from GET /status: a commit response can repeat an old one, as sourceTxHash explains. A replacement is refused with not_a_replacement when Trustware can’t prove it:
  • The new transaction is visible but does not share the payer and nonce of the committed one.
  • Trustware never saw the committed transaction on-chain, so it has no nonce to compare.
  • The committed transaction is already mined.
On Solana, commit a re-signed transaction only after the first one’s blockhash has expired. Until then you get 409 with signature_still_valid, so retry shortly. Trustware accepts the new signature once it is confirmed with the intent’s payer as fee payer. Until then you get 409 with replacement_not_visible. A Solana replacement is refused with not_a_replacement when:
  • The first signature landed.
  • The new transaction’s fee payer is not the intent’s payer.
  • Trustware can’t tell when the first signature stops being able to land. It can tell when the first signature was committed through send-serialized, and for some route-built Solana transactions, which is provider dependent.
A sponsored receipt can’t be replaced. A re-bundle keeps the userOp hash, so any different hash is refused with not_a_replacement. A receipt that has reached a final status never takes a new hash. A different hash returns 409 with receipt_terminal. Build a new route.

Refusal codes

Read code, not error. The error message is for people and its wording can change. Error responses also carry request_id.
These four codes mean “retry shortly”: Every other code is final. Don’t retry the same request.

If you never commit

On some routes Trustware watches for the payment itself and commits it for you, for up to 30 minutes after expiresAt. If it has, your own commit of the same hash returns 200 with the same transaction_id. Which routes it watches is provider dependent, and it watches EVM source chains only. These are never covered:
  • Deposit-address routes.
  • Payments in a chain’s native token.
  • Routes whose transaction is a plain ERC-20 transfer call.
  • Solana routes. Pass routeIntentId to send-serialized to have Trustware commit at broadcast instead.
  • Transactions not sent from the payer address, such as a smart-account payer whose transaction a third-party bundler submits.
Don’t rely on it. A payment you don’t commit and Trustware doesn’t find is never tracked, so always commit.

Solana: commit at broadcast

If you broadcast through POST /api/v1/sdk/rpc/solana/send-serialized, add routeIntentId to its request body with the intentId. Trustware commits the returned signature at broadcast, under the same rules as this endpoint. routeIntentId needs an SDK key that also holds the intents scope, which this endpoint requires. Without it the request returns 403 with error.code set to SCOPE_NOT_ALLOWED, and the transaction is not broadcast. A failed commit never fails the broadcast response, because the transaction is already out. Commit the signature through this endpoint as well. Retries are safe.