description |
---|
The Transfers API allows you to easily fetch historical transactions for any address without having to scan the entire chain and index everything for each of your users. |
Transfers are a representation of value being exchanged between two accounts. Often times users wish to see the historical transactions associated with a specific account or address. This is currently an extremely challenging and inefficient task, requiring users to scan the entire blockchain and index everything to search for transactions associated with the desired address. However, with the Transfers API users can query all types of historical transactions for a given address in a single request.
If you don't have an account yet, you can sign up with Alchemy for free.
There are three main types of transfers that are captured when using this API.
These are top level ethereum transactions that occur with a from address being an external (user created) address. External addresses have private keys and are accessed by users.
These are event logs for ERC20 and ERC721 transfers.
These are transfers that occur where the fromAddress
is an internal (smart contract) address. (ex: a smart contract calling another smart contract or smart contract calling another external address).
{% hint style="info" %} NOTE: For efficiency, we do not return internal transfers with 0 value as they don't provide useful information without digging deeper into the internal transaction itself. If you are interested in these type of events see our Trace API.
Additionally, we do not include any internal transfers with call typedelegatecall
because although they have a value associated with them they do not actually transfer that value (see Appendix H of the Ethereum Yellow Paper if you're curious). We also do not include miner rewards as an internal transfer.
{% endhint %}
{% hint style="warning" %}
NOTE: alchemy_getAssetTransfers
is currently only available on Mainnet.
{% endhint %}
- Parameters:
- Object - An object with the following fields (required):
fromBlock
: inclusive from block (hex string orlatest
). optional (defaults tolatest
)toBlock
: inclusive to block (hex string orlatest
). optional (defaults tolatest
)fromAddress
: from address (hex string). optional (default wildcard - any address)toAddress
: to address (hex string). optional (default wildcard - any address)contractAddresses
: list of contract addresses (hex strings) fortoken
transfers. optional (default wildcard - any address)category
: list of any combination ofexternal
,internal
,token
. optional (default all)excludeZeroValue:
aBoolean
to exclude transfers with zero value. optional (defaulttrue
)maxCount
: max hex string number of results to return per call. optional (default and max1000
or0x3e8
)pageKey
:uuid
for pagination. optional. If more results are available, a uuid pageKey will be returned in the response. Pass that uuid intopageKey
to fetch the next 1000 ormaxCount.
- Object - An object with the following fields (required):
- NOTE:
fromAddress
andtoAddress
areAND
ed together when filtering. - NOTE:
contractAddresses
areOR
ed together. This filter will then beAND
ed withfromAddress
andtoAddress
.
- Response Payload:
id
: json-rpc idjsonrpc
: json-rpc versionresult
: an object with the following fields:pageKey
: uuid of next page of results (if exists, else blank).transfers:
array of objects (defined below) - sorted in ascending order by block number, ties broken by category (external
,internal
,token
)
- Object schema:
category
:external
,internal
, ortoken
- label for the transferblockNum
: the block where the transfer occurred (hex string).from
: from address of transfer (hex string).to
: to address of transfer (hex string).null
if contract creation.value
: converted asset transfer value as a number (raw value divided by contract decimal).null
if erc721 transfer or contract decimal not available.erc721TokenId
: raw erc721 token id (hex string).null
if not an erc721 token transferasset
:ETH
or the token's symbol.null
if not defined in the contract and not available from other sources.hash
: transaction hash (hex string).rawContract
value
: raw transfer value (hex string).null
if erc721 transferaddress
: contract address (hex string).null
ifexternal
orinternal
transferdecimal
: contract decimal (hex string).null
if not defined in the contract and not available from other sources.
Request
{% tabs %} {% tab title="Curl" %}
curl https://eth-mainnet.alchemyapi.io/v2/your-api-key \
-X POST \
-H "Content-Type: application/json" \
-d'{"jsonrpc":"2.0", "id": 1, "method":"alchemy_getAssetTransfers","params":[{"fromBlock": "0xA97AB8", "toBlock": "0xA97CAC", "fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE", "contracts": ["0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"], "category": ["external", "internal", "token"], "maxCount": "0x5"}]}'
{% endtab %}
{% tab title="Postman" %}
URL: https://eth-mainnet.alchemyapi.io/v2/your-api-key
RequestType: POST
Body:
{
"jsonrpc": "2.0",
"id": 0,
"method": "alchemy_getAssetTransfers",
"params": [
{
"fromBlock": "0xA97AB8",
"toBlock": "0xA97CAC",
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
"contractAddresses": [
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
],
"maxCount": "0x5",
"excludeZeroValue": true,
"category": [
"external",
"token"
]
}
]
}
{% endtab %} {% endtabs %}
Result
{
"id": 0,
"result": {
"transfers": [
{
"blockNum": "0xa97ae2",
"hash": "0x6b0b85a7d202fbec16aea70f876298283b44b00629a3b472fbcadf2f9436e5fd",
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
"to": "0xb4caa764e2bf087f1a7a0cec43250892022787d9",
"value": 2.995,
"erc721TokenId": null,
"asset": "ETH",
"category": "external",
"rawContract": {
"value": "0x299060a1be4b8000",
"address": null,
"decimal": "0x12"
}
},
{
"blockNum": "0xa97ae2",
"hash": "0x8cc39a71b5da3abab46460a990f1e999e74428b4b075053f98d675656107f4f8",
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
"to": "0x66ee6fc2c17b3a2624c06ae8783eb265a747a23d",
"value": 0.1,
"erc721TokenId": null,
"asset": "ETH",
"category": "external",
"rawContract": {
"value": "0x16345785d8a0000",
"address": null,
"decimal": "0x12"
}
},
{
"blockNum": "0xa97ae2",
"hash": "0x8f8b1af8041b2c32eb4fb1b236c2523b28038c2a510ec48948749bc6bddf2824",
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
"to": "0x8187d27641eaa9eca3a80f7a2f37af192fa43507",
"value": 0.495,
"erc721TokenId": null,
"asset": "ETH",
"category": "external",
"rawContract": {
"value": "0x6de97e09bd18000",
"address": null,
"decimal": "0x12"
}
},
{
"blockNum": "0xa97ae2",
"hash": "0xb322ec7cf57d56b7250f36d7c59f0e7d96de05218ab402f345d4507829516f02",
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
"to": "0xe535d87c42d21af3166eb00bbace668b13d55ec7",
"value": 17.625,
"erc721TokenId": null,
"asset": "ETH",
"category": "external",
"rawContract": {
"value": "0xf498941e66428000",
"address": null,
"decimal": "0x12"
}
},
{
"blockNum": "0xa97ae2",
"hash": "0x56a00d5fac0dcacfe1cd950c49506712ec5bf319e246701321e8a92643da349d",
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
"to": "0xfd5d6417fdcf02f0627aafa9e594a67d4485642d",
"value": 5.73621309,
"erc721TokenId": null,
"asset": "ETH",
"category": "external",
"rawContract": {
"value": "0x4f9b1f69e1655400",
"address": null,
"decimal": "0x12"
}
}
],
"pageKey": "755207c2-d187-40fe-87aa-f43e71126777"
},
"jsonrpc": "2.0"
}
There are two cases in which pagination will be required:
- If you have a specific number of responses that you want to receive in a given payload
- If you receive a response with more than 1000 results.
In the first case, you should use the maxCount
parameter in your request to specify the number of responses you wish to receive. If there are more results than specified in maxCount
, you will receive a value for pageKey
in your result which you should use to fetch the next response load by putting the returned pageKey
value in the pageKey
parameter of your next request. Continue to do so until a pageKey
is no longer returned (meaning you've fetched all the results).
In the second case, you will also receive a value for pageKey
in the response, which you should use to fetch the next 1000 (or however many is left) by putting the returned pageKey
value in the pageKey
parameter of your next request.
{% hint style="danger" %}
NOTE: Each page key has a TTL (Time to Live) of 10 minutes so if you receive a response with a pageKey
value you must send the next request (with the pageKey
) within the 10 minute window, otherwise you will have to restart the entire request cycle.
{% endhint %}