For the complete documentation index, see llms.txt. This page is also available as Markdown.

/track - Request the status of a swap

The /track endpoint provides real-time status information for a specific transaction. It is particularly useful for tracking the progress and details of swaps, transfers, and other operations. To use this endpoint, you normally provide the chain ID and transaction hash.

For NEAR Intents swaps, you can also call the endpoint with depositAddress, which is the address the deposit transaction was sent to.

For deposit-channel routes you can also call it with depositChannelId — the meta.providerDepositChannelId returned by /v3/swap. This is the way to track a Chainflip swap whose deposit was broadcast outside your app, where you never see a transaction hash. For a complete list of chain IDs used by SwapKit you can check the table here.

Method: POST URL: https://api.swapkit.dev/track

SwapKit has it's own transaction tracking interface here: https://track.swapkit.dev/. You can also directly fill the fields by directing users to https://track.swapkit.dev/?hash={{hash}} by populating it with the respective transaction hash.

Request Body:

Field
Type
Description

hash

string

Transaction hash (required if using chainId)

chainId

string

Chain ID of the transaction (required if using hash)

depositChannelId

string

Deposit channel ID, can be used instead of hash and chainId. Use the meta.providerDepositChannelId returned by /v3/swap. Needed for Chainflip when the deposit was broadcast without a wallet connection, so no hash is available.

depositAddress

string

Deposit address used to swap with NEAR Intents, can be used instead of hash and chainId

block

number

Block number. Required for Polkadot.

routeId

string

The routeId of the /v3/quote route this transaction executed. Pass it on /track calls until the response contains a parsed transaction, to enable realized-slippage reporting on completion. Best-effort: quote data expires. Send it on the first call, right after broadcast.

Provide exactly one of: hash + chainId, depositChannelId, or depositAddress. routeId is not one of those identifiers — it is additive, and is passed alongside whichever one you use.

Example Requests:

hash and chainId
curl -X 'POST' \
  'https://api.swapkit.dev/track' \
  -H 'Content-Type: application/json' \
  -H "x-api-key: YOUR_API_KEY_HERE" \
  -d '{
  "hash": "0x1890aba1c0b25126892af2ab09f5c1bba75adefc47918a96ea498764ab643ce9",
  "chainId": "1",
  "routeId": "eed91159-86bd-4674-9558-48f7e4f8bac0"
}'
depositAddress
depositChannelId

Response

The response contains detailed information about the transaction status, type, and associated metadata. It also includes the array "legs" which represent the different stages or components of the transaction.

Response Fields:

Field
Type
Description

chainId

string

The chain ID where the transaction occurred.

hash

string

The transaction hash.

block

number

The block number where the transaction was included.

type

string

The type of the transaction (e.g., swap, token_transfer).

status

string

The transaction status (e.g., completed). See below for more details.

trackingStatus

string

The finer-grained phase of the transaction. Optional. See Tracking status.

fromAsset

string

The asset being sent.

fromAmount

string

The amount of fromAsset that was actually deposited.

fromAddress

string

The address sending the asset.

toAsset

string

The asset being received.

toAmount

string

The amount of toAsset.

toAddress

string

The recipient address.

finalisedAt

number

Unix timestamp in seconds at which the transaction finalised, or -1 when it hasn't finalised or the time isn't known. Always seconds — provider values reported in milliseconds or nanoseconds are normalized before you see them.

slippageTolerance

number (Optional)

Tolerance of the quote the swap committed to, in basis points. See Realized slippage.

realizedSlippageBps

number (Optional)

Realized slippage of the settled output vs the quoted expected output, in basis points. Positive means the swap settled for less than quoted. See Realized slippage.

meta

object

Metadata including images, provider info, and fees — the fees actually charged. See Realized fees. And the USD valuations amountInUsd / amountOutUsd (see USD amounts). On a refunded or partially refunded swap it also carries refundReason, the provider's own reason for the refund; absent when the provider gave none, and on swaps that were not refunded.

payload

object

Additional transaction specific data.

legs

array

Detailed breakdown of each transaction leg.


Example response:


Notes:

  • The legs array provides a detailed view of each step in the transaction process.

  • meta contains additional information, including images, the swap provider details, the fees actually charged (meta.fees), and the USD valuations (meta.amountInUsd / meta.amountOutUsd).

  • The payload may include data like evmCalldata or memo for more complex transactions.

Realized fees

meta.fees reports what the swap actually settled, as opposed to the estimates returned by /v3/quote. It uses the same schema as the quote response's fees, so a quote and its settled result can be compared entry for entry.

It appears at transaction level and on each entry of legs, and is omitted entirely — never an empty array — whenever no fee has settled yet or the provider exposes none.

One exception: NEAR's outbound echoes the quote-time withdrawal fee, since 1Click exposes no settled value. It appears only on a successful swap and is already reflected in the amount received.

Fee entry fields

Field
Type
Description

type

string

One of inbound, outbound, liquidity, network, affiliate, service.

amount

string

Fee amount, in decimal units of asset.

asset

string

Asset the fee was charged in (e.g. "BTC.BTC").

chain

string

Chain of the fee asset.

protocol

string

Provider that charged it (e.g. "CHAINFLIP").

amountBps

number

Optional. Fee in basis points — present on affiliate and service entries.

It is an array, not one bucket per type, because a single swap can pay the same type more than once. Within one provider, entries sharing a type and asset are summed. Across legs they're concatenated, not summed: an exact repeat of type + asset + protocol is dropped, while the same type and asset from different protocols both appear. inbound is the exception — see below.

Leg-level vs transaction-level

Each leg reports what that leg paid. For inbound, the transaction level reports the sum of the wallet gas and any matching ingress. On a Chainflip BTC deposit, the miner fee sits on the deposit leg, Chainflip's ingress fee sits on the swap leg, and the transaction reports the total:

Those two components merged because both were in BTC. When they're in different assets they stay separate — a Chainflip USDC deposit on Ethereum reports two inbound entries: the ingress fee in USDC and the wallet gas in ETH.

Plain transfers with no swap provider report no inbound fee — there is nothing to attribute it to. It is also omitted when the fee is zero, when the chain data doesn't expose the sender's fee (Zcash shielded sends, UTXO transactions with an unresolvable input, Tron when free bandwidth covered the cost).

USD amounts

meta.amountInUsd / meta.amountOutUsd value the amount deposited and received. Transaction-level only.

  • Positive 2-decimal string or absent — never "0". A sub-cent value rounds to zero and is therefore reported as absent, not as a misleading "0.00". Absent means "not priced", not "worth nothing"; each field resolves independently.

  • Priced at current price at track time; only live or recently-settled swaps (~1h of finalisedAt), never backfilled.

  • The first valid value stored is kept forever, even under forceUpdate. There is no settlement guard, so if you track while the swap is still pending, whatever toAmount the parser had at that moment is the value that gets frozen.

Realized slippage

On a completed swap, /track compares the settled output with the quote it was committed against. Both fields are in bps, transaction-level only (not per leg), and omitted when uncomputable.

Field
Type
Description

slippageTolerance

number (optional)

Tolerance of the quote the swap committed to, in bps.

realizedSlippageBps

number (optional)

(expected − actual) / expected in bps, rounded. Positive = received less than quoted.

  • Only on completed swaps. Either field may be absent; slippageTolerance in particular isn't available from every quote source.

  • On a partially refunded swap the value measures against the full quoted amount, so it reads as a large positive number — check trackingStatus for partially_refunded before reading it as slippage.

  • Automatic on Chainflip, NEAR, Garden, Flashnet, Jupiter and Harbor routes. On any other route, pass routeId on your /track calls until the response contains a parsed transaction — quotes expire ~5 minutes after quoting, so call right after broadcast.

Status fields

Every transaction, and every leg in its legs array, carries two status fields:

  • status — the coarse lifecycle state. Always present, a small stable set. Poll this for completion.

  • trackingStatus — the finer phase. Varies more between providers, optional in the schema, and the only place some states are reported.

Both are taken from the leg currently in flight — the first leg not yet completed, refunded or failed — so they advance as the swap moves between legs, and report the last leg once all are terminal. unknown and not_started are not terminal.

Two exceptions:

  • partially_refunded on any leg surfaces as the transaction's trackingStatus, whichever leg is in flight.

  • When the transaction's trackingStatus is refunded, its status is reported as refunded. Legs keep their own values.

Poll status and treat completed, refunded and failed as terminal. Read trackingStatus for mid-swap progress, or for the states status cannot express.

Route
status sequence
Where the swap phase is reported

Chainflip

pendingswappingcompleted

status, mapped from its SWAPPING/SENDING states

THORChain (incl. streaming), Maya, NEAR Intents, Mayan, Flashnet, Garden

pendingcompleted

trackingStatus

Harbor

pendingcompleted

not reported — trackingStatus goes inboundoutboundcompleted

Same-chain: 1inch and the other EVM aggregators, Jupiter on Solana

unknowncompleted / failed

no middle state; never reports pending

Before the deposit is seen, a cross-chain status may read not_started or unknown.

So a THORChain or NEAR swap observably goes pendingcompleted, and that is correct. To display "swapping", read legs[].trackingStatus.

Chainflip caveat. The transaction reads swapping only once the deposit leg has confirmed. That leg's status comes from our own chain parsing, so while it is still settling the transaction reads pendingtrackingStatus mempool or broadcasted on UTXO deposits, starting on EVM — even though legs[1].status already reads swapping.

Tracking status

trackingStatus reports the specific phase of the transaction. Use it for progress display, and for what status cannot express (swapping off Chainflip, partially_refunded).

Which values a route passes through depends on the provider; the set is deliberately not uniform and may grow. Keep polling status for completion — don't read an unrecognized trackingStatus as "still progressing", since dropped, reverted, replaced, retries_exceeded and parsing_error all accompany a swap that has stopped.

Known issue: a failed Flashnet swap currently reports trackingStatus: "swapping" instead of a failure state. status correctly reads failed — another reason to treat status as the source of truth for completion.

Transaction status

An important part of the response is the transaction status from the status field, which can have multiple values:

Status value
Explanation

not_started

The swap has not happened yet.

pending

Intermediate state. The transaction has been detected by the mempool but is pending block confirmation.

swapping

The swap is happening.

completed

The swap is finished.

refunded

The swap was refunded because of the slippage settings.

unknown

Catch all for other situations.

failed

The transaction failed in an inbound EVM contract.

Last updated