Skip to main content

Transfers · API reference

Base https://gateway.gelabs.org. Always X-API-Key.

HTTP queries sit in {code,message,data} with code 0 on success. WebSocket frames and webhook bodies do not use that envelope.

Addresses​

MethodPathPurpose
GET/tx/api/v1/addressesList (page, pageSize, chain_type)
POST/tx/api/v1/addressesAdd. wallets[]: chain_type, chain_id, address[]
POST/tx/api/v1/addresses/batch-deleteDelete with the same shape
PATCH/tx/api/v1/addressesadd / remove
POST/tx/api/v1/addresses/containsAlready watched?

HTTP watches persist. Live push also needs enable_ws / enable_webhook.

Excluded from push​

Watches and history stay. For the same chain_type, a transfer is not sent over WebSocket or webhook when the sender, receiver, or a token-transfer from / to / contract is on this list.

MethodPathPurpose
GET/tx/api/v1/addresses/exclusionsList (page, pageSize, chain_type)
POST/tx/api/v1/addresses/exclusionsAdd. wallets[] matches the watch body
POST/tx/api/v1/addresses/exclusions/batch-deleteRemove with the same shape

Queries​

MethodPathPurpose
POST/tx/api/v1/transfers/searchOne address. Cursor id; filters tx_type (native / token / other), token
POST/tx/api/v1/transfers/multi-chainMany chains / addresses
POST/tx/api/v1/transactions/batch-getBy tx_hash
GET/tx/api/v1/transactions/{tx_hash}One tx; query needs chain_type, chain_id

search example:

{
"address": "0x...",
"chain_type": "evm",
"chain_id": 1,
"limit": 20
}

Push config​

MethodPathPurpose
GET/tx/api/v1/app/configWS / webhook flags
PUT/tx/api/v1/app/configenable_ws, enable_webhook, webhook_url, webhook_secret
POST/tx/api/v1/app/webhook/retryRetry failed deliveries

Webhook requires a public webhook_url. webhook_secret is optional; when set, every POST includes the Sign header.

{
"enable_ws": true,
"enable_webhook": true,
"webhook_url": "https://your-server.example/hooks/tx",
"webhook_secret": "your-secret"
}

Transfer object​

data on a WebSocket type: transaction frame, and each item in the webhook array, describe the same transfer, but the JSON shape is not identical (see Webhook below).

The push chain family is evm / tvm / svm / utxo. Supported networks and chain_id values: Overview.

camelCase primary fields (prefer these for new integrations):

FieldTypeMeaning
chainTypestringFamily, e.g. evm, tvm
chainIdintegerChain ID, e.g. Ethereum mainnet 1
txHashstringTransaction hash
txTimeintegerTx time, Unix milliseconds
heightintegerBlock height
senderstringSender
receiverstringReceiver
feePayerstringFee payer
amountstringNative amount (string; do not parse as a JS number)
symbolstringNative symbol
decimalsintegerNative decimals
txStatusstringOn-chain status, e.g. success
gasLimit / gasUsed / gasPrice / txFeestringGas and fee (strings)
noncestringTransaction nonce
transferTypestringNativeCoin / Token / Other; see table below
methodId / methodCallstringContract method
l1OriginHashstringL1 origin hash (L2, etc.)
listenAddressstring[]Matched watch addresses; [] if none
tokenTransferDetailsarrayToken transfers (camelCase items)
fromDetailsarrayMulti-input details (camelCase)
toDetailsarrayMulti-output details (camelCase)
internalTransactionDetailsarrayInternal calls / instructions (camelCase)

Common tokenTransferDetails[] fields: from, to, tokenContractAddress, symbol, amount, decimals, mint.

transferType​

Classifies the primary transfer semantics of a transaction. All chain families (evm / tvm / svm / utxo) use the same values:

ValueMeaning
NativeCoinNative coin transfer. Examples: plain ETH on EVM, TVM TransferContract (TRX), Bitcoin UTXO. Top-level amount / symbol / decimals are usually populated.
TokenToken transfer. Examples: direct ERC-20 / TRC-20 transfer contract calls. Native amount is often "0"; see tokenTransferDetails for token amounts.
OtherOther contract interactions: batch transfers, non-direct token calls, stake / freeze, etc. Token movements, if any, are in tokenTransferDetails; top-level fields may not reflect actual asset flow.

Webhook snake_case transfer_type is the DB raw shape; legacy rows may use lowercase token. camelCase transferType is always PascalCase.

For /tx/api/v1/transfers/search, tx_type filters are case-insensitive: native / nativecoin → NativeCoin, token → Token, other → Other.

Webhook also emits snake_case (same meaning or DB raw shape, for legacy consumers):

snake_case keycamelCase / notes
chain_type, chain_id, tx_hash, tx_time, tx_statusSame as chainType, chainId, txHash, txTime, txStatus
token_transfers, from_details, to_detailsSame family as tokenTransferDetails, DB field names
internal_transactionsSame family as internalTransactionDetails, DB shape
tx_version, fee_payer, transfer_typeRaw pointer fields; may be null
max_fee_per_gas, max_priority_fee_per_gasEIP-1559; may be null
gas_limit, gas_used, gas_price, tx_feeSame as gasLimit, etc.; raw pointer shape
method_id, method_call, l1_origin_hashSame as methodId, etc.; raw pointer shape

WebSocket data matches the webhook business fields, plus is_reorg_resend (true for reorg resends). There is no legacy txhash alias; read txHash / tx_hash. ACK with chain_type + txHash.


WebSocket​

GET wss://gateway.gelabs.org/tx/ws

Header X-API-Key. To receive transaction pushes, PUT /tx/api/v1/app/config with enable_ws: true and add addresses over HTTP.

Every frame:

FieldTypeMeaning
idstringFrame ID. Use as messageId when ACKing
timeintegerUnix milliseconds
typestringSee table below
codeinteger0 success; non-zero is an error
dataobject / nullDepends on type
messagestringHuman text. It is message, not msg
typeDirectionMeaning
connecteddownHandshake
transactiondownHit; data is the transfer object
transactionACKupConfirm receipt; stops resend
ping / pongbothJSON heartbeat; raw text ping also works
subscribe / unsubscribeupAdd / remove a persistent watch on this App
getTxHashupLook up one tx by hash

connected​

{
"id": "c1",
"time": 1710000000000,
"type": "connected",
"code": 0,
"data": {
"clientId": "client-uuid",
"appId": "your-app-id"
},
"message": "success"
}

transaction​

{
"id": "msg-1",
"time": 1710000000000,
"type": "transaction",
"code": 0,
"data": {
"chain_type": "evm",
"chain_id": 1,
"tx_hash": "0xabc...",
"txHash": "0xabc...",
"tx_time": 1710000000000,
"txTime": 1710000000000,
"height": 12345678,
"sender": "0x1111...",
"receiver": "0x2222...",
"amount": "1000000000000000000",
"symbol": "ETH",
"decimals": 18,
"tx_status": "success",
"listenAddress": ["0x1111..."],
"token_transfers": [],
"from_details": [],
"to_details": [],
"is_reorg_resend": false
},
"message": "success"
}

ACK immediately or the server resends:

{
"id": "ack-1",
"type": "transactionACK",
"data": {
"chain_type": "evm",
"txHash": "0xabc...",
"messageId": "msg-1"
}
}

chain_type is required. Provide at least one of txHash (or tx_hash) and messageId (or message_id, the downlink frame id). The server replies with the same type; code 0 means the ACK landed.

subscribe​

{
"id": "sub-1",
"type": "subscribe",
"data": {
"address": "0x1234567890abcdef1234567890abcdef12345678",
"chain_type": "evm",
"chain_id": 1
}
}

On success data is {app_id, address, chain_type}. unsubscribe uses the same request shape; success data is {address, chainType}. Prefer HTTP for the watch list so disconnects do not surprise you.


Webhook​

The server POSTs to your webhook_url. You do not poll.

Headers​

HeaderMeaning
Content-Typeapplication/json
SignEquals the webhook_secret in config. Empty string if unset

Compare Sign as plaintext. It is not an HMAC.

Body​

The body is a JSON array. Each item includes both camelCase primary fields and snake_case compatibility keys (see Transfer object above). The example omits some raw fields that may be null:

[
{
"chain_type": "evm",
"chain_id": 1,
"tx_time": 1710000000000,
"tx_hash": "0xabc...",
"tx_status": "success",
"gas_limit": "21000",
"gas_used": "21000",
"gas_price": "1000000000",
"tx_fee": "21000000000000",
"token_transfers": [],
"from_details": [],
"to_details": [],
"internal_transactions": [],
"chainType": "evm",
"chainId": 1,
"txTime": 1710000000000,
"txHash": "0xabc...",
"height": 12345678,
"sender": "0x1111...",
"receiver": "0x2222...",
"feePayer": "0x1111...",
"amount": "1000000000000000000",
"symbol": "ETH",
"decimals": 18,
"txStatus": "success",
"gasLimit": "21000",
"gasUsed": "21000",
"gasPrice": "1000000000",
"txFee": "21000000000000",
"nonce": "7",
"listenAddress": ["0x1111..."],
"tokenTransferDetails": [],
"fromDetails": [],
"toDetails": [],
"internalTransactionDetails": []
}
]

Legacy integrations may keep reading chain_type / tx_hash; new integrations should prefer camelCase primary fields.

Your response​

Return HTTP 2xx (body may be empty). Non-2xx or timeout triggers retry. Use POST /tx/api/v1/app/webhook/retry to replay failed deliveries.