Skip to main content

Documentation Index

Fetch the complete documentation index at: https://eco.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

The Routes V3 API gives you a production-grade, server-to-server integration path. Three steps: get a quote, publish + fund the intent on-chain using the encodedRoute from the quote, poll for fulfillment. For the full OpenAPI surface, see the API Reference.

0. Prerequisites

  • Source-chain RPC + a funded wallet
  • HTTP client (curl, fetch, axios)
  • Web3 library (viem, ethers)
No authentication is required. Pass an identifier as dAppID in the request body for attribution.

1. Get a quote

The V3 quote API returns the best quote ready for on-chain execution. It returns the encodedRoute you’ll pass straight to the Portal — you don’t construct the intent struct yourself.
curl -X POST https://quotes.eco.com/api/v3/quotes/single \
  -H "Content-Type: application/json" \
  -d '{
    "dAppID": "your-app",
    "quoteRequest": {
      "sourceChainID": 10,
      "destinationChainID": 8453,
      "sourceToken": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
      "destinationToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "sourceAmount": "1000000",
      "funder": "0xYourWalletAddress",
      "recipient": "0xRecipientAddress"
    }
  }'
Available quote endpoints:
EndpointUse for
POST /api/v3/quotes/singleBest single quote, ready for execution
POST /api/v3/quotes/exactInSpecify input amount, get multiple competing quotes
POST /api/v3/quotes/exactOutSpecify output amount, get quotes for required input
Response shape:
{
  data: {
    quoteResponse: {
      intentExecutionType: "SELF_PUBLISH",
      sourceChainID: number,
      destinationChainID: number,
      sourceToken: string,
      destinationToken: string,
      sourceAmount: string,            // bigint as string (reward you'll lock)
      destinationAmount: string,       // bigint as string (recipient receives)
      funder: string,
      recipient: string,
      fees: [{ name, description, token, amount }],
      deadline: number,                // unix seconds
      estimatedFulfillTimeSec: number,
      encodedRoute: string,            // ABI-encoded — pass straight to Portal
    },
    contracts: {
      sourcePortal: string,            // Portal address on source chain
      destinationPortal: string,
      prover: string,
    }
  }
}

2. Approve the reward token

Standard ERC-20 approve to contracts.sourcePortal for the reward amount (quoteResponse.sourceAmount).
import { erc20Abi } from 'viem';

const portal = quote.data.contracts.sourcePortal;
const rewardToken = quote.data.quoteResponse.sourceToken;
const rewardAmount = BigInt(quote.data.quoteResponse.sourceAmount);

const allowance = await publicClient.readContract({
  address: rewardToken,
  abi: erc20Abi,
  functionName: 'allowance',
  args: [user, portal],
});

if (allowance < rewardAmount) {
  await walletClient.writeContract({
    address: rewardToken,
    abi: erc20Abi,
    functionName: 'approve',
    args: [portal, rewardAmount],
  });
}

3. Publish + fund

Build the reward struct from the quote and call publishAndFund on the source Portal.
const reward = {
  deadline: BigInt(quote.data.quoteResponse.deadline),
  creator: user,
  prover: quote.data.contracts.prover,
  nativeAmount: 0n,
  tokens: [{ token: rewardToken, amount: rewardAmount }],
};

const tx = await walletClient.writeContract({
  address: portal,
  abi: portalAbi,
  functionName: 'publishAndFund',
  args: [
    BigInt(quote.data.quoteResponse.destinationChainID),
    quote.data.quoteResponse.encodedRoute,
    reward,
    false, // allowPartial
  ],
});

const receipt = await publicClient.waitForTransactionReceipt({ hash: tx });
// Read the IntentPublished event from receipt.logs to extract intentHash

4. Track fulfillment

curl -X POST https://quotes.eco.com/api/v3/intents/intentStatus \
  -H "Content-Type: application/json" \
  -d '{ "intentHash": "0x..." }'
Status returns:
{
  data: {
    intentHash: string,
    status: {
      status: "Pending" | "Completed",
      subStatus: "WaitingToFulfill" | "WaitingForRefund" | "Fulfilled" | "Refunded",
      subStatusMessage: string
    },
    intentCreated: { chainId, transactionHash, blockExplorerUrl },
    fulfillment?: { chainId, transactionHash, blockExplorerUrl },
    refund?: { chainId, transactionHash, blockExplorerUrl }
  }
}
Typical fulfillment: 20–40 seconds, depending on source-chain finality.

5. Refunds (if expired)

If the intent expires unfulfilled, call refund(routeHash, reward) on the source Portal to reclaim the reward tokens. Refunds are also driven by an independent permissionless service.

Custom intents with destination calls

If you need arbitrary contract calls on the destination chain (bridge AND deposit, for example), build the intent’s route.calls array yourself and call publishAndFund with a hand-built route — see Destination calls.