curl --request GET \
--url https://api.range.org/v2/corridors \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.range.org/v2/corridors"
headers = {"X-API-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>'}};
fetch('https://api.range.org/v2/corridors', 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.range.org/v2/corridors",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <api-key>"
],
]);
$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.range.org/v2/corridors"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
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.range.org/v2/corridors")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.range.org/v2/corridors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"items": [
{
"id": "YXJiMS8weGNhODJhNzk2",
"status": "settled",
"protocol": "cctpv2",
"time": "2026-09-23T09:43:35.000Z",
"source": {
"network": "eth",
"address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"destination": {
"network": "eth",
"address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"asset": "USDC",
"amount": "38.24",
"usd": "38.24",
"detected_fee": {
"status": "detected",
"amount": "0.12",
"usd": "0.12"
},
"match_method": "bridge_verified",
"match_confidence": 1
}
],
"meta": {
"next_cursor": "eyJpZCI6IjkxeFFlV3Z...",
"page_number": 1
}
}Cross-chain corridors between the workspace’s own Accounts
Returns the bridged movements in a period where both ends are addresses this workspace owns — money it moved between its own Accounts across networks, rather than to anyone else. These are facts, not inferences: a bridge record links the two transactions by construction, so a corridor is reported only when both of its ends resolve to owned addresses. Ownership is tested against every address the workspace owns, including the fund-holding addresses behind multisig and governance connections, not only the addresses saved on Accounts. By default only movements that arrived are returned; use the status parameter to also see ones still in transit or that failed. Supported bridge protocols: across, allbridge, axelar, cctp, cctpv2, circle-gateway, debridge, hyperlane, hyperliquid-bridge2, ibc, ibcv2, layerzero, mayan, near-intents, union, wormhole. A movement through any other bridge is not detected, and is absent rather than reported as external. The workspace is taken from the authenticated key, never from a parameter. Read-only: nothing is stored, and re-running an identical query returns an identical set.
curl --request GET \
--url https://api.range.org/v2/corridors \
--header 'X-API-KEY: <api-key>'import requests
url = "https://api.range.org/v2/corridors"
headers = {"X-API-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<api-key>'}};
fetch('https://api.range.org/v2/corridors', 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.range.org/v2/corridors",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <api-key>"
],
]);
$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.range.org/v2/corridors"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<api-key>")
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.range.org/v2/corridors")
.header("X-API-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.range.org/v2/corridors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"items": [
{
"id": "YXJiMS8weGNhODJhNzk2",
"status": "settled",
"protocol": "cctpv2",
"time": "2026-09-23T09:43:35.000Z",
"source": {
"network": "eth",
"address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"destination": {
"network": "eth",
"address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"asset": "USDC",
"amount": "38.24",
"usd": "38.24",
"detected_fee": {
"status": "detected",
"amount": "0.12",
"usd": "0.12"
},
"match_method": "bridge_verified",
"match_confidence": 1
}
],
"meta": {
"next_cursor": "eyJpZCI6IjkxeFFlV3Z...",
"page_number": 1
}
}Authorizations
Authorization method required to allow user to access the api endpoints.
Query Parameters
Start of the period to search (ISO 8601), inclusive.
"2026-09-01T00:00:00Z"
End of the period to search (ISO 8601), inclusive.
"2026-10-01T00:00:00Z"
Corridors per page.
1 <= x <= 10050
Opaque cursor from a previous page’s meta. Omit for the first page.
Comma-separated account ids (UUIDs) to narrow to. Omit to cover every Account in the workspace. Returns corridors touching these Accounts, not corridors between them — narrowing to one wallet still returns its corridors when the far end is an Account you did not list, and that far end is still named. Ids outside your workspace, or failing any filter below, are dropped. At most 100 ids.
1"a1b2c3d4-e5f6-7890-abcd-ef1234567890,b2c3d4e5-f6a7-8901-bcde-f12345678901"
Comma-separated statuses to return. Defaults to settled — movements that arrived. Widen it to also see movements that have not arrived yet (pending) or never will (failed). Every status describes a movement between two addresses you own; only arrival differs. If you widen this, read each item’s status. pending covers only movements whose destination is already known to be yours, so it is not a complete list of everything in transit.
1settled, pending, failed "settled,pending"
Narrow to Accounts in this group (account_groups.id). A non-UUID value is rejected with a 400 naming the field.
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Narrow to Accounts held under a connection of this provider.
utila, kraken, binance, okx, bybit, bitget, gate, kucoin, plaid, squads, altitude, coinbase, realms, wise, safe, hyperliquid, cubist, privy, dfns, anchorage, revolut_business, turnkey, fordefi, coins_ph, fireblocks, pave_bank, copper, custom "utila"
Narrow to Accounts on this network (e.g. ethereum, solana, stellar). This filters which Accounts are in scope, not which networks a corridor may cross.
"ethereum"
Narrow to Accounts of this account type.
eoa, multisig, contract, custodian, exchange, bank, defi "exchange"
Narrow to Accounts tagged with this free-text role.
"treasury"
Narrow to Accounts under this connection id. A non-UUID value is rejected with a 400 naming the field.
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Was this page helpful?