Transfers API (Tx History)
The Transfers API allows you to easily fetch historical transactions for any address without having to scan the entire Ethereum and Polygon chain and index everything for each of your users.

What are Transfers?

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.
NOTE: The Transfers API is currently only available on Ethereum and Polygon.
TIP: Check out this tutorial on integrating historical transaction data into your dApp to learn how to get started using the Transfers API!

Types of Transfers

There are five main types of transfers that are captured when using this API.

Types of transfers supported on each network:

  • Ethereum Mainnet: External, Internal, Token, ERC20, ERC721, ERC1155
  • Ethereum Testnets: - Rinkeby, Kovan, Ropsten: Token, ERC20, ERC721, ERC1155 - Goerli: Exteranl, Token, ERC20, ERC721, ERC1155
  • Polygon Mainnet: External, Token, ERC20, ERC721, ERC1155
  • Polygon Mumbai: External, Token, ERC20, ERC721, ERC1155

1. External Eth Transfers

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.

2. ERC20 Transfers

Event logs for ERC20 transfers.
NOTE: ERC20 Transfers are also included in the "token" category

3. ERC721 Transfers

Event logs for ERC721 transfers.
NOTE: ERC721 Transfers are also included in the "token" category

4. ERC1155 Transfers

These are event logs for ERC1155 transfers.

5. Internal Eth 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).
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.

alchemy_getAssetTransfers (Ethereum Mainnet)

NOTE: The documentation in this section only applies to alchemy_getAssetTransfers on Ethereum Mainnet. For documentation on Ethereum Testnets and Polygon (Mainnet and Mumbai), see alchemy_getAssetTransfers (Testnets and Layer 2s).

Parameters

  • Object - An object with the following fields (required):
    • fromBlock: [optional] inclusive from block (hex string, int, or latest)
      • Default: latest
    • toBlock: [optional] inclusive to block (hex string, int, or latest)
      • Default: latest
    • fromAddress: [optional] from address (hex string)
      • Default: wildcard - any address
    • toAddress: [optional] to address (hex string)
      • Default: wildcard - any address
    • contractAddresses: [optional] list of contract addresses (hex strings) to filter for - only applies to "token", "erc20", "erc721", "erc1155" transfers
      • Default: wildcard - any address
    • category: [optional] array of categories, can be any of the following: "external", "internal", "token", "erc20", "erc721", "erc1155"
      • Default: ["external", "internal", "token"]
    • excludeZeroValue: [optional] aBoolean to exclude transfers with zero value. Zero value is not the same as null value
      • Default: true
    • maxCount: [optional] max hex string number of results to return per call
      • Default (and max): 1000 or 0x3e8
    • pageKey: [optional] uuid for pagination. If more results are available, a uuid pageKey will be returned in the response. Pass that uuid into pageKey to fetch the next 1000 or maxCount.
NOTE:
  • fromAddress and toAddress are ANDed together when filtering.
  • contractAddresses are OR ed together. This filter will then be ANDed with fromAddress and toAddress.

Returns

  • id: json-rpc id
    • jsonrpc: json-rpc version
    • result: 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", "token", "erc20", "erc721", "erc1155" - label for the transfer
      • "token" includes "erc20" and "erc721" transfers
    • blockNum: 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 transfer
    • erc1155Metadata: A list of objects containing the ERC1155 tokenId (hex string) and value (hex string). null if not an ERC1155 transfer
    • tokenId: token ID for ERC721 (or other NFT) tokens
    • asset: 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 or ERC1155 transfer
      • address: contract address (hex string). null if external or internal transfer
      • decimal: contract decimal (hex string). null if not defined in the contract and not available from other sources.

​Example​

Request

Fetch (JS)
Axios (JS)
Curl
Postman
1
var myHeaders = new Headers();
2
myHeaders.append("Content-Type", "application/json");
3
​
4
var raw = JSON.stringify({
5
"jsonrpc": "2.0",
6
"id": 0,
7
"method": "alchemy_getAssetTransfers",
8
"params": [
9
{
10
"fromBlock": "0xA97AB8",
11
"toBlock": "0xA97CAC",
12
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
13
"contractAddresses": [
14
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
15
],
16
"maxCount": "0x5",
17
"excludeZeroValue": true,
18
"category": [
19
"external",
20
"token"
21
]
22
}
23
]
24
});
25
​
26
var requestOptions = {
27
method: 'POST',
28
headers: myHeaders,
29
body: raw,
30
redirect: 'follow'
31
};
32
​
33
fetch("https://eth-mainnet.alchemyapi.io/v2/demo", requestOptions)
34
.then(response => response.text())
35
.then(result => console.log(result))
36
.catch(error => console.log('error', error));
Copied!
1
import axios from 'axios';
2
​
3
var data = JSON.stringify({
4
"jsonrpc": "2.0",
5
"id": 0,
6
"method": "alchemy_getAssetTransfers",
7
"params": [
8
{
9
"fromBlock": "0xA97AB8",
10
"toBlock": "0xA97CAC",
11
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
12
"contractAddresses": [
13
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
14
],
15
"maxCount": "0x5",
16
"excludeZeroValue": true,
17
"category": [
18
"external",
19
"token"
20
]
21
}
22
]
23
});
24
​
25
var config = {
26
method: 'post',
27
url: 'https://eth-mainnet.alchemyapi.io/v2/demo',
28
headers: {
29
'Content-Type': 'application/json'
30
},
31
data : data
32
};
33
​
34
axios(config)
35
.then(function (response) {
36
console.log(JSON.stringify(response.data));
37
})
38
.catch(function (error) {
39
console.log(error);
40
});
41
​
Copied!
1
curl https://eth-mainnet.alchemyapi.io/v2/your-api-key \
2
-X POST \
3
-H "Content-Type: application/json" \
4
-d'{"jsonrpc":"2.0", "id": 1, "method":"alchemy_getAssetTransfers","params":[{"fromBlock": "0xA97AB8", "toBlock": "0xA97CAC", "fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE", "contracts": ["0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"], "category": ["external", "internal", "token"], "maxCount": "0x5"}]}'
Copied!
1
URL: https://eth-mainnet.alchemyapi.io/v2/your-api-key
2
RequestType: POST
3
Body:
4
{
5
"jsonrpc": "2.0",
6
"id": 0,
7
"method": "alchemy_getAssetTransfers",
8
"params": [
9
{
10
"fromBlock": "0xA97AB8",
11
"toBlock": "0xA97CAC",
12
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
13
"contractAddresses": [
14
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
15
],
16
"maxCount": "0x5",
17
"excludeZeroValue": true,
18
"category": [
19
"external",
20
"token"
21
]
22
}
23
]
24
}
Copied!

Result

1
{
2
"id": 0,
3
"result": {
4
"transfers": [
5
{
6
"blockNum": "0xa97ae2",
7
"hash": "0x56a00d5fac0dcacfe1cd950c49506712ec5bf319e246701321e8a92643da349d",
8
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
9
"to": "0xfd5d6417fdcf02f0627aafa9e594a67d4485642d",
10
"value": 5.73621309,
11
"erc721TokenId": null,
12
"erc1155Metadata": null,
13
"tokenId": null,
14
"asset": "ETH",
15
"category": "external",
16
"rawContract": {
17
"value": "0x4f9b1f69e1655400",
18
"address": null,
19
"decimal": "0x12"
20
}
21
},
22
{
23
"blockNum": "0xa97ae2",
24
"hash": "0x6b0b85a7d202fbec16aea70f876298283b44b00629a3b472fbcadf2f9436e5fd",
25
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
26
"to": "0xb4caa764e2bf087f1a7a0cec43250892022787d9",
27
"value": 2.995,
28
"erc721TokenId": null,
29
"erc1155Metadata": null,
30
"tokenId": null,
31
"asset": "ETH",
32
"category": "external",
33
"rawContract": {
34
"value": "0x299060a1be4b8000",
35
"address": null,
36
"decimal": "0x12"
37
}
38
},
39
{
40
"blockNum": "0xa97ae2",
41
"hash": "0x8cc39a71b5da3abab46460a990f1e999e74428b4b075053f98d675656107f4f8",
42
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
43
"to": "0x66ee6fc2c17b3a2624c06ae8783eb265a747a23d",
44
"value": 0.1,
45
"erc721TokenId": null,
46
"erc1155Metadata": null,
47
"tokenId": null,
48
"asset": "ETH",
49
"category": "external",
50
"rawContract": {
51
"value": "0x16345785d8a0000",
52
"address": null,
53
"decimal": "0x12"
54
}
55
},
56
{
57
"blockNum": "0xa97ae2",
58
"hash": "0x8f8b1af8041b2c32eb4fb1b236c2523b28038c2a510ec48948749bc6bddf2824",
59
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
60
"to": "0x8187d27641eaa9eca3a80f7a2f37af192fa43507",
61
"value": 0.495,
62
"erc721TokenId": null,
63
"erc1155Metadata": null,
64
"tokenId": null,
65
"asset": "ETH",
66
"category": "external",
67
"rawContract": {
68
"value": "0x6de97e09bd18000",
69
"address": null,
70
"decimal": "0x12"
71
}
72
},
73
{
74
"blockNum": "0xa97ae2",
75
"hash": "0xb322ec7cf57d56b7250f36d7c59f0e7d96de05218ab402f345d4507829516f02",
76
"from": "0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be",
77
"to": "0xe535d87c42d21af3166eb00bbace668b13d55ec7",
78
"value": 17.625,
79
"erc721TokenId": null,
80
"erc1155Metadata": null,
81
"tokenId": null,
82
"asset": "ETH",
83
"category": "external",
84
"rawContract": {
85
"value": "0xf498941e66428000",
86
"address": null,
87
"decimal": "0x12"
88
}
89
}
90
],
91
"pageKey": "347664a8-a6fd-40dd-b421-9cd08ae8c067"
92
},
93
"jsonrpc": "2.0"
94
}
Copied!

alchemy_getAssetTransfers (Testnets and Layer 2s)

The documentation in this section only applies to alchemy_getAssetTransfers on Ethereum Testnets and Polygon (Mainnet and Mumbai). For documentation on Ethereum Mainnet, see above.
NOTE: Types of Transfers supported
alchemy_getAssetTransfers on Polygon only supports external ,token, ERC20, ERC721, and ERC1155 transfers, notinternal MATIC transfers.
If you'd like support for these transfer types, please upvote and comment to add this to our roadmap.

Parameters

  • Object - An object with the following fields (required):
    • fromBlock: [optional] inclusive from block (hex string, int, or latest)
      • Default: latest
    • toBlock: [optional] inclusive to block (hex string, int, or latest)
      • Default: latest
    • fromAddress: [optional] from address (hex string)
      • Default: wildcard - any address
    • toAddress: [optional] to address (hex string)
      • Default: wildcard - any address
    • contractAddresses: [optional] list of contract addresses (hex strings) to filter for - only applies to "token", "erc20", "erc721", "erc1155" transfers
      • Default: wildcard - any address
    • category: [optional] array of categories, can be any of the following: "token", "erc20", "erc721", "erc1155"
      • Defaults: ["token"]
    • excludeZeroValue: [optional] aBoolean to exclude transfers with zero value
      • Default: true
    • maxCount: [optional] max hex string number of results to return per call
      • Default (and max): 1000 or 0x3e8
    • pageKey: [optional] uuid for pagination. If more results are available, a uuid pageKey will be returned in the response. Pass that uuid into pageKey to fetch the next 1000 or maxCount.
NOTE:
  • fromAddress and toAddress are ANDed together when filtering.
  • contractAddresses are OR ed together. This filter will then be ANDed with fromAddress and toAddress.

Returns

  • id: json-rpc id
  • jsonrpc: json-rpc version
  • result: 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: "token", "erc20", "erc721", "erc1155" - label for the transfer
      • "token" includes "erc20" and "erc721" transfers
    • blockNum: 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 transfer
    • erc1155Metadata: A list of objects containing the ERC1155 tokenId (hex string) and value (hex string). null if not an ERC1155 transfer
    • tokenId: token ID for ERC721 (or other NFT) tokens
    • asset: 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 or ERC1155 transfer
      • address: contract address (hex string). null if external or internal transfer
      • decimal: contract decimal (hex string). null if not defined in the contract and not available from other sources.

Request

Fetch (JS)
Axios (JS)
Curl
Postman
1
var myHeaders = new Headers();
2
myHeaders.append("Content-Type", "application/json");
3
​
4
var raw = JSON.stringify({
5
"jsonrpc": "2.0",
6
"id": 0,
7
"method": "alchemy_getAssetTransfers",
8
"params": [
9
{
10
"fromBlock": "0xA97AB8",
11
"toBlock": "0xA97CAC",
12
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
13
"contractAddresses": [
14
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
15
],
16
"maxCount": "0x5",
17
"excludeZeroValue": true,
18
"category": [
19
"external",
20
"token"
21
]
22
}
23
]
24
});
25
​
26
var requestOptions = {
27
method: 'POST',
28
headers: myHeaders,
29
body: raw,
30
redirect: 'follow'
31
};
32
​
33
fetch("https://polygon-mainnet.g.alchemy.com/v2/your-api-key", requestOptions)
34
.then(response => response.text())
35
.then(result => console.log(result))
36
.catch(error => console.log('error', error));
Copied!
1
import axios from 'axios';
2
​
3
var data = JSON.stringify({
4
"jsonrpc": "2.0",
5
"id": 0,
6
"method": "alchemy_getAssetTransfers",
7
"params": [
8
{
9
"fromBlock": "0xA97AB8",
10
"toBlock": "0xA97CAC",
11
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
12
"contractAddresses": [
13
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
14
],
15
"maxCount": "0x5",
16
"excludeZeroValue": true,
17
"category": [
18
"external",
19
"token"
20
]
21
}
22
]
23
});
24
​
25
var config = {
26
method: 'post',
27
url: 'https://polygon-mainnet.g.alchemy.com/v2/your-api-key',
28
headers: {
29
'Content-Type': 'application/json'
30
},
31
data : data
32
};
33
​
34
axios(config)
35
.then(function (response) {
36
console.log(JSON.stringify(response.data));
37
})
38
.catch(function (error) {
39
console.log(error);
40
});
41
​
Copied!
1
curl https://polygon-mainnet.g.alchemy.com/v2/your-api-key \
2
-X POST \
3
-H "Content-Type: application/json" \
4
-d'{"jsonrpc":"2.0", "id": 1, "method":"alchemy_getAssetTransfers","params":[{"fromBlock": "0xA97AB8", "toBlock": "0xA97CAC", "fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE", "contracts": ["0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"], "category": ["external", "token"], "maxCount": "0x5"}]}'
Copied!
1
URL: https://polygon-mainnet.g.alchemy.com/v2/your-api-key
2
RequestType: POST
3
Body:
4
{
5
"jsonrpc": "2.0",
6
"id": 0,
7
"method": "alchemy_getAssetTransfers",
8
"params": [
9
{
10
"fromBlock": "0xA97AB8",
11
"toBlock": "0xA97CAC",
12
"fromAddress": "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
13
"contractAddresses": [
14
"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
15
],
16
"maxCount": "0x5",
17
"excludeZeroValue": true,
18
"category": [
19
"external",
20
"token"
21
]
22
}
23
]
24
}
Copied!

Response

1
{
2
"id":0
3
"result":{
4
"transfers":[
5
0:{
6
"blockNum":"0x16c5378"
7
"hash":"0x1e85ace98f4fc4ad7b1b64465df81d0a275d494421e553e23a238b156f42b17f"
8
"from":"0x5350e1068f0e138ff306990b16fa4910d970c692"
9
"to":"0x9d2b758e3ffd2569c6956676fae7f8b71a53ffb5"
10
"value":NULL
11
"erc721TokenId":NULL
12
"erc1155Metadata":NULL
13
"tokenId":NULL
14
"asset":NULL
15
"category":"erc20"
16
"rawContract":{
17
"value": "0x02f86e8030",
18
"address": "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
19
"decimal": null
20
}
21
}
22
]
23
}
24
"jsonrpc":"2.0"
25
}
Copied!

Pagination

There are two cases in which pagination will be required:
  1. 1.
    If you have a specific number of responses that you want to receive in a given payload
  2. 2.
    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.
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.

How to get timestamps for a transaction

A transaction object will have a block number associated with it, the block number is Ethereum's measure of time, however, if you want a standard timestamp you can easily get that by grabbing the blockNum result and making a call to eth_getBlockByNumber. Here is an example request.