# Build with AI for Sim APIs Source: https://docs.sim.dune.com/build-with-ai Build faster with Sim APIs using LLMs and AI assistants. We provide several resources to help you use LLMs and AI coding assistants to build much faster with Sim APIs. ## OpenAPI Specifications To help AI tools understand our API structure, we provide OpenAPI specifications for each of our endpoints. These files detail available parameters, request bodies, and response schemas, making them ideal for generating client code or for use in custom AI agents. You can find our OpenAPI specifications in the following directories: * EVM API specifications: [`/evm/openapi/`](https://github.com/duneanalytics/sim-docs/tree/main/evm/openapi) * SVM API specifications: [`/svm/openapi/`](https://github.com/duneanalytics/sim-docs/tree/main/svm/openapi) ## Add Docs to Cursor To integrate our documentation directly into your Cursor editor for easy reference: 1. Go to **Cursor Settings -> Indexing & Docs -> Add Doc**. 2. Enter `docs.sim.dune.com` in the URL field. 3. Provide a name (e.g., "@simdocs"). 4. Hit confirm. The documentation will sync automatically. 5. Reference Sim APIs documentation by typing `@simdocs` (or your chosen name) in your Cursor chat window. ## AI Search To ask questions about our documentation, click the **Ask AI** button in the header of the site. This opens a chat interface, powered by Mintlify, that understands natural language queries. Ask questions about endpoints, authentication, or specific data points, and it will answer you with the most relevant, accurate information. ## Use with LLMs ### Complete Documentation for LLMs For LLM applications such as custom agents, RAG systems, or any scenario requiring our complete documentation, we provide an optimized text file at [`https://docs.sim.dune.com/llms-full.txt`](https://docs.sim.dune.com/llms-full.txt). ### Per-Page Access You can get the Markdown version of any documentation page by appending `.md` to its URL. For example, `/evm/activity` becomes [`https://docs.sim.dune.com/evm/activity.md`](https://docs.sim.dune.com/evm/activity.md). Additionally, in the top-right corner of each page, you will find several options to access the page's content in LLM-friendly formats: * **Copy Page:** Copies the fully rendered content of the current page. * **View Markdown:** Provides a URL with the raw Markdown source. This is ideal for direct input into LLMs. * **Open with ChatGPT:** Instantly loads the page's content into a new session with ChatGPT. Ask questions, summarize, or generate code based on the page's content. You can also type `⌘C` or `Ctrl+C` to copy any page's Markdown content. Try it now. # Compute Units Source: https://docs.sim.dune.com/compute-units Understand how Sim bills API usage using Compute Units (CUs) and how they're calculated per endpoint. export const DefaultChainCount = ({endpoint}) => { const dataState = useState(null); const data = dataState[0]; const setData = dataState[1]; useEffect(function () { fetch("https://api.sim.dune.com/v1/evm/supported-chains", { method: "GET" }).then(function (response) { return response.json(); }).then(function (responseData) { setData(responseData); }); }, []); if (data === null) { return <>N; } if (!data.chains || !Array.isArray(data.chains)) { return <>N; } var uniqueDefaultChains = new Set(); for (var i = 0; i < data.chains.length; i++) { var chain = data.chains[i]; var hasDefaultTag = Array.isArray(chain.tags) && chain.tags.indexOf("default") !== -1; if (!hasDefaultTag) { continue; } if (endpoint !== undefined) { if (chain[endpoint] && chain[endpoint].supported === true) { uniqueDefaultChains.add(chain.name); } } else { uniqueDefaultChains.add(chain.name); } } var count = uniqueDefaultChains.size; return <>{count}; }; Compute Units (CUs) are how we measure API usage in Sim. CUs reflect the actual computational work of each API call. For example, querying Balances across 30 chains uses more CUs than querying just two chains. | Endpoint | Type | Compute Units | Default Chains (no chain\_ids) | | -------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- | | Balances (EVM & SVM) | Chain-dependent | N compute units, where N is the number of chains processed in the `chain_ids` query parameter after tag expansion | {} | | Balances (single token sub-path) | Fixed | 1 compute unit per request. Accepts exactly one `chain_ids` value (single chain only) | - | | Collectibles | Chain-dependent | N compute units, where N is the number of chains processed in the `chain_ids` query parameter after tag expansion | {} | | DeFi Positions | Chain-dependent | 2N compute units, where N is the number of chains processed in the `chain_ids` query parameter after tag expansion | — | | Activity | Fixed | 3 compute units per request | — | | Transactions (EVM & SVM) | Fixed | 1 compute unit per request | — | | Token Info | Fixed | 2 compute units per request, even though `chain_ids` is required | — | | Token Holders | Fixed | 2 compute units per request | — | | Subscriptions | Event-based | 1 compute unit per event sent to your webhook. Note that a single webhook payload can contain multiple events. | — | ## How CUs work For chain-dependent endpoints, CU equals the number of distinct chains the request processes. If you pass tags (like `default`, `mainnet`, or `testnet`) via `chain_ids`, we expand them to specific chains before computing CU. If you omit `chain_ids` in the Collectibles or Balances endpoints, the endpoint uses its default chain set. CU equals the size of that set at request time, currently {} for Balances and {} for Collectibles, and may change as Sim adds more chains. For fixed endpoints, each request consumes exactly specified number of compute units regardless of how many chains you query or what parameters you provide. ## Chain selection and tags Chain count is computed after we expand any tags you pass. To keep CU predictable over time, specify explicit `chain_ids` (EVM). If you use tags like `default` or `mainnet`, we expand them to specific chains at request time. Tags can grow as we add more networks. Pin chains explicitly to keep CU stable. See [Supported Chains](/evm/supported-chains#tags). ## Examples Use `?chain_ids=1,8453,137` to process three chains. This consumes three CUs. Omitting `chain_ids` uses the endpoint's chains tagged `default`. CU equals the size of that set at request time ({} as of now, and subject to change). See [Supported Chains](/evm/supported-chains#tags). Passing `?chain_ids=mainnet` expands to all supported mainnet chains for the endpoint. CU equals the expanded chain count. Each request consumes 1 CU and must specify exactly one chain via `chain_ids`. Omitting `chain_ids` uses the endpoint's chains tagged `default`. CU equals the size of that set at request time ({} as of now, and subject to change). Activity uses a fixed-cost model. Each request consumes the same CU regardless of chains queried. Token Info is fixed-cost per request, even though `chain_ids` is required. CU does not scale with the number of chains. Each event sent to your webhook consumes 1 CU. A single webhook payload may contain multiple events, resulting in multiple CUs per webhook delivery. ## FAQs For chain-dependent endpoints, count the chains you include (after any tag expansion). For fixed-CU endpoints, see the table at the top of the page. No. CU is based on chain count or a fixed per-request cost, not on token filtering. See [Token Filtering](/token-filtering). If you omit `chain_ids` for endpoints where it can be passed, we use the endpoint's `default` chain set, which may grow as new chains are added. Pin explicit chains to keep CU stable. Visit your Sim Dashboard. # Sim APIs vs Dune Analytics API Source: https://docs.sim.dune.com/dune-analytics-api/overview Learn about the Dune Analytics API and how it compares to Sim APIs, helping you choose the right tool for data analysis vs. realtime apps. While Sim APIs provide low-latency, realtime data for building apps, Dune also offers a separate suite of analytical APIs. Both are part of the Dune ecosystem, but they are designed for different use cases. Dive into the official documentation for the Dune Analytics API to see all available endpoints, guides, and references. ## When to Use Which API Use Sim APIs if you need low-latency app data (balances, activity, NFTs) via simple REST endpoints so your UI can react to onchain events without writing SQL. Use the [Dune Analytics API](https://docs.dune.com/api-reference/overview/introduction) if you need custom SQL for analysis, dashboards, BI/warehousing, or exporting large historical datasets. ## Core Differences | Aspect | Sim APIs | Dune Analytics API | | ------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | Data access & flexibility | Ready-made realtime REST endpoints optimized for apps. | Run custom SQL across Dune’s dataset.
Connect with the DuneSQL Trino connector. | | Performance & latency | Very low latency for realtime experiences. | Built for analytical workloads.
Queries may take seconds to minutes. | | Primary use cases | Wallets, activity feeds, DeFi dashboards, onchain agents. | Market research and internal dashboards.
BI integration such as PowerBI and Metabase, plus CSV exports. | ## What You Get with the Dune Analytics API The [Dune Analytics API](https://docs.dune.com/api-reference/overview/introduction) offers a unique set of capabilities tailored for deep data analysis and custom queries. Here are some of the powerful features you can leverage that differ from Sim APIs. Programmatically run your Dune queries. Fetch exactly the data you need in your preferred format. Connect through the DuneSQL Trino connector. Use tools such as PowerBI, Metabase, DBeaver, and notebooks. Push query results to your endpoints on a custom schedule using webhooks. Upload your datasets to Dune and join them with onchain data in SQL. Enrich analyses with your internal or off-chain information. # Error Handling Source: https://docs.sim.dune.com/error-handling How to handle errors when using Sim APIs This guide explains how to handle errors when using Sim APIs, including common error codes, troubleshooting steps, and code examples for proper error handling. ## Error Response Format When an error occurs, Sim APIs return a JSON response with error information: ```json theme={null} { "error": "Description of what went wrong" } ``` The error property can be either `"error"` or `"message"` depending on the type of error. ## Common Error Codes | HTTP Status | Description | Troubleshooting | | ----------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------- | | 401 | Invalid or missing API key | Check that you're including the correct API key in the `X-Sim-Api-Key` header | | 400 | Malformed request | Verify the address format and other parameters in your request | | 402 | Compute units quota exceeded | You are out of compute units. Please contact sales to upgrade your plan: [sales@dune.com](mailto:sales@dune.com) | | 404 | Resource not found | Verify the endpoint URL and resource identifiers | | 429 | Too many requests | Implement backoff strategies and consider upgrading your plan if you consistently hit limits | | 500 | Server-side error | Retry the request after a short delay; if persistent, contact support | ## Handling Errors in Code Here are examples of how to properly handle errors in different programming languages: ```javascript theme={null} fetch('https://api.sim.dune.com/v1/evm/balances/0xd8da6bf26964af9d7eed9e03e53415d37aa96045', { method: 'GET', headers: {'X-Sim-Api-Key': 'YOUR_API_KEY'} }) .then(response => { if (!response.ok) { return response.json().then(err => { const errorMessage = err.error || err.message || response.statusText; throw new Error(`API error: ${errorMessage}`); }); } return response.json(); }) .then(data => { console.log('Success:', data); // Process your data here }) .catch(err => { console.error('Error fetching balances:', err); // Handle error appropriately in your application // e.g., show user-friendly message, retry, or fallback behavior }); ``` ```python theme={null} import requests import time def get_balances(address, api_key, max_retries=3): url = f"https://api.sim.dune.com/v1/evm/balances/{address}" headers = {"X-Sim-Api-Key": api_key} for attempt in range(max_retries): try: response = requests.get(url, headers=headers) response.raise_for_status() # Raises an exception for 4XX/5XX responses return response.json() except requests.exceptions.HTTPError as err: status_code = err.response.status_code error_data = {} try: error_data = err.response.json() except: pass # Get error message from either 'error' or 'message' property error_message = error_data.get('error') or error_data.get('message', 'Unknown error') print(f"HTTP Error {status_code}: {error_message}") # Handle specific error codes if status_code == 429: # Rate limit exceeded wait_time = min(2 ** attempt, 60) # Exponential backoff print(f"Rate limit exceeded. Retrying in {wait_time} seconds...") time.sleep(wait_time) continue elif status_code == 500: # Server error if attempt < max_retries - 1: wait_time = 2 ** attempt print(f"Server error. Retrying in {wait_time} seconds...") time.sleep(wait_time) continue # For other errors or if we've exhausted retries return {"error": error_message, "status_code": status_code} except requests.exceptions.RequestException as err: print(f"Request error: {err}") return {"error": "Network or connection error", "details": str(err)} return {"error": "Max retries exceeded"} # Usage result = get_balances("0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "YOUR_API_KEY") if "error" in result: print(f"Failed to get balances: {result['error']}") else: print(f"Found {len(result['balances'])} token balances") ``` ## Best Practices for Error Handling 1. **Always check for errors**: Don't assume API calls will succeed. 2. **Use HTTP status codes**: Rely on HTTP status codes rather than parsing error message strings for programmatic decisions. 3. **Implement retry logic with backoff**: For transient errors (like rate limits or server errors), implement exponential backoff. 4. **Provide meaningful error messages**: Transform API error responses into user-friendly messages. 5. **Log errors for debugging**: Maintain detailed logs of API errors for troubleshooting. 6. **Implement fallbacks**: When possible, have fallback behavior when API calls fail. ## Debugging Tips If you're experiencing persistent errors: 1. **Verify your API key**: Ensure it's valid and has the necessary permissions. 2. **Check request format**: Validate that your request parameters match the API specifications. 3. **Inspect full error responses**: The error message often contains specific details about what went wrong. 4. **Monitor your usage**: Check if you're approaching or exceeding rate limits. 5. **Test with cURL**: Isolate issues by testing the API directly with cURL: ```bash theme={null} curl -v -X GET "https://api.sim.dune.com/v1/evm/balances/0xd8da6bf26964af9d7eed9e03e53415d37aa96045" \ -H "X-Sim-Api-Key: YOUR_API_KEY" ``` ## Need More Help? If you're still experiencing issues after following these guidelines, please reach out through our [support channels](/support). # Activity Source: https://docs.sim.dune.com/evm/activity evm/openapi/activity.json get /v1/evm/activity/{address} View chronologically ordered transactions including native transfers, ERC20 movements, NFT transfers, and decoded contract interactions. export const SupportedChains = ({endpoint, title}) => { const dataState = useState(null); const data = dataState[0]; const setData = dataState[1]; useEffect(function () { var url = "https://api.sim.dune.com/v1/evm/supported-chains"; if (endpoint === 'defi_positions') { url = "https://api.sim.dune.com/idx/supported-chains"; } fetch(url, { method: "GET" }).then(function (response) { return response.json(); }).then(function (responseData) { setData(responseData); }); }, [endpoint]); if (data === null) { return
Loading chain information...
; } if (!data.chains) { return
No chain data available
; } var supportedChains = []; var totalChains = data.chains.length; if (endpoint !== undefined && endpoint !== 'defi_positions') { for (var i = 0; i < data.chains.length; i++) { var chain = data.chains[i]; if (chain[endpoint] && chain[endpoint].supported) { supportedChains.push(chain); } } } else { supportedChains = data.chains; } var count = supportedChains.length; var endpointName = endpoint ? endpoint.charAt(0).toUpperCase() + endpoint.slice(1).replace(/_/g, " ") : "All"; var accordionTitle = title ? title + " (" + count + ")" : "Supported Chains (" + count + ")"; return {supportedChains.map(function (chain) { return ; })}
name chain_id tags
{chain.name} {chain.chain_id} {chain.tags ? chain.tags.join(", ") : ""}
; }; Activity Sv The Activity API provides a realtime feed of onchain activity for any EVM address. The newest activity is returned first and includes the following activity types: * **send** - Outgoing transfers of tokens or native assets * **receive** - Incoming transfers of tokens or native assets * **mint** - Token minting activities * **burn** - Token burning activities * **swap** - Token swaps and exchanges * **approve** - Token approval transactions * **call** - Generic contract interactions that don't fall into the above categories Each activity includes detailed information such as: * Native token transfers * ERC20 token transfers with metadata (symbol, decimals) * ERC721 (NFT) transfers with token IDs * Contract interactions with decoded function calls Activities are mostly indexed events. There are, of course, no events for native token transfers (wen [7708](https://ethereum-magicians.org/t/eip-7708-eth-transfers-emit-a-log/20034)?). We do have a heuristic to catch very simple native token transfers, where the native token transfer is the entirety of the transaction, but unfortunately we don't currently catch native token transfers that happen within internal txns. ## Data Finality & Re-orgs Sim APIs are designed to automatically detect and handle blockchain re-organizations. We detect any potentially broken parent-child block relationships as soon as they arise and update our internal state to match the onchain state, typically within a few hundred milliseconds. This re-org handling is an automatic, non-configurable feature designed to provide the most reliable data. ## Token Filtering We include all the data needed for custom filtering in the responses, allowing you to implement your own filtering logic. For a detailed explanation of our approach, see our [Token Filtering](/token-filtering) guide. ## Compute Unit Cost The Activity endpoint has a fixed CU cost of **3** per request. See the [Compute Units](/compute-units) page for detailed information. # Add Account Activity Source: https://docs.sim.dune.com/evm/add-account-activity Expand your realtime crypto wallet by integrating a dynamic feed of onchain activity. Now that you have a wallet capable of showing realtime token balances and total portfolio value, let's enhance it by adding an *Activity* tab. A key feature for any wallet is the ability to view past transaction activity. This includes native currency transfers, ERC20 token movements, NFT transfers, and decoded interactions with smart contracts. The [Activity API](/evm/activity) provides a comprehensive, realtime feed of this onchain activity, letting you implement this functionality with a single API request across 60+ EVM chains. Access the complete source code for this wallet on GitHub Interact with the finished wallet app This guide assumes you've completed the first guide, [Build a Realtime Wallet](/evm/build-a-realtime-wallet). Your project should already be set up to fetch and display token balances. ## See It in Action You can see the activity feed in action by trying the live demo below. Click on the "Activity" tab to explore transaction history for the sample wallet: