# Integrating Squid Intents

Integrating Squid Intents follows the same flow as a standard Squid integration. If you already have Squid integrated, the only steps are to have Squid Intents enabled on your integrator ID, poll for status with a `quoteId`, and handle the transaction request type.

Squid Intents must be enabled on your integrator ID. Reach out to the Squid team to get started.

### Route Request <a href="#route-request" id="route-request"></a>

Squid Intents uses the `/v2/route` endpoint. When Squid Intents is enabled and a route is available, it will be automatically selected.

**There are no expiry constraints** — You do not need to submit the transaction within a time window.

#### EVM Route Request Example <a href="#evm-route-request-example" id="evm-route-request-example"></a>

<a class="button secondary">Copy</a>

```
const params = {
  fromAddress: signer.address,
  fromChain: "42161",          // Arbitrum
  fromToken: usdcAddress,
  fromAmount: amount,
  toChain: "1",                // Ethereum
  toToken: nativeToken,
  toAddress: signer.address,
  quoteOnly: false,
};

// Get the route
const routeResult = await axios.post(
  "https://v2.api.squidrouter.com/v2/route",
  params,
  {
    headers: {
      "x-integrator-id": integratorId,
      "Content-Type": "application/json",
    },
  }
);

const route = routeResult.data.route;
const quoteId = route.quoteId; // Save this — required for status tracking
console.log("Quote ID:", quoteId);
```

### Transaction Request Types <a href="#transaction-request-types" id="transaction-request-types"></a>

The route response's `transactionRequest` object will include a `transaction_request_type` field that determines how to execute the transaction. There are three types:

TypeDescription

`ON_CHAIN_EXECUTION`

Standard on-chain transaction (EVM). Execute like any Squid transaction.

`DEPOSIT_ADDRESS_CALLDATA`

Deposit to the provided address with the specified calldata. Used for certain non-EVM chains.

`DEPOSIT_ADDRESS_WITH_SIGNATURE`

Submit a signed deposit to the provided address. Used for certain non-EVM chains.

### Executing the Route <a href="#executing-the-route" id="executing-the-route"></a>

#### `ON_CHAIN_EXECUTION` (EVM Transactions) <a href="#on_chain_execution-evm-transactions" id="on_chain_execution-evm-transactions"></a>

For EVM-to-EVM Squid Intents routes where `transaction_request_type` is `ON_CHAIN_EXECUTION`, execution is the same as any Squid transaction:

<a class="button secondary">Copy</a>

```
const tx = await signer.sendTransaction({
  to: route.transactionRequest.target,
  data: route.transactionRequest.data,
  value: route.transactionRequest.value,
  gasLimit: route.transactionRequest.gasLimit,
  gasPrice: route.transactionRequest.gasPrice,
});

const receipt = await tx.wait();
console.log("Transaction hash:", receipt.transactionHash);
```

#### `DEPOSIT_ADDRESS_CALLDATA` & `DEPOSIT_ADDRESS_WITH_SIGNATURE` <a href="#deposit_address_calldata-and-deposit_address_with_signature" id="deposit_address_calldata-and-deposit_address_with_signature"></a>

For certain chains, Squid Intents uses a **deposit address flow** instead of standard on-chain execution. The `transaction_request_type` field will be one of:

* `"DEPOSIT_ADDRESS_CALLDATA"` — submit a deposit to the provided address with the specified calldata
* `"DEPOSIT_ADDRESS_WITH_SIGNATURE"` — submit a signed deposit to the provided address

<a class="button secondary">Copy</a>

```
const route = routeResult.data.route;
const transactionRequest = route.transactionRequest;

// Check the type to determine the execution flow
console.log("Transaction type:", transactionRequest.transaction_request_type);
// "ON_CHAIN_EXECUTION", "DEPOSIT_ADDRESS_CALLDATA", or "DEPOSIT_ADDRESS_WITH_SIGNATURE"

// Follow the deposit instructions in the transactionRequest
// The specific fields will vary by chain and type
```

### Status Tracking <a href="#status-tracking" id="status-tracking"></a>

**Status polling is required for Squid Intents.** After executing a Squid Intent transaction, you **must** call the status API with the `quoteId` parameter. A Squid Intent transaction will fail unless status is called with `quoteId`.

#### Getting the Quote ID <a href="#getting-the-quote-id" id="getting-the-quote-id"></a>

The `quoteId` is returned at the top level of the route response:

<a class="button secondary">Copy</a>

```
{
    "route": {
        "quoteId": "6f388be5205ee044cd7fd5047a4ce72e"
    }
}
```

#### Polling for Status <a href="#polling-for-status" id="polling-for-status"></a>

<a class="button secondary">Copy</a>

```
// Function to get the status of a Coral V2 transaction
const getStatus = async (params) => {
  try {
    const result = await axios.get("https://v2.api.squidrouter.com/v2/status", {
      params: {
        transactionId: params.transactionId,
        fromChainId: params.fromChainId,
        toChainId: params.toChainId,
        quoteId: params.quoteId, // Required for Coral V2
      },
      headers: {
        "x-integrator-id": integratorId,
      },
    });
    return result.data;
  } catch (error) {
    if (error.response) {
      console.error("API error:", error.response.data);
    }
    throw error;
  }
};

// Poll for transaction completion
const updateTransactionStatus = async (txHash, quoteId) => {
  const getStatusParams = {
    transactionId: txHash,
    fromChainId: fromChainId,
    toChainId: toChainId,
    quoteId: quoteId, // Required for Coral V2
  };

  let status;
  const completedStatuses = ["success", "partial_success", "needs_gas", "not_found", "refund"];
  const maxRetries = 10;
  let retryCount = 0;

  do {
    try {
      status = await getStatus(getStatusParams);
      console.log(`Route status: ${status.squidTransactionStatus}`);
    } catch (error) {
      if (error.response && error.response.status === 404) {
        retryCount++;
        if (retryCount >= maxRetries) {
          console.error("Max retries reached. Transaction not found.");
          break;
        }
        console.log("Transaction not found. Retrying...");
        await new Promise((resolve) => setTimeout(resolve, 5000));
        continue;
      } else {
        throw error;
      }
    }

    if (!completedStatuses.includes(status.squidTransactionStatus)) {
      await new Promise((resolve) => setTimeout(resolve, 5000));
    }
  } while (!completedStatuses.includes(status.squidTransactionStatus));
};
```

### Refund Behavior <a href="#refund-behavior" id="refund-behavior"></a>

When a Squid Intent transaction fails, funds are automatically refunded on the source chain. Refunds typically complete within **\~15 minutes**.

* Funds are transferred from the `msg.sender` on the source chain
* Refunds are sent to the `order.fromAddress`, which corresponds to the `fromAddress` in the route request
* This ensures refunds go to the actual user even if the transaction was initiated through a smart contract

### Squid Intents Limitations <a href="#coral-v2-limitations" id="coral-v2-limitations"></a>

* Bitcoin and Solana support is coming soon
