> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction Status Tracking

> Complete guide to checking cross-chain transaction statuses using the LI.FI API

# Transaction Status

This guide explains how to check the status of cross-chain and swap transactions using the `/status` endpoint provided by LI.FI.

***

## Querying the Status Endpoint

To fetch the status of a transfer, the `/status` endpoint can be queried with:

1. sending transaction hash
2. receiving transaction hash
3. transactionId

<Note>
  Only one of the above values are required and need to be passed in `txHash` param.
</Note>

### Required:

* `txHash`

### Optional:

* `fromChain`: Speeds up the request (recommended)
* `toChain`
* `bridge`

For swap transactions, set `fromChain` and `toChain` to the same value. The `bridge` parameter can be omitted.

```typescript theme={"system"}
const getStatus = async (txHash: string) => {
  const result = await axios.get('https://li.quest/v1/status', {
    params: { txHash },
  });
  return result.data;
};
```

## Sample Response

```json theme={"system"}
{
  "transactionId": "0x0959ee0fbb37a868752d7ae40b25dbfa3b7d72f499fa8386fd5f4105b18b62bd",
  "sending": {
    "txHash": "0x5862726dbc6643c6a34b3496bb15e91f11771f6756ccf83826304846bbc93c0v",
    "txLink": "https://etherscan.io/tx/0x5862726dbc6643c6a34b3496bb15e91f11771f6756ccf83826304846bbc93c0v",
    "amount": "60000000000000000000000",
    "token": {
      "symbol": "ORDS",
      "priceUSD": "0.012027801612559667"
    },
    "gasPrice": "23079962248",
    "gasUsed": "231727",
    "gasAmountUSD": "14.0296",
    "amountUSD": "721.6681",
    "includedSteps": [
      {
        "tool": "feeCollection",
        "fromAmount": "60000000000000000000000",
        "toAmount": "59820000000000000000000"
      },
      {
        "tool": "1inch",
        "fromAmount": "59820000000000000000000",
        "toAmount": "275101169247651913"
      }
    ]
  },
  "receiving": {
    "txHash": "0x2862726dbc6643c6a34b3496bb15e91f11771f6756ccf83826604846bbc93c0v",
    "amount": "275101169247651913",
    "token": {
      "symbol": "ETH",
      "priceUSD": "2623.22"
    },
    "gasAmountUSD": "14.0296",
    "amountUSD": "721.6509"
  },
  "lifiExplorerLink": "https://scan.li.fi/tx/0x5862726dbc6643c6a34b3496bb15e91f11771f6756ccf83826304846bbc93c0e",
  "fromAddress": "0x14a980237fa9797fa27c5152c496cab65e36da4f",
  "toAddress": "0x14a980237fa9797fa27c5152c496cab65e36da4f",
  "tool": "1inch",
  "status": "DONE",
  "substatus": "COMPLETED",
  "substatusMessage": "The transfer is complete.",
  "metadata": {
    "integrator": "example_integrator"
  }
}
```

***

## Quoted vs executed amounts

When LI.FI issued a quote for the transfer, `GET /v1/status` includes an optional `quote` object so you can reconcile the quote-time estimate with what actually settled.

* `quote.action` is what was requested.
* `quote.estimate` records the quoted amounts and costs (`toAmount`, `toAmountMin`, fees, gas).
* `sending` and `receiving` are the executed legs. Compare `receiving.amount` with `quote.estimate.toAmount` and `quote.estimate.toAmountMin`.

No extra query parameter is required. The field is omitted when LI.FI has no stored quote — for example the transaction never went through [`/quote`](/api-reference/get-a-quote-for-a-token-transfer) or `/stepTransaction`, it was partner-ingested, or the record predates quote persistence. Omission is not an error and does not change `status` or `substatus`.

`quote` can already appear while `status` is `PENDING`, because it is loaded from the quote-time record, not from destination settlement.

The schema lives on the [`GET /v1/status` API reference](/api-reference/check-the-status-of-a-cross-chain-transfer).

### Quote object

| Field | Description |
| - | - |
| `stepId` | Id of the quoted step. Matches `id` on the `/quote` response. |
| `tool` | Tool that was quoted. |
| `type` | Quoted step type. |
| `action` | Requested transfer (`Action`, same shape as `/quote`). |
| `estimate` | Quoted outcome (`Estimate`, including estimated `toAmount` and minimum `toAmountMin`). |
| `includedSteps` | Quoted sub-steps. Each has `tool`, `type`, `action`, and `estimate`. |
| `integrator` | Integrator the quote was issued for, when stored. |
| `gasLimit` | Gas limit of the transaction proposed at quote time (string). |
| `createdAt` | When the quote was issued (ISO 8601). |

Internal database fields are stripped and are never returned.

### Reconcile a completed transfer

1. Poll [`/status`](/api-reference/check-the-status-of-a-cross-chain-transfer) until `status` is `DONE`.
2. If `quote` is present, compare `receiving.amount` to `quote.estimate.toAmountMin` (quoted minimum) and `quote.estimate.toAmount` (quoted estimate).
3. `substatus: COMPLETED` means the transfer finished successfully. It does not mean `receiving.amount` equals `quote.estimate.toAmount`. The actual amount can differ from the quoted estimate while remaining at or above `toAmountMin`.
4. Use `PARTIAL` / `REFUNDED` together with the amounts when the outcome is not a full delivery.

### Example

Production `GET /v1/status` observed on 2026-09-14 (trimmed). Quoted `toAmount` was `377946589`; actual `receiving.amount` was `377639049`, still above `toAmountMin` `376056856`.

```bash theme={"system"}
curl "https://li.quest/v1/status?txHash=0x1f61dc6a35bdf60c1d1d5fe9bf983667c13afbc9d00d7d8d62a6720bb1aff20a&fromChain=999"
```

```json theme={"system"}
{
  "status": "DONE",
  "substatus": "COMPLETED",
  "tool": "mayan",
  "sending": {
    "txHash": "0x1f61dc6a35bdf60c1d1d5fe9bf983667c13afbc9d00d7d8d62a6720bb1aff20a",
    "amount": "378108480",
    "chainId": 999
  },
  "receiving": {
    "amount": "377639049",
    "chainId": 8453
  },
  "quote": {
    "stepId": "069e657a-5160-433e-a6bf-03264328ee0d:0",
    "tool": "mayan",
    "type": "lifi",
    "action": {
      "fromChainId": 999,
      "toChainId": 8453,
      "fromAmount": "378108480",
      "slippage": 0.005
    },
    "estimate": {
      "fromAmount": "378108480",
      "toAmount": "377946589",
      "toAmountMin": "376056856"
    },
    "includedSteps": [
      {
        "tool": "mayan",
        "type": "cross"
      }
    ],
    "integrator": "jumper.exchange",
    "gasLimit": "0x8c99c",
    "createdAt": "2025-09-15T01:32:52.376Z"
  }
}
```

```typescript theme={"system"}
const result = await axios.get('https://li.quest/v1/status', {
  params: { txHash, fromChain },
});
const actual = result.data.receiving?.amount;
const quotedMin = result.data.quote?.estimate?.toAmountMin;
const quoted = result.data.quote?.estimate?.toAmount;

if (actual && quotedMin) {
  // Amounts are integer strings in the destination token's smallest unit.
  // Use BigInt so large token amounts do not lose precision.
  const actualAmount = BigInt(actual);
  const quotedMinimum = BigInt(quotedMin);
  const varianceFromEstimate = quoted
    ? actualAmount - BigInt(quoted)
    : undefined;

  console.log({
    belowQuotedMinimum: actualAmount < quotedMinimum,
    varianceFromEstimate: varianceFromEstimate?.toString(),
  });
}
```

***

## Status Values

| Status | Description |
| - | - |
| `NOT_FOUND` | Transaction doesn't exist or not yet mined. |
| `INVALID` | Hash is not tied to the requested tool. |
| `PENDING` | Bridging is still in progress. |
| `DONE` | Transaction completed successfully. |
| `FAILED` | Bridging process failed. |

<Note>
  When LI.FI cannot find the hash, `/status` can respond with **HTTP 404** and error code `1003` (other lookup paths can still return a `NOT_FOUND` body):

  ```json theme={"system"}
  { "message": "Transaction hash '0x…' not found on chain '1'", "code": 1003 }
  ```

  Without `fromChain` the message reads `Transaction hash is not found in any chain.` Treat this response like `NOT_FOUND`: normal for the first minute or two after broadcast, a problem if it persists. See [Unknown and never-mined transaction hashes](#unknown-and-never-mined-transaction-hashes).
</Note>

***

## Substatus Definitions

### PENDING

* `WAIT_SOURCE_CONFIRMATIONS`: Waiting for source chain confirmations
* `WAIT_DESTINATION_TRANSACTION`: Waiting for destination transaction
* `BRIDGE_NOT_AVAILABLE`: Bridge API is unavailable
* `CHAIN_NOT_AVAILABLE`: Source/destination chain RPC unavailable
* `REFUND_IN_PROGRESS`: Refund in progress (if supported)
* `UNKNOWN_ERROR`: Status is indeterminate

### DONE

* `COMPLETED`: Transfer was successful
* `PARTIAL`: Only partial transfer completed (common for across, hop, stargate, amarok)
* `REFUNDED`: Tokens were refunded

### FAILED

* `NOT_PROCESSABLE_REFUND_NEEDED`: Cannot complete, refund needed
* `OUT_OF_GAS`: Transaction ran out of gas
* `SLIPPAGE_EXCEEDED`: Received amount too low
* `INSUFFICIENT_ALLOWANCE`: Not enough allowance
* `INSUFFICIENT_BALANCE`: Not enough balance
* `EXPIRED`: Transaction expired
* `UNKNOWN_ERROR`: Unknown or invalid state
* `REFUNDED`: Tokens were refunded

***

## Unknown and never-mined transaction hashes

An unknown LI.FI hash does not prove the transaction was never mined. Possible causes include indexing delay, an incorrect source chain, a pending or replaced transaction, mempool eviction, or recording a hash other than the final broadcast transaction. A dropped transaction can still be rebroadcast later.

1. Poll with backoff for a bounded window appropriate to the source chain. Elapsed time is not evidence of failure.
2. First query the original hash's receipt on the correct source chain (`eth_getTransactionReceipt` on EVM). A receipt means the original was mined, not replaced: handle a reverted source transaction as a source failure, or continue LI.FI/cross-chain reconciliation after source success. Apply your confirmation policy and account for reorgs.
3. If there is no receipt, look up the original transaction (`eth_getTransactionByHash` on EVM). If pending, do not mark it replaced. A missing transaction or an RPC error does not prove it was dropped.
4. For ordinary EVM account transactions, `eth_getTransactionCount` with `latest` can narrow the investigation, but nonce advancement can also mean the original was mined. Confirm replacement only after finding a different mined transaction on the same source chain with the same sender and nonce; a `pending` nonce does not prove inclusion. This nonce rule does not apply to non-EVM transactions or account-abstraction operation identifiers.
5. Before binding a replacement hash to the original order, verify its actual operation (recipient, value, calldata and relevant events) continues the intended transfer. Speed-ups, cancellations and changed intent can all reuse a nonce. A cancellation does not complete the cross-chain operation; do not auto-bind when the original nonce or intent is unknown.

<Warning>
  You may pause automatic polling at a duration limit, but preserve the unresolved state and transaction context for later reconciliation. Timeout, 404 and nonce advancement alone prove neither failure nor replacement and must not trigger an automatic resubmission.
</Warning>

## Reconciling by wallet

When a tracked hash is unknown but the user's funds may have moved under another hash, look up the wallet's transfers instead of the hash:

```bash theme={"system"}
curl "https://li.quest/v1/analytics/transfers?wallet=0x590b7835c489b238156e8411187f05b3f018815d&fromTimestamp=1788681600&toTimestamp=1788685200&status=ALL"
```

Use `status=ALL` to include `DONE`, `PENDING` and `FAILED`; the default is `DONE` only. These are LI.FI-indexed candidates, not complete on-chain history; an empty result does not prove no replacement exists. Example response:

```json theme={"system"}
{
  "transfers": [
    {
      "status": "DONE",
      "tool": "relaydepository",
      "sending": {
        "chainId": 1,
        "txHash": "0xab28fe3857427db9b5f74a6465d309d3be885003015c6f6d483b162845936f15",
        "amount": "1174196371374981",
        "token": { "symbol": "ETH" }
      },
      "receiving": {
        "chainId": 4663,
        "txHash": "0xb568d4796d81f6f03f6e8b143175390c891a20d7372b79959c5e5c0f4ae54f3a"
      }
    }
  ]
}
```

Chain pair, amount and timing only narrow candidates; they do not establish identity. For each candidate `sending.txHash`, verify the source chain, sender, nonce, receipt and intent as above before binding it to the original order and tracking `/status?txHash=<sending.txHash>`. Optional filters include `fromChain`, `toChain` and `integrator`. See the [transfers endpoint reference](/api-reference/get-a-list-of-filtered-transfers).

## Polling guidance

* `DONE` and `FAILED` are terminal. Stop polling as soon as you receive one.
* Back off: 10 seconds for the first minute, then 30 seconds, then 60 seconds, and cap the total duration. Most bridges complete within the quote's `estimate.executionDuration`.
* Persistent `404` / `1003` (or `NOT_FOUND`) is not terminal evidence. Reconcile on the source chain as above; stopping automatic polling does not establish failure or replacement.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.