This guide walks through a swap of 100 USDC on Base for USDC on Starknet, from quote to completion. Your app creates a secret, the user deposits, a solver locks the user’s tokens on Starknet, and your app reveals the secret so the user is paid. How Tern works explains why each step is there.

Before you start

  • Somewhere to store one secret per swap, encrypted, on your server or in the user’s app. Without the secret, a swap can’t complete and only refunds.
  • A connection to each destination chain you support (an RPC endpoint), so you can check the solver’s tokens yourself.
  • The user’s address on both chains. Refunds go to the source-chain address, so it must be one the user controls.
  • An API key, for production. You can build and test without one: see Authentication and limits.
1

Create a secret

Generate 32 random bytes with a secure random generator. This secret is what completes the swap. Tern’s API calls it the fulfillment.Its SHA-256 hash is what you share with Tern up front. The API calls it the executionCondition.
Use a new secret for every swap. Tern refuses a hash that any earlier quote used (409 condition_reused), because one revealed secret would unlock every swap that shared it.
2

Get a firm quote

When the user confirms the price, ask for a firm quote. It’s the same request as a price, plus three fields:
  • sender: the user’s address on the source chain, where any refund goes.
  • recipient: the user’s address on the destination chain.
  • executionCondition: the hash from step 1.
You can also set slippageBps: how far below the expected amount the user accepts, in case the solver has to buy the token they want. It’s 50 (0.5%) by default and at most 300 (3%). Add an Idempotency-Key header so a retried request returns the same quote.
  • id identifies this swap from now on. Store it with the secret.
  • to.amount is what the user should receive. If the quote also has to.minAmount, that’s the least they’ll receive: show both. See Amounts.
  • expiresAt is the deadline to deposit, 30 minutes from now.
  • execute is how the user deposits, in the next step.
For what to show about cost, see Fees and pricing.
3

Take the deposit

Before expiresAt, the user deposits in one of two ways.
  • EVM chains: send execute.transactions in order from sender. An approval is included only when it’s needed. USDT on Ethereum may get an extra approval of zero first, because that token requires it.
  • Starknet: send execute.calls together, as a single transaction, from sender.
Before the user signs, check that the transactions only approve the token being sold to Tern’s contract and then call it. Hard-code the address from Contract addresses.
Once you have the deposit’s transaction hash, you can send it to POST /v1/index so the status updates sooner. Tern finds the deposit either way.
4

Wait for the solver

Check the swap’s status with GET /v1/quote/{id}, or receive it through webhooks. It moves from awaiting_deposit to deposit_confirmed once the deposit is confirmed, then to in_progress once the solver has locked the user’s tokens on the destination chain.
At in_progress, move to the next step. If the status becomes refunded or expired instead, the swap is over: see If something goes wrong. Track a swap covers how often to check and what each field means.
5

Check the solver's tokens

Before you reveal the secret, confirm on the destination chain that the solver has really locked the user’s tokens. Use your own connection to the chain, not Tern’s status or a webhook: this check is what makes revealing safe.The solver locks the tokens in Tern’s escrow contract, in one or more locks tied to your hash. Check that:
  1. Every lock you count is still open, pays recipient, holds to.asset, and has at least 30 minutes before it expires.
  2. Together they hold at least to.minAmount, or to.amount if the quote has no minimum.
To find the locks, look for the escrow contract’s Prepared events that carry your hash. On EVM chains the hash is the event’s third indexed field (topics[3]), and escrows(escrowId) returns each lock’s amount and state (1 means still open). On Starknet the hash is a key of the Prepared event, and get_escrow(escrow_id) returns the same. The exact event formats are in the specification.If the solver locked less than the minimum, don’t reveal. Wait a few minutes for it to add the rest; if it doesn’t, the swap refunds.
6

Reveal the secret

Send the secret from step 1 to Tern, with an Idempotency-Key:
Tern answers 202 Accepted and pays the user on the destination chain. It runs the same checks first. If the solver’s tokens aren’t ready yet, it answers 409 destination_not_ready and does nothing: wait a few seconds and try again with the same key.Keep checking the status until it’s completed. destination.txHash is the transaction that paid the user.
Once revealed, the secret is public. Reveal it only after the checks in the previous step pass.

If something goes wrong

Next steps

Track a swap

Follow statuses and show users their swap history.

Webhooks

Get every status change sent to your server.

Refunds

Every way a swap can end without completing.

Errors

Every error and what to do about it.