Skip to main content
POST
/
rpc
/
Trails
/
GetIntentHistory
Get Intent History
curl --request POST \
  --url https://trails-api.sequence.app/rpc/Trails/GetIntentHistory \
  --header 'Content-Type: application/json' \
  --header 'X-Access-Key: <api-key>' \
  --data '
{
  "page": {
    "column": "<string>",
    "before": 123,
    "after": 123,
    "sort": [
      {
        "column": "<string>",
        "order": "DESC"
      }
    ],
    "pageSize": 123,
    "more": true
  },
  "byProjectId": 123,
  "byOwnerAddress": "<string>"
}
'
{
  "intents": [
    {
      "intentId": "<string>",
      "status": "QUOTED",
      "expiresAt": "<string>",
      "receipt": {
        "id": 123,
        "projectId": 123,
        "intentId": "<string>",
        "status": "QUOTED",
        "ownerAddress": "<string>",
        "originChainId": 123,
        "destinationChainId": 123,
        "depositTransactionId": 123,
        "depositTransaction": {
          "id": 123,
          "intentId": "<string>",
          "chainId": 123,
          "type": "UNKNOWN",
          "context": "NONE",
          "fromAddress": "<string>",
          "toAddress": "<string>",
          "tokenAddress": "<string>",
          "tokenAmount": 123,
          "status": "UNKNOWN",
          "calldata": "<string>",
          "metaTxnId": "<string>",
          "metaTxnFeeQuote": "<string>",
          "precondition": {
            "type": "<string>",
            "chainId": 123,
            "ownerAddress": "<string>",
            "tokenAddress": "<string>",
            "minAmount": 123
          },
          "depositIntentEntry": {
            "intentSignature": "<string>",
            "feeAmount": "<string>",
            "feeToken": "<string>",
            "feeCollector": "<string>",
            "userNonce": 123,
            "deadline": 123,
            "permitSignature": "<string>",
            "permitDeadline": 123,
            "permitAmount": 123
          },
          "txnHash": "<string>",
          "txnMinedAt": "<string>",
          "statusReason": "<string>",
          "updatedAt": "<string>",
          "createdAt": "<string>"
        },
        "originTransactionId": 123,
        "originTransaction": {
          "id": 123,
          "intentId": "<string>",
          "chainId": 123,
          "type": "UNKNOWN",
          "context": "NONE",
          "fromAddress": "<string>",
          "toAddress": "<string>",
          "tokenAddress": "<string>",
          "tokenAmount": 123,
          "status": "UNKNOWN",
          "calldata": "<string>",
          "metaTxnId": "<string>",
          "metaTxnFeeQuote": "<string>",
          "precondition": {
            "type": "<string>",
            "chainId": 123,
            "ownerAddress": "<string>",
            "tokenAddress": "<string>",
            "minAmount": 123
          },
          "depositIntentEntry": {
            "intentSignature": "<string>",
            "feeAmount": "<string>",
            "feeToken": "<string>",
            "feeCollector": "<string>",
            "userNonce": 123,
            "deadline": 123,
            "permitSignature": "<string>",
            "permitDeadline": 123,
            "permitAmount": 123
          },
          "txnHash": "<string>",
          "txnMinedAt": "<string>",
          "statusReason": "<string>",
          "updatedAt": "<string>",
          "createdAt": "<string>"
        },
        "summary": {
          "intentId": "<string>",
          "status": "QUOTED",
          "ownerAddress": "<string>",
          "originChainId": 123,
          "destinationChainId": 123,
          "tradeType": "EXACT_INPUT",
          "routeProviders": [
            "AUTO"
          ],
          "originIntentAddress": "<string>",
          "originTokenAddress": "<string>",
          "originTokenAmount": 123,
          "originTokenMetadata": {
            "chainId": 123,
            "tokenAddress": "<string>",
            "name": "<string>",
            "symbol": "<string>",
            "decimals": 123,
            "logoUri": "<string>"
          },
          "destinationIntentAddress": "<string>",
          "destinationTokenMetadata": {
            "chainId": 123,
            "tokenAddress": "<string>",
            "name": "<string>",
            "symbol": "<string>",
            "decimals": 123,
            "logoUri": "<string>"
          },
          "destinationHasCallData": true,
          "destinationHasCallValue": true,
          "createdAt": "<string>",
          "expiresAt": "<string>",
          "destinationTokenAddress": "<string>",
          "destinationTokenAmount": 123,
          "destinationToAddress": "<string>",
          "memo": "<string>",
          "startedAt": "<string>",
          "finishedAt": "<string>"
        },
        "destinationTransactionId": 123,
        "destinationTransaction": {
          "id": 123,
          "intentId": "<string>",
          "chainId": 123,
          "type": "UNKNOWN",
          "context": "NONE",
          "fromAddress": "<string>",
          "toAddress": "<string>",
          "tokenAddress": "<string>",
          "tokenAmount": 123,
          "status": "UNKNOWN",
          "calldata": "<string>",
          "metaTxnId": "<string>",
          "metaTxnFeeQuote": "<string>",
          "precondition": {
            "type": "<string>",
            "chainId": 123,
            "ownerAddress": "<string>",
            "tokenAddress": "<string>",
            "minAmount": 123
          },
          "depositIntentEntry": {
            "intentSignature": "<string>",
            "feeAmount": "<string>",
            "feeToken": "<string>",
            "feeCollector": "<string>",
            "userNonce": 123,
            "deadline": 123,
            "permitSignature": "<string>",
            "permitDeadline": 123,
            "permitAmount": 123
          },
          "txnHash": "<string>",
          "txnMinedAt": "<string>",
          "statusReason": "<string>",
          "updatedAt": "<string>",
          "createdAt": "<string>"
        },
        "updatedAt": "<string>",
        "createdAt": "<string>"
      },
      "updatedAt": "<string>",
      "createdAt": "<string>"
    }
  ],
  "nextPage": {
    "column": "<string>",
    "before": 123,
    "after": 123,
    "sort": [
      {
        "column": "<string>",
        "order": "DESC"
      }
    ],
    "pageSize": 123,
    "more": true
  }
}

Overview

The GetIntentHistory endpoint provides a paginated view of intent history with detailed receipt information. This endpoint returns full IntentHistory objects that include the complete IntentReceipt for each intent, giving you comprehensive transaction data including status, timestamps, and transaction hashes.

Use Cases

  • Build comprehensive transaction history pages with full receipt details
  • Display user transaction history with complete status information
  • Create audit logs with detailed transaction information
  • Export complete transaction data for analytics
  • Build dashboards with full intent lifecycle visibility

Request Parameters

All parameters are optional:
  • page (Page): Pagination configuration
    • column (string): Column to paginate by (typically “id” or “createdAt”)
    • before (number): Cursor for previous page
    • after (number): Cursor for next page
    • sort (SortBy[]): Sorting configuration
      • column (string): Column to sort by
      • order (SortOrder): DESC or ASC
    • pageSize (number): Number of results per page (default: 20)
    • more (boolean): Indicates if more pages are available
  • byProjectId (number): Filter by project ID
  • byOwnerAddress (string): Filter by wallet address

Response

The response includes:
  • intents (IntentHistory[]): Array of intent history objects with receipts
  • nextPage (Page): Pagination cursor for the next page

IntentHistory Structure

Each IntentHistory object contains:
  • intentId (string): Unique intent identifier
  • status (IntentStatus): Current status (QUOTED, COMMITTED, EXECUTING, FAILED, SUCCEEDED, ABORTED, REFUNDED)
  • expiresAt (string): Intent expiration timestamp
  • updatedAt (string): Last update timestamp
  • createdAt (string): Creation timestamp
  • receipt (IntentReceipt): Complete receipt with transaction details

IntentReceipt Details

The receipt object includes comprehensive transaction information:
  • id (number): Internal database ID
  • intentId (string): Unique intent identifier
  • status (IntentStatus): Current status
  • ownerAddress (string): Wallet address that initiated the intent
  • originChainId (number): Source chain ID
  • destinationChainId (number): Destination chain ID
  • depositTransaction (IntentTransaction): Deposit transaction details
  • originTransaction (IntentTransaction): Origin chain transaction details
  • destinationTransaction (IntentTransaction): Destination chain transaction details
  • summary (IntentReceiptSummary): Summary with token metadata and route providers

Examples

Basic Request (First Page)

const historyResponse = await fetch(
    'https://trails-api.sequence.app/rpc/Trails/GetIntentHistory',
    {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-Access-Key': 'YOUR_ACCESS_KEY'
        },
        body: JSON.stringify({
            page: {
                pageSize: 20,
                sort: [{
                    column: 'createdAt',
                    order: 'DESC'
                }]
            }
        })
    }
);

const { intents, nextPage } = await historyResponse.json();

console.log(`Loaded ${intents.length} intents with receipts`);
intents.forEach(intent => {
    console.log(`${intent.intentId}: ${intent.status}`);
    console.log(`  Receipt status: ${intent.receipt.status}`);
    console.log(`  Origin TX: ${intent.receipt.originTransaction?.txnHash}`);
    console.log(`  Destination TX: ${intent.receipt.destinationTransaction?.txnHash}`);
});

// Check if there are more pages
if (nextPage) {
    console.log('More pages available');
}

Filter by Owner Address

const historyResponse = await fetch(
    'https://trails-api.sequence.app/rpc/Trails/GetIntentHistory',
    {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-Access-Key': 'YOUR_ACCESS_KEY'
        },
        body: JSON.stringify({
            byOwnerAddress: '0x0709CF2d5D4f3D38f5948d697fE64d7FB3639Eb1',
            page: {
                pageSize: 50,
                sort: [{ column: 'createdAt', order: 'DESC' }]
            }
        })
    }
);

const { intents } = await historyResponse.json();
console.log(`Found ${intents.length} intents for this address`);

Paginated Loading with Full Receipts

import { SortOrder, type IntentHistory, type Page } from "@0xtrails/api";

async function loadAllHistoryWithReceipts(ownerAddress: string) {
    const allIntents: IntentHistory[] = [];
    let page: Page | undefined = {
        pageSize: 50,
        sort: [{ column: 'createdAt', order: SortOrder.DESC }]
    };

    while (page) {
        const { intents, nextPage }: { intents: IntentHistory[], nextPage: Page } = await fetch(
            'https://trails-api.sequence.app/rpc/Trails/GetIntentHistory',
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Access-Key': 'YOUR_ACCESS_KEY'
                },
                body: JSON.stringify({ 
                    byOwnerAddress: ownerAddress,
                    page 
                })
            }
        ).then(r => r.json());

        allIntents.push(...intents);
        page = nextPage;

        console.log(`Loaded ${allIntents.length} intents so far...`);
    }

    return allIntents;
}

const allHistory = await loadAllHistoryWithReceipts('0x0709CF2d5D4f3D38f5948d697fE64d7FB3639Eb1');
console.log(`Total intents: ${allHistory.length}`);

Transaction History Component with Receipts

import { SortOrder, type IntentHistory, type Page } from '@0xtrails/api';
import { useState, useEffect } from 'react';

function getExplorerUrl(chainId: number, txHash: string) {
    const explorers: Record<number, string> = {
        1: 'https://etherscan.io/tx/',
        137: 'https://polygonscan.com/tx/',
        8453: 'https://basescan.org/tx/',
        42161: 'https://arbiscan.io/tx/',
        10: 'https://optimistic.etherscan.io/tx/'
    };

    return (explorers[chainId] || '') + txHash;
}

export const IntentHistoryWithReceipts = ({ ownerAddress }: { ownerAddress: string }) => {
    const [intents, setIntents] = useState<IntentHistory[]>([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        async function loadHistory() {
            try {
                const response = await fetch(
                    'https://trails-api.sequence.app/rpc/Trails/GetIntentHistory',
                    {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'X-Access-Key': 'YOUR_ACCESS_KEY'
                        },
                        body: JSON.stringify({
                            byOwnerAddress: ownerAddress,
                            page: {
                                pageSize: 20,
                                sort: [{ column: 'createdAt', order: SortOrder.DESC }]
                            }
                        })
                    }
                );

                const data = await response.json();
                setIntents(data.intents);
            } catch (error) {
                console.error('Failed to load intent history:', error);
            } finally {
                setLoading(false);
            }
        }

        loadHistory();
    }, [ownerAddress]);

    if (loading) return <div>Loading...</div>;

    return (
        <div className="intent-history">
            <h2>Transaction History</h2>

            {intents.length === 0 ? (
                <p>No transactions found</p>
            ) : (
                <ul>
                    {intents.map(intent => (
                        <li key={intent.intentId}>
                            <div>
                                <strong>{intent.intentId.slice(0, 12)}...</strong>
                                <span className={`status-${intent.status.toLowerCase()}`}>
                                    {intent.status}
                                </span>
                            </div>
                            <div>
                                Chain {intent.receipt.originChainId} → Chain {intent.receipt.destinationChainId}
                            </div>
                            {intent.receipt.summary && (
                                <div>
                                    {intent.receipt.summary.originTokenMetadata?.symbol}{' '}
                                    {intent.receipt.summary.destinationTokenMetadata?.symbol}
                                </div>
                            )}
                            <div>
                                {new Date(intent.createdAt || '').toLocaleString()}
                            </div>
                            <div className="transaction-links">
                                {intent.receipt.originTransaction?.txnHash && (
                                    <a 
                                        href={getExplorerUrl(intent.receipt.originChainId, intent.receipt.originTransaction.txnHash)}
                                        target="_blank" 
                                        rel="noopener noreferrer"
                                    >
                                        View Origin TX
                                    </a>
                                )}
                                {intent.receipt.destinationTransaction?.txnHash && (
                                    <a 
                                        href={getExplorerUrl(intent.receipt.destinationChainId, intent.receipt.destinationTransaction.txnHash)}
                                        target="_blank" 
                                        rel="noopener noreferrer"
                                    >
                                        View Destination TX
                                    </a>
                                )}
                            </div>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    );
}

Analyze Intent History

import { TrailsApi, type IntentHistory } from '@0xtrails/api'

const trailsApi = new TrailsApi('YOUR_API_KEY')

async function analyzeIntentHistory(ownerAddress: string) {
    const { intents } = await trailsApi.getIntentHistory({ 
        byOwnerAddress: ownerAddress,
        page: { pageSize: 100 }
    });

    const stats = {
        total: intents.length,
        succeeded: intents.filter((i: IntentHistory) => i.status === 'SUCCEEDED').length,
        failed: intents.filter((i: IntentHistory) => i.status === 'FAILED').length,
        aborted: intents.filter((i: IntentHistory) => i.status === 'ABORTED').length,
        refunded: intents.filter((i: IntentHistory) => i.status === 'REFUNDED').length,
        pending: intents.filter((i: IntentHistory) =>
            ['QUOTED', 'COMMITTED', 'EXECUTING'].includes(i.status)
        ).length,
        chains: [...new Set(intents.flatMap((i: IntentHistory) =>
            [i.receipt.originChainId, i.receipt.destinationChainId]
        ))],
        routeProviders: [...new Set(intents.flatMap((i: IntentHistory) => 
            i.receipt.summary?.routeProviders || []
        ))]
    };

    return stats;
}

const stats = await analyzeIntentHistory('0x0709CF2d5D4f3D38f5948d697fE64d7FB3639Eb1');
console.log('Intent History Analysis:', stats);
GetIntentHistory provides comprehensive transaction data including full receipt details, transaction hashes, and token metadata. It’s ideal for building detailed transaction history views, audit logs, and analytics dashboards.

Best Practices

  1. Use appropriate page sizes: Since responses include full receipts, use smaller page sizes (10-30) to reduce payload size
  2. Cache results: Store intent history locally to avoid refetching
  3. Filter by owner address: Always filter by owner address when possible to reduce result set
  4. Handle all status types: Account for ABORTED and REFUNDED statuses in addition to SUCCEEDED and FAILED
Always handle the case where nextPage is null, indicating no more results are available.

Next Steps

  • Use GetIntent to fetch the full intent object (not just receipt) when needed
  • Use GetIntentReceipt for single intent receipt lookups
  • Use SearchIntents to find intents by various criteria

Authorizations

X-Access-Key
string
header
required

API Key for authenticating requests, get an access key at https://trails.build and request early access

Body

application/json
page
object
byProjectId
number
byOwnerAddress
string

Response

Successful response

intents
object[]
required

[]IntentHistory

nextPage
object