Flipside Docs
  • Welcome to Flipside!
    • Welcome to Flipside
    • Growth Services
    • Data
      • Choose your Flipside plan
        • Free
        • Builder
        • Pro
          • Get Started in Snowflake
          • Incremental Table Pattern
          • Copy Data from Snowflake to AWS
          • Copy Data from Snowflake to GCP
          • Copy Data from Snowflake to Azure
        • Snowflake Data Shares
          • Mounting a Snowflake Data Share
    • Earn
    • Community
  • Data
    • Flipside Data
      • Table Docs by Chain
      • Data Modeling Approach
      • Labels
        • Centralized Exchange Label Type
        • Decentralized Exchange Label Type
        • Operator Label Type
        • Chain Admin Label Type
        • Decentralized Finance Label Type
        • NonFungible Tokens Label Type
        • Games Label Type
        • Bridge Label Type
        • Decentralized Applications Label Type
        • Token Label Type
        • Flotsam Label Type
      • Tags
      • Table Freshness Targets
      • Contribute to Our Data
        • Contract Decoding & ABIs
        • How to Add Your Own Tags
        • Community Curation
          • Getting Started
            • Contribution Workflow
          • Model Standards
            • dbt Tips
          • PR Checklist
    • Data Products
      • Data Studio (SQL Analysts)
        • Get Started
          • Write/fork your first query
        • Flipside AI
        • Studio in Depth
          • Query Editor
            • Query Referencing
            • Pro Tips for Querying
            • Keyboard Shortcuts
            • Hex-to-Integer Function
          • Create a Chart
            • Advanced Visualization
          • Build a Dashboard
            • Markdown Reference
          • Team Accounts
        • Tutorials
          • How to Analyze Web3 Data
          • Video Tutorials
            • Overview of Schemas & Tables
            • Ethereum Tutorials
              • Getting Started with Decoded Ethereum Events
              • Getting Started with Ethereum Balances
              • Block Level and Daily Balances
              • Finding Centralized Exchange Flows
            • Solana Tutorials
              • Solana Schema & Tables: Video Walkthrough
              • Solana Specialty Tables: Video Walkthrough
              • Exploring Transactions in solana.events
            • THORChain Tutorials
              • THORChain Schema & Tables
              • Calculating IL for THORChain
          • More Tools & Resources
        • Get Inspired
      • LiveQuery
        • Get Started
        • LiveQuery in Depth
          • Functions
            • 🤝Partner Functions
            • 🧙‍♂️EVM Functions
              • 💡Seaport: Real-time Orders
              • 💡WETH Pool Balances
              • 💡General EVM Node Queries
            • 🤖API Functions
              • 💡Query TheGraph
              • 💡Query Defi Llama
            • ⚙️Utility Functions
              • 💡Hex Converters
              • 💡JSON RPC Request Builder
              • 💡EVM Logs Decoder
              • 💡Keccak256 Encoder
          • QuickNode Setup Guide
        • Secrets Manager
        • Get Inspired
      • Snowflake
      • API/SDK (Developers)
        • Get Started - Your first API call in < 2 min
        • SDK in Depth
          • JSON RPC methods
          • Run A Query
          • Query Results
          • Pagination
          • Sorting
          • Filtering
          • Query Seconds
          • Caching (maxAgeMinutes)
          • Rate Limits
          • Errors
          • More Examples
          • Archive
            • [ARCHIVED] JS/TS SDK
            • ShroomDK Migration Guide
            • [LEGACY] R
        • Tutorials
          • Have Questions?
        • Get Inspired
    • Insights and Tools
  • Earn
    • Flipside Earn
    • Onchain Rewards
      • Quests
    • Analyst Rewards
      • Top Dashboards
        • Top Dashboard Guidelines
        • Skill Tree
      • Ambassador Program
      • Direct to Analyst Commissions
    • Wallet Management
    • Tax Center
  • Support
    • General Support
    • Open a Ticket
      • That email doesn't look quite right
    • 🌟Product Special Releases
      • 2025
        • 2025-02-06 | EVM Blockchain Standardization
          • Table Change Overview
      • 2024
        • 2024-06-13 | Solana native and wrapped addresses
        • 2024-05-01 | Improvements to Pricing Data
          • Actions for Data Studio Users
          • Actions for API Users
          • Action for Data Share Users
    • 🗒️Release Notes
      • 2025
        • 2025-05-01 | Release Notes
        • 2025-04-17 | Release Notes
        • 2025-04-03 | Release Notes
        • 2025-03-20 | Release Notes
        • 2025-03-06 | Release Notes
        • 2025-02-20 | Release Notes
        • 2025-02-06 | Release Notes
        • 2025-01-23 | Release Notes
      • 2024
        • 2024-12-24 | Release Notes
        • 2024-12-12 | Release Notes
        • 2024-11-27 | Release Notes
        • 2024-11-14 | Release Notes
        • 2024-10-31 | Release Notes
        • 2024-10-03 | Release Notes
        • 2024-10-17 | Release Notes
        • 2024-09-19 | Release Notes
        • 2024-09-05 | Release Notes
        • 2024-08-22 | Release Notes
        • 2024-08-08 | Release Notes
        • 2024-07-25 | Release Notes
        • 2024-07-11 | Release Notes
        • 2024-06-27 | Release Notes
        • 2024-06-14 | Release Notes
        • 2024-05-30 | Release Notes
        • 2024-05-16 | Release Notes
        • 2024-05-02 | Release Notes
        • 2024-04-18 | Release Notes
        • 2024-04-05 | Release Notes
        • 2024-03-18 | Release Notes
        • 2024-03-05 | Release Notes
        • 2024-02-20 | Release Notes
        • 2024-02-05 | Release Notes
    • 📊Studio Change log
  • Flipside Community
    • Get Started
    • Ambassador Program
    • Join Our Discord
    • Join Our Guild
Powered by GitBook
On this page
  • Summary
  • Step 1: Create a Query
  • Step 2: Poll for the Status of the Query Run
  • Step 3: Get the Query Run Results

Was this helpful?

  1. Data
  2. Data Products
  3. API/SDK (Developers)
  4. SDK in Depth

JSON RPC methods

Lower-level direct HTTP access

PreviousSDK in DepthNextRun A Query

Last updated 11 months ago

Was this helpful?

To skip the walkthrough and go straight to dedicated API Documentation, .

Don't see an SDK for your language of choice? Interact directly with the API endpoints below! Want an SDK for another language, or want to create your own SDK? !

Flipside makes available the following SDKs as higher-level, more developer-friendly wrappers over the API. Examples for each SDK are available throughout the More Examples

Language
Version
Source Code (Github)

✅ Python

2.0.7

✅ JS/TypeScript

2.0.0

✅ R

0.2.2

Summary

The Query API uses an RPC interface instead of REST for its client-server communication. This is because RPC can provide more efficient communication and support for batch/multi-calls, which is useful for dashboards that have lots of queries powering them. Future functionality will make use of the RPC architecture to enable more efficient/scalable application use cases.

There are three RPC methods you must interact with to execute a query:

  1. createQueryRun: used to queue up the execution of a query.

  2. getQueryRun: used to retrieve the status of a query run.

  3. getQueryRunResults: used to retrieve the results of the query run once it has completed executing.

Step 1: Create a Query

The following call to the API will queue up the execution of a query. If results already exist the query will not be executed. The endpoint returns a token that can be plugged into the Get Query Results endpoint to retrieve your data.

curl --location -g 'https://api-v2.flipsidecrypto.xyz/json-rpc' \
--header 'Content-Type: application/json' \
--header 'x-api-key: {{api_key}}' \
--data '{
    "jsonrpc": "2.0",
    "method": "createQueryRun",
    "params": [
        {
            "resultTTLHours": 1,
            "maxAgeMinutes": 0,
            "sql": "SELECT date_trunc('\''hour'\'', block_timestamp) as hourly_datetime, count(distinct tx_hash) as tx_count from ethereum.core.fact_transactions where block_timestamp >= getdate() - interval'\''1 month'\'' group by 1 order by 1 desc",
            "tags": {
                "source": "postman-demo",
                "env": "test"
            },
            "dataSource": "snowflake-default",
            "dataProvider": "flipside"
        }
    ],
    "id": 1
}'
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("x-api-key", "{{api_key}}");

var raw = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "createQueryRun",
  "params": [
    {
      "resultTTLHours": 1,
      "maxAgeMinutes": 0,
      "sql": "SELECT date_trunc('hour', block_timestamp) as hourly_datetime, count(distinct tx_hash) as tx_count from ethereum.core.fact_transactions where block_timestamp >= getdate() - interval'1 month' group by 1 order by 1 desc",
      "tags": {
        "source": "postman-demo",
        "env": "test"
      },
      "dataSource": "snowflake-default",
      "dataProvider": "flipside"
    }
  ],
  "id": 1
});

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: raw,
  redirect: 'follow'
};

fetch("https://api-v2.flipsidecrypto.xyz/json-rpc", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));
import requests
import json

url = "https://api-v2.flipsidecrypto.xyz/json-rpc"

payload = json.dumps({
  "jsonrpc": "2.0",
  "method": "createQueryRun",
  "params": [
    {
      "resultTTLHours": 1,
      "maxAgeMinutes": 0,
      "sql": "SELECT date_trunc('hour', block_timestamp) as hourly_datetime, count(distinct tx_hash) as tx_count from ethereum.core.fact_transactions where block_timestamp >= getdate() - interval'1 month' group by 1 order by 1 desc",
      "tags": {
        "source": "postman-demo",
        "env": "test"
      },
      "dataSource": "snowflake-default",
      "dataProvider": "flipside"
    }
  ],
  "id": 1
})
headers = {
  'Content-Type': 'application/json',
  'x-api-key': '{{api_key}}'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
library(shroomDK) # imports jsonlite and httr

qtoken <- create_query_token(
query = "SELECT * FROM ethereum.core.fact_transactions LIMIT 33",
api_key = readLines("api_key.txt"), #always gitignore your api keys 
ttl = 1,
mam = 5,
data_source = "snowflake-default",
data_provider = "flipside",
api_url = "https://api-v2.flipsidecrypto.xyz/json-rpc"
)

# use body(create_query_token) to see how header and body are formed. 

Step 2: Poll for the Status of the Query Run

This endpoint takes as input a query run id returned by the createQueryRun rpc call.

curl --location -g 'https://api-v2.flipsidecrypto.xyz/json-rpc' \
--header 'Content-Type: application/json' \
--header 'x-api-key: {{api_key}}' \
--data '{
    "jsonrpc": "2.0",
    "method": "getQueryRun",
    "params": [
        {
            "queryRunId": "{{queryRunId}}"
        }
    ],
    "id": 1
}'
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("x-api-key", "{{api_key}}");

var raw = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "getQueryRun",
  "params": [
    {
      "queryRunId": "{{queryRunId}}"
    }
  ],
  "id": 1
});

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: raw,
  redirect: 'follow'
};

fetch("https://api-v2.flipsidecrypto.xyz/json-rpc", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));
import requests
import json

url = "https://api-v2.flipsidecrypto.xyz/json-rpc"

payload = json.dumps({
  "jsonrpc": "2.0",
  "method": "getQueryRun",
  "params": [
    {
      "queryRunId": "{{queryRunId}}"
    }
  ],
  "id": 1
})
headers = {
  'Content-Type': 'application/json',
  'x-api-key': '{{api_key}}'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
library(shroomDK) # imports jsonlite and httr
# see above for qtoken <- create_query_token(...)
query_id <- qtoken$result$queryRequest$queryRunId
query_status <- get_query_status(query_id, api_key)

# use body(get_query_status) to see how header and body are formed.

Every QueryRun has the following life cycle:

Once the getQueryRun has returned a state of QUERY_STATE_SUCCESS call the getQueryRunResults RPC method to retrieve the result set in Step3.

Step 3: Get the Query Run Results

This endpoint takes as input a query run id used in the previous two steps.

curl --location -g 'https://api-v2.flipsidecrypto.xyz/json-rpc' \
--header 'Content-Type: application/json' \
--header 'x-api-key: {{api_key}}' \
--data '{
    "jsonrpc": "2.0",
    "method": "getQueryRunResults",
    "params": [
        {
            "queryRunId": "{{queryRunId}}",
            "format": "csv",
            "page": {
                "number": 1,
                "size": 1
            }
        }
    ],
    "id": 1
}'
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("x-api-key", "{{api_key}}");

var raw = JSON.stringify({
  "jsonrpc": "2.0",
  "method": "getQueryRunResults",
  "params": [
    {
      "queryRunId": "{{queryRunId}}",
      "format": "csv",
      "page": {
        "number": 1,
        "size": 1
      }
    }
  ],
  "id": 1
});

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: raw,
  redirect: 'follow'
};

fetch("https://api-v2.flipsidecrypto.xyz/json-rpc", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));
import requests
import json

url = "https://api-v2.flipsidecrypto.xyz/json-rpc"

payload = json.dumps({
  "jsonrpc": "2.0",
  "method": "getQueryRunResults",
  "params": [
    {
      "queryRunId": "{{queryRunId}}",
      "format": "csv",
      "page": {
        "number": 1,
        "size": 1
      }
    }
  ],
  "id": 1
})
headers = {
  'Content-Type': 'application/json',
  'x-api-key': '{{api_key}}'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)
library(shroomDK) # imports jsonlite and httr
# see above for query_status <- get_query_status(...)

 query_state <- query_status$result$queryRun$state

# this loop is inside get_query_from_token() 

 status_check_done <- FALSE
  warn_flag <- FALSE

  while (!status_check_done) {

    query_status <- get_query_status(
      query_run_id = query_id, 
      api_key = api_key, # gitignore your API key 
      api_url = "https://api-v2.flipsidecrypto.xyz/json-rpc"
      ) # default 
    
query_state <- query_status$result$queryRun$state

    if(query_state == "QUERY_STATE_SUCCESS"){
      status_check_done <- TRUE
      next()
    } else if(query_state == "QUERY_STATE_FAILED"){
      status_check_done <- TRUE
      stop(query_status$result$queryRun$errorMessage)
    } else if(query_state == "QUERY_STATE_CANCELED"){
      status_check_done <- TRUE
      stop("This query was canceled, typically by cancel_query()")
    } else if(query_state != "QUERY_STATE_SUCCESS"){
      warning("Query in process, checking again in 5 seconds, use cancel_query() if needed.")
      Sys.sleep(5)
    }

  }

Detailed documentation on Flipside's RPC API can be .

click here
Let's talk
found by clicking here
Source Code
Source Code
Source Code