curl --request GET \
--url https://api.citadel.example/api/v1/transfers \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.citadel.example/api/v1/transfers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.citadel.example/api/v1/transfers"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.citadel.example/api/v1/transfers"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"data": [
{
"tx_hash": "3b9f6a…",
"chain": "tron",
"instance": "tron",
"network": "mainnet",
"direction": "in",
"status": "confirmed",
"block_number": 61234567,
"block_time": "2026-10-08T12:30:00Z",
"created_at": "2026-10-08T12:31:05Z",
"legs": [
{
"index": 0,
"asset": "USDT",
"contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"kind": "token",
"from": "TV9F7xFWTg6grbfQ51ppeL8wn69cHiTt3R",
"from_basis": "owner",
"origin": "TV9F7xFWTg6grbfQ51ppeL8wn69cHiTt3R",
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF",
"amount_base_units": "150000000",
"wallet": "user-4211"
}
]
}
],
"next_cursor": null
}List transfers
What moved on chain through your wallets on one network, newest first: deposits
(direction: in), payouts (out), and moves between your own wallets (internal). Each
row is the body of the blockchain_event.confirmed webhook, so you credit a deposit the
same way from either, plus aml: the compliance screenings your workflows ran for it since.
Use it to catch up on deposits whose webhook you missed.
Only confirmed transactions are listed: Citadel reports one once a reorganization can no
longer undo it. A transaction that moved no value (an approve, a plain contract call) is
not a transfer; read it with GET /transactions/{id}.
network is required. Paged with a cursor — see Lists and pagination. Needs the read
scope. A key limited to vaults lists the transfers that touch a wallet in them, and a leg
of a wallet outside them reads wallet: null.
curl --request GET \
--url https://api.citadel.example/api/v1/transfers \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.citadel.example/api/v1/transfers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.citadel.example/api/v1/transfers"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.citadel.example/api/v1/transfers"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"data": [
{
"tx_hash": "3b9f6a…",
"chain": "tron",
"instance": "tron",
"network": "mainnet",
"direction": "in",
"status": "confirmed",
"block_number": 61234567,
"block_time": "2026-10-08T12:30:00Z",
"created_at": "2026-10-08T12:31:05Z",
"legs": [
{
"index": 0,
"asset": "USDT",
"contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"kind": "token",
"from": "TV9F7xFWTg6grbfQ51ppeL8wn69cHiTt3R",
"from_basis": "owner",
"origin": "TV9F7xFWTg6grbfQ51ppeL8wn69cHiTt3R",
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF",
"amount_base_units": "150000000",
"wallet": "user-4211"
}
]
}
],
"next_cursor": null
}Authorizations
An API key minted in the console (ctd_…). Authenticates; never authorizes funds. A key
carries scopes (read, wallets.write, transactions.write, events.write,
webhooks.write, policy.write) and may be limited to vaults, to IP addresses, and in
lifetime — see Authentication.
Query Parameters
The network the data lives on. Required — there is no default network: without it,
422 network_required. A wallet named by its id on another network: 422 network_mismatch.
The network the data lives on. Required wherever it appears in a request — there is no
default network. One your installation does not serve: 422 network_not_served.
mainnet, testnet One direction, or several separated by commas (in,internal).
"in"
Only the transfers touching this wallet: your reference on network, or its id. Token
deposits to it count, also when they land on a token sub-account Citadel keeps for it.
An unknown wallet, or one outside the key's vaults, answers 404; a wallet id from
another network, 422 network_mismatch.
Only the transfers moving this asset: a token's contract as GET /assets lists it, or
native for the chain's own coin. The same address in another form matches too (a TRON
contract as 41… hex, EVM and TON hex in any case). A value that is not a contract
address, such as a symbol, answers 422: a symbol does not identify a token, two can
share one.
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
Only rows Citadel recorded at this time or later (created_at). An ISO 8601 date-time.
Only rows Citadel recorded before this time (created_at). An ISO 8601 date-time.
Rows per page, 1 to 100. Out of range, 422.
1 <= x <= 100The next_cursor of the page before; absent for the first page. Send the same filters
with it. A cursor this API did not issue answers 422 invalid_cursor.