Recent Swaps
curl --request GET \
--url https://api.hadron.fi/pools/{address}/swapsimport requests
url = "https://api.hadron.fi/pools/{address}/swaps"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.hadron.fi/pools/{address}/swaps', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hadron.fi/pools/{address}/swaps",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.hadron.fi/pools/{address}/swaps"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.hadron.fi/pools/{address}/swaps")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hadron.fi/pools/{address}/swaps")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": [
{
"signature": "5ZVLukBf3HfmT7d9Emte1fobjhtHsjps5TXtNZboTK3di76NbVUxHsLDFuzcnyhnjYLNnVdJajKg9k5NJCs9CLCi",
"timestamp": 1773239448,
"slot": 405713180,
"direction": "buy",
"input_amount": 86476334,
"output_amount": 998378024,
"input_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"output_mint": "So11111111111111111111111111111111111111112",
"midprice_at_swap": 0.08647878072224557,
"execution_price_at_swap": 0.08662,
"base_spread_factor_at_swap": 0.9995,
"vault_x_after": 5413038034,
"vault_y_after": 515256215,
"fees": {
"protocol_fee_quote_raw": 0,
"protocol_fee_raw": 0,
"protocol_fee_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"realized_spread_quote_raw": 142136,
"realized_spread_bps": 16.44,
"protocol_fee_split": null
}
},
{
"signature": "4b76z7T6gqn5aNjvDN3eE4X9dLrdR88DNYomkugjRvExxLRrYAgumaoGbzN8NYPFXvoXaeM9bbmD6P2tp5aTT2Tn",
"timestamp": 1773239444,
"slot": 405713171,
"direction": "sell",
"input_amount": 1000000000,
"output_amount": 86347675,
"input_mint": "So11111111111111111111111111111111111111112",
"output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"midprice_at_swap": 0.08649538387544453,
"execution_price_at_swap": 0.08634768,
"base_spread_factor_at_swap": 0.9995,
"vault_x_after": 6411416058,
"vault_y_after": 428792852,
"fees": {
"protocol_fee_quote_raw": 0,
"protocol_fee_raw": 0,
"protocol_fee_mint": "So11111111111111111111111111111111111111112",
"realized_spread_quote_raw": 147709,
"realized_spread_bps": 17.08,
"protocol_fee_split": null
}
}
],
"next_cursor": "eyJpZCI6ImozZDd4a203...",
"has_more": true
}
Pools
Recent Swaps
Returns swap events for a pool, ordered newest first. Cursor-paginated — you can walk the full history of a pool by following next_cursor.
GET
/
pools
/
{address}
/
swaps
Recent Swaps
curl --request GET \
--url https://api.hadron.fi/pools/{address}/swapsimport requests
url = "https://api.hadron.fi/pools/{address}/swaps"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.hadron.fi/pools/{address}/swaps', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hadron.fi/pools/{address}/swaps",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.hadron.fi/pools/{address}/swaps"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.hadron.fi/pools/{address}/swaps")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hadron.fi/pools/{address}/swaps")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": [
{
"signature": "5ZVLukBf3HfmT7d9Emte1fobjhtHsjps5TXtNZboTK3di76NbVUxHsLDFuzcnyhnjYLNnVdJajKg9k5NJCs9CLCi",
"timestamp": 1773239448,
"slot": 405713180,
"direction": "buy",
"input_amount": 86476334,
"output_amount": 998378024,
"input_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"output_mint": "So11111111111111111111111111111111111111112",
"midprice_at_swap": 0.08647878072224557,
"execution_price_at_swap": 0.08662,
"base_spread_factor_at_swap": 0.9995,
"vault_x_after": 5413038034,
"vault_y_after": 515256215,
"fees": {
"protocol_fee_quote_raw": 0,
"protocol_fee_raw": 0,
"protocol_fee_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"realized_spread_quote_raw": 142136,
"realized_spread_bps": 16.44,
"protocol_fee_split": null
}
},
{
"signature": "4b76z7T6gqn5aNjvDN3eE4X9dLrdR88DNYomkugjRvExxLRrYAgumaoGbzN8NYPFXvoXaeM9bbmD6P2tp5aTT2Tn",
"timestamp": 1773239444,
"slot": 405713171,
"direction": "sell",
"input_amount": 1000000000,
"output_amount": 86347675,
"input_mint": "So11111111111111111111111111111111111111112",
"output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"midprice_at_swap": 0.08649538387544453,
"execution_price_at_swap": 0.08634768,
"base_spread_factor_at_swap": 0.9995,
"vault_x_after": 6411416058,
"vault_y_after": 428792852,
"fees": {
"protocol_fee_quote_raw": 0,
"protocol_fee_raw": 0,
"protocol_fee_mint": "So11111111111111111111111111111111111111112",
"realized_spread_quote_raw": 147709,
"realized_spread_bps": 17.08,
"protocol_fee_split": null
}
}
],
"next_cursor": "eyJpZCI6ImozZDd4a203...",
"has_more": true
}
Path Parameters
string
required
The pool config PDA address.
Query Parameters
integer
default:"50"
Page size — number of swaps to return per request. Maximum
200.string
Opaque pagination cursor. Omit on the first request; on subsequent requests, pass the
next_cursor value from the previous response to fetch the next page. When the server returns next_cursor: null (equivalently has_more: false), you have reached the end of the pool’s history.string
default:"mainnet-beta"
Solana cluster —
mainnet-beta or devnet.number
Only return swaps whose quote (Y) leg is at least this many raw quote atoms. The quote leg is
input_amount on a buy (Y to X) and output_amount on a sell (X to Y). For a USDC-quoted pool, 1000000 means “at least 1 USDC”. Use this to keep dust trades out of a page.integer
Only return swaps with
slot strictly greater than this value. Made for polling: remember the highest slot you have processed and pass it back on the next call to receive just the swaps that landed since. has_more: false in the response means the walk reached the bound and nothing was left out.integer | string
Only return swaps with
timestamp strictly greater than this value, compared in whole seconds (the unit the response uses), so feeding back data[0].timestamp never repeats a swap. Accepts unix seconds (1788659015) or an ISO-8601 date-time (2026-09-06T02:23:35Z); a string without a zone designator is read as UTC. Numbers of 1e12 or more are treated as unix milliseconds. Two swaps landing in the same second as your bound are excluded together; when a gapless feed matters, prefer after_slot, which is exact.How filtered pages are built. Take
min_quote_amount, after_slot and after_timestamp can be combined. The API walks the pool’s history newest-first in blocks of 200 rows and keeps the rows that pass, until it has limit of them, reaches the after_slot or after_timestamp bound, or has scanned 1,000 rows. If the scan budget runs out, the page is returned with has_more: true and a next_cursor that resumes the walk, and it may hold fewer than limit rows (even none). Cursors from filtered requests look different from unfiltered ones; both are opaque, so always pass back exactly what you received. Following a filtered cursor never repeats or skips a swap, even when new swaps arrive in between.Polling recipe (every minute, ignoring anything under 5 USDC):curl 'https://api.hadron.fi/pools/{address}/swaps?after_slot=LAST_SEEN_SLOT&min_quote_amount=5000000' \
--header 'x-api-key: YOUR_KEY'
data[0].slot from a non-empty response as the next LAST_SEEN_SLOT.Response
array
Array of swap events on this page, ordered by most recent first.
Show Swap event
Show Swap event
string
Solana transaction signature.
integer
Swap timestamp (Unix seconds).
integer
Solana slot number.
string
Swap direction —
buy (Y to X) or sell (X to Y).integer
Raw input token amount.
integer
Raw output token amount.
string
Input token mint address.
string
Output token mint address.
number
The pool midprice at the time of the swap (raw Q32-decoded value).
number
Effective execution price in Y-per-X terms, excluding the protocol fee. Directly comparable to
midprice_at_swap.number | null
The pool’s base spread factor read from the oracle at the time of the swap.
1.0 means no base spread; e.g. 0.9995 means the LP charged ≈5 bps of base spread before any inventory skew. Values above 1.0 indicate the curve was skewed in the trader’s favor (the LP gave up base spread to rebalance inventory) — this is the conceptual fee the LP is still earning even when realized_spread_quote_raw is negative. null for swaps recorded before this field was tracked.integer
Vault X balance after the swap.
integer
Vault Y balance after the swap.
object
Fee and execution quality metrics for the swap.
Show Fees
Show Fees
number
Protocol fee in raw Y (quote-side) atoms. For sell swaps (fee paid in X), converted to Y-equivalent using midprice.
number
Protocol fee in raw atoms of the fee token (the swap’s input token — X on a sell, Y on a buy). Unlike
protocol_fee_quote_raw, this is not midprice-converted.string
Mint of the fee token (equals
input_mint).number
Spread captured by the pool in raw Y (quote-side) atoms. Positive values indicate pool profit; negative values indicate the trade executed better than midprice. For buy swaps this is a Y-equivalent conversion of the X atoms the pool saved.
number
Spread captured by the pool in basis points of the trade’s notional value at midprice. Unit-independent — directly comparable across pools and directions.
array | null
Per-recipient breakdown of the protocol fee for pools whose fee routes through the fee-split sidecar.
null for pools that use the default (single) fee recipient, and for swaps recorded before this field was tracked.Amounts are exact proportional shares of protocol_fee_raw (protocol_fee_raw × ppm / Σ ppm) — they sum to protocol_fee_raw. The split ratio is captured at the swap’s slot, so it is exact even if the pool’s recipient weights change later.string | null
Cursor to pass as
?cursor=... on the next request to fetch the following page. null when there are no more swaps (end of history).boolean
true if more swaps are available beyond this page, false if this is the last page.{
"data": [
{
"signature": "5ZVLukBf3HfmT7d9Emte1fobjhtHsjps5TXtNZboTK3di76NbVUxHsLDFuzcnyhnjYLNnVdJajKg9k5NJCs9CLCi",
"timestamp": 1773239448,
"slot": 405713180,
"direction": "buy",
"input_amount": 86476334,
"output_amount": 998378024,
"input_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"output_mint": "So11111111111111111111111111111111111111112",
"midprice_at_swap": 0.08647878072224557,
"execution_price_at_swap": 0.08662,
"base_spread_factor_at_swap": 0.9995,
"vault_x_after": 5413038034,
"vault_y_after": 515256215,
"fees": {
"protocol_fee_quote_raw": 0,
"protocol_fee_raw": 0,
"protocol_fee_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"realized_spread_quote_raw": 142136,
"realized_spread_bps": 16.44,
"protocol_fee_split": null
}
},
{
"signature": "4b76z7T6gqn5aNjvDN3eE4X9dLrdR88DNYomkugjRvExxLRrYAgumaoGbzN8NYPFXvoXaeM9bbmD6P2tp5aTT2Tn",
"timestamp": 1773239444,
"slot": 405713171,
"direction": "sell",
"input_amount": 1000000000,
"output_amount": 86347675,
"input_mint": "So11111111111111111111111111111111111111112",
"output_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"midprice_at_swap": 0.08649538387544453,
"execution_price_at_swap": 0.08634768,
"base_spread_factor_at_swap": 0.9995,
"vault_x_after": 6411416058,
"vault_y_after": 428792852,
"fees": {
"protocol_fee_quote_raw": 0,
"protocol_fee_raw": 0,
"protocol_fee_mint": "So11111111111111111111111111111111111111112",
"realized_spread_quote_raw": 147709,
"realized_spread_bps": 17.08,
"protocol_fee_split": null
}
}
],
"next_cursor": "eyJpZCI6ImozZDd4a203...",
"has_more": true
}
For a pool whose protocol fee routes through the fee-split sidecar, the
fees object includes a populated protocol_fee_split (shares sum to
protocol_fee_raw):"fees": {
"protocol_fee_quote_raw": 12500,
"protocol_fee_raw": 12500,
"protocol_fee_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"realized_spread_quote_raw": 142136,
"realized_spread_bps": 16.44,
"protocol_fee_split": [
{ "recipient": "Rec1", "ppm": 700000, "amount_raw": 8750 },
{ "recipient": "Rec2", "ppm": 300000, "amount_raw": 3750 }
]
}