NexusGeyser API
Block Endpoints
Query X1 Blockchain blocks and block transactions
Block Endpoints
Access X1 Blockchain block data including block metadata, transactions, and historical block ranges.
Endpoints Overview
| Endpoint | Method | Description | Credits |
|---|---|---|---|
/geyser/blocks | GET | List recent blocks | 10 |
/geyser/block/:slot | GET | Get block by slot | 5 |
/geyser/blocks/latest | GET | Get latest block | 5 |
/geyser/block/:slot/transactions | GET | Get block transactions | 15 |
GET /geyser/blocks
Get a paginated list of recent blocks.
HTTP Method: GET
Endpoint: https://nexus.fortiblox.com/geyser/blocks
Authentication: API key via X-API-Key header or Authorization: Bearer header
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit | integer | No | 20 | Number of blocks to return (max 1000) |
offset | integer | No | 0 | Pagination offset for retrieving subsequent pages |
commitment | string | No | confirmed | Commitment level: processed | confirmed | finalized |
Response Fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether request succeeded |
| data | array | Array of block objects |
| data[].slot | string | Slot number (unique block identifier) |
| data[].blockhash | string | Base58-encoded blockhash |
| data[].previous_blockhash | string | Base58-encoded hash of previous block |
| data[].parent_slot | string | Parent slot number |
| data[].block_time | number | Unix timestamp of block production time |
| data[].block_height | number | Block height in blockchain |
| data[].transaction_count | number | Number of transactions in block |
| commitment | string | Commitment level used for query |
| pagination.limit | number | Limit parameter used |
| pagination.offset | number | Offset parameter used |
| meta | object | Response metadata (see Response Format section) |
Request Example
curl "https://nexus.fortiblox.com/geyser/blocks?limit=20&offset=0" \
-H "X-API-Key: $FORTIBLOX_API_KEY"const response = await fetch(
'https://nexus.fortiblox.com/geyser/blocks?limit=20&offset=0',
{
headers: {
'X-API-Key': process.env.FORTIBLOX_API_KEY
}
}
);
const data = await response.json();
if (data.success) {
data.data.forEach(block => {
console.log(`Slot ${block.slot}: ${block.transaction_count} txs`);
});
}import requests
import os
response = requests.get(
'https://nexus.fortiblox.com/geyser/blocks',
params={
'limit': 20,
'offset': 0
},
headers={'X-API-Key': os.getenv('FORTIBLOX_API_KEY')}
)
data = response.json()
if data['success']:
for block in data['data']:
print(f"Slot {block['slot']}: {block['transaction_count']} txs")Response Schema
{
"success": true,
"data": [
{
"slot": "123456789",
"blockhash": "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N",
"previous_blockhash": "8T9VrzhS4CdKHyP3c2YUB5jPq1XW9Qq5rKmX2Z4H3jkL",
"parent_slot": "123456788",
"block_time": 1699564800,
"block_height": 123456000,
"transaction_count": 1234,
"leader": "9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g"
}
],
"commitment": "confirmed",
"pagination": {
"limit": 20,
"offset": 0
},
"meta": {
"timestamp": "2025-11-24T13:36:07.656Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"cached": false,
"path": "/geyser/blocks",
"method": "GET",
"rateLimit": {
"remaining": 999,
"limit": 1000,
"reset": 1763991540
}
}
}GET /geyser/block/:slot
Get detailed information about a specific block by slot number.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slot | integer | Yes | - | Block slot number |
commitment | string | No | confirmed | Commitment level |
api-key | string | Yes | - | Your API key |
Request Example
curl "https://nexus.fortiblox.com/geyser/block/123456789?commitment=finalized&api-key=$FORTIBLOX_API_KEY"const slot = 123456789;
const response = await fetch(
`https://nexus.fortiblox.com/geyser/block/${slot}?commitment=finalized&api-key=${process.env.FORTIBLOX_API_KEY}`
);
const data = await response.json();
if (data.success) {
console.log('Block details:', data.data);
console.log(`Transactions: ${data.data.transaction_count}`);
console.log(`Leader: ${data.data.leader}`);
}import requests
import os
from datetime import datetime
slot = 123456789
response = requests.get(
f'https://nexus.fortiblox.com/geyser/block/{slot}',
params={
'commitment': 'finalized',
'api-key': os.getenv('FORTIBLOX_API_KEY')
}
)
data = response.json()
if data['success']:
block = data['data']
timestamp = datetime.fromtimestamp(block['block_time']).isoformat()
print(f"Block {block['slot']} at {timestamp}")
print(f"Transactions: {block['transaction_count']}")
print(f"Leader: {block['leader']}")Response Schema
{
"success": true,
"data": {
"slot": 123456789,
"blockhash": "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N",
"previous_blockhash": "8T9VrzhS4CdKHyP3c2YUB5jPq1XW9Qq5rKmX2Z4H3jkL",
"parent_slot": 123456788,
"block_time": 1699564800,
"block_height": 123456000,
"transaction_count": 1234,
"leader": "9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g",
"rewards": []
},
"commitment": "finalized"
}Error Response (404)
{
"success": false,
"error": "Block not found",
"slot": 999999999
}GET /geyser/blocks/latest
Get the most recent block.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
commitment | string | No | confirmed | Commitment level |
api-key | string | Yes | - | Your API key |
Request Example
curl "https://nexus.fortiblox.com/geyser/blocks/latest?commitment=confirmed&api-key=$FORTIBLOX_API_KEY"const API_KEY = process.env.FORTIBLOX_API_KEY;
const BASE_URL = 'https://nexus.fortiblox.com/geyser';
async function getLatestBlock() {
const response = await fetch(
`${BASE_URL}/blocks/latest?commitment=confirmed&api-key=${API_KEY}`
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
if (!data.success) {
throw new Error(data.error);
}
return data.data;
}
// Usage
const block = await getLatestBlock();
console.log(`Latest block: ${block.slot}`);
console.log(`Time: ${new Date(block.block_time * 1000).toISOString()}`);
console.log(`Transactions: ${block.transaction_count}`);
console.log(`Leader: ${block.leader}`);import os
import requests
from datetime import datetime
API_KEY = os.getenv('FORTIBLOX_API_KEY')
BASE_URL = 'https://nexus.fortiblox.com/geyser'
def get_latest_block():
"""Get the latest block from Geyser API"""
response = requests.get(
f'{BASE_URL}/blocks/latest',
params={
'commitment': 'confirmed',
'api-key': API_KEY
}
)
response.raise_for_status()
data = response.json()
if not data['success']:
raise Exception(data['error'])
return data['data']
# Usage
block = get_latest_block()
timestamp = datetime.fromtimestamp(block['block_time']).isoformat()
print(f"Latest block: {block['slot']}")
print(f"Time: {timestamp}")
print(f"Transactions: {block['transaction_count']}")
print(f"Leader: {block['leader']}")use reqwest;
use serde::Deserialize;
use std::env;
#[derive(Debug, Deserialize)]
struct GeyserResponse<T> {
success: bool,
data: Option<T>,
error: Option<String>,
}
#[derive(Debug, Deserialize)]
struct BlockInfo {
slot: u64,
blockhash: String,
previous_blockhash: String,
block_time: i64,
block_height: u64,
transaction_count: u32,
leader: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("FORTIBLOX_API_KEY")?;
let block = get_latest_block(&api_key).await?;
println!("Latest block: {}", block.slot);
println!("Time: {}", block.block_time);
println!("Transactions: {}", block.transaction_count);
println!("Leader: {}", block.leader);
Ok(())
}
async fn get_latest_block(
api_key: &str
) -> Result<BlockInfo, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let url = format!(
"https://nexus.fortiblox.com/geyser/blocks/latest?commitment=confirmed&api-key={}",
api_key
);
let response = client.get(&url).send().await?;
let data: GeyserResponse<BlockInfo> = response.json().await?;
if !data.success {
return Err(data.error.unwrap_or("Unknown error".into()).into());
}
Ok(data.data.unwrap())
}package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
)
type GeyserResponse struct {
Success bool `json:"success"`
Data BlockInfo `json:"data,omitempty"`
Error string `json:"error,omitempty"`
}
type BlockInfo struct {
Slot uint64 `json:"slot"`
Blockhash string `json:"blockhash"`
PreviousBlockhash string `json:"previous_blockhash"`
BlockTime int64 `json:"block_time"`
BlockHeight uint64 `json:"block_height"`
TransactionCount uint32 `json:"transaction_count"`
Leader string `json:"leader"`
}
func getLatestBlock() (*BlockInfo, error) {
apiKey := os.Getenv("FORTIBLOX_API_KEY")
url := fmt.Sprintf(
"https://nexus.fortiblox.com/geyser/blocks/latest?commitment=confirmed&api-key=%s",
apiKey,
)
// Make HTTP GET request
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// Read response body
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// Parse JSON response
var result GeyserResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
// Check for API errors
if !result.Success {
return nil, fmt.Errorf("API error: %s", result.Error)
}
return &result.Data, nil
}
func main() {
block, err := getLatestBlock()
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
// Convert Unix timestamp to readable format
blockTime := time.Unix(block.BlockTime, 0)
fmt.Printf("Latest block: %d\n", block.Slot)
fmt.Printf("Time: %s\n", blockTime.Format(time.RFC3339))
fmt.Printf("Transactions: %d\n", block.TransactionCount)
fmt.Printf("Leader: %s\n", block.Leader)
}This endpoint has a short cache TTL (5 seconds) for real-time monitoring applications.
GET /geyser/block/:slot/transactions
Get all transactions in a specific block.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
slot | integer | Yes | - | Block slot number |
limit | integer | No | 100 | Number of transactions (max 10000) |
offset | integer | No | 0 | Pagination offset |
api-key | string | Yes | - | Your API key |
Request Example
curl "https://nexus.fortiblox.com/geyser/block/123456789/transactions?limit=100&offset=0&api-key=$FORTIBLOX_API_KEY"const slot = 123456789;
const response = await fetch(
`https://nexus.fortiblox.com/geyser/block/${slot}/transactions?limit=100&offset=0&api-key=${process.env.FORTIBLOX_API_KEY}`
);
const data = await response.json();
if (data.success) {
console.log(`Block ${slot} contains ${data.data.length} transactions:`);
data.data.forEach((tx, i) => {
console.log(` ${i + 1}. ${tx.signature} - Fee: ${tx.fee} lamports`);
});
}import requests
import os
slot = 123456789
response = requests.get(
f'https://nexus.fortiblox.com/geyser/block/{slot}/transactions',
params={
'limit': 100,
'offset': 0,
'api-key': os.getenv('FORTIBLOX_API_KEY')
}
)
data = response.json()
if data['success']:
print(f"Block {slot} contains {len(data['data'])} transactions:")
for i, tx in enumerate(data['data'], 1):
print(f" {i}. {tx['signature']} - Fee: {tx['fee']} lamports")Response Schema
{
"success": true,
"data": [
{
"signature": "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7",
"slot": 123456789,
"block_time": 1699564800,
"fee": 5000,
"success": true,
"signer": "9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g",
"transaction_index": 0
}
],
"pagination": {
"limit": 100,
"offset": 0
}
}Use Cases
Block Explorer
async function getBlockDetails(slot) {
// Get block metadata
const blockRes = await fetch(
`https://nexus.fortiblox.com/geyser/block/${slot}?api-key=${process.env.FORTIBLOX_API_KEY}`
);
const block = await blockRes.json();
// Get block transactions
const txsRes = await fetch(
`https://nexus.fortiblox.com/geyser/block/${slot}/transactions?limit=1000&api-key=${process.env.FORTIBLOX_API_KEY}`
);
const txs = await txsRes.json();
return {
...block.data,
transactions: txs.data
};
}Network Monitor
async function monitorLatestBlocks() {
const response = await fetch(
`https://nexus.fortiblox.com/geyser/blocks/latest?api-key=${process.env.FORTIBLOX_API_KEY}`
);
const data = await response.json();
if (data.success) {
const block = data.data;
const blockTime = new Date(block.block_time * 1000);
const age = (Date.now() - blockTime.getTime()) / 1000;
console.log(`Latest slot: ${block.slot}`);
console.log(`Block age: ${age.toFixed(1)}s`);
console.log(`TPS: ${(block.transaction_count / 0.4).toFixed(0)}`);
}
}
// Poll every 5 seconds
setInterval(monitorLatestBlocks, 5000);Block Range Query
import requests
import os
def get_blocks_in_range(start_slot, end_slot):
"""Get all blocks in a slot range"""
blocks = []
current_slot = start_slot
while current_slot <= end_slot:
response = requests.get(
f'https://nexus.fortiblox.com/geyser/block/{current_slot}',
params={'api-key': os.getenv('FORTIBLOX_API_KEY')}
)
data = response.json()
if data['success']:
blocks.append(data['data'])
current_slot += 1
return blocks
# Get blocks from slot 100000 to 100010
blocks = get_blocks_in_range(100000, 100010)
print(f"Retrieved {len(blocks)} blocks")Best Practices
Do This
- Cache block data - Historical blocks never change
- Use finalized commitment for permanent records
- Paginate large transaction lists from blocks
- Monitor latest block to track network health
Don't Do This
- Don't poll
/blocks/latestmore than once per 5 seconds - Don't fetch all transactions from large blocks without pagination
- Don't query non-existent slots repeatedly
Next Steps
- Transaction Endpoints - Query transaction data
- Validator Endpoints - Get validator information