Receive an Inbound Transfer

This guide outlines initiating a currency transfer into a previously created user-controlled wallet. If you have not yet created a user-controlled wallet, go to this guide

The following steps utilize Circle’s sample applications in combination with API requests that can be done via Circle's API references or cURL requests. cURL request will be provided inline, while API references will be linked from the API endpoint code text. You can find instructions on using it in the testing via the reference pages guide.

1. Acquire a Session Token

Make a request to POST /users/token using a previously created userId. The userToken is a 60-minute session token to initiate requests requiring a user challenge (PIN code entry). After 60 minutes, the session expires, and a new userToken must be generated via the same endpoint. 

curl --request POST \
     --url 'https://api.circle.com/v1/w3s/users/token' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'authorization: Bearer <API_KEY>' \
     --data '
{
  "userId": "2f1dcb5e-312a-4b15-8240-abeffc0e3463"
}
'
{
  "data": {
    "userToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCC9.eyJkZXZlbG9wZXJFbnRpdHlFbnZpcm9ubWVudCI6IlRFU1QiLCJlbnRpdHlJZCI6IjRlMDdhOGM5LTIxOTAtNDVlNC1hNjc0LWQyMGFkNjg4MWI3YyIsImV4cCI6MTY5MDU1MjcwNywiaWF0IjoxNjkwNTQ5MTA3LCJpbnRlcm5hbFVzZXJJZCI6ImQ2ZjkzODliLWQ5MzUtNWFlYy1iOTVhLWNjNTk1NjA2YWM5NiIsImlzcyI6Imh0dHBzOi8vcHJvZ3JhbW1hYmxlLXdhbGxldC5jaXJjbGUuY29tIiwianRpIjoiMmE0YmJlMzAtZTdkZi00YmM2LThiODMtNTk0NGUyMzE2ODlkIiwic3ViIjoiZXh0X3VzZXJfaWRfOSJ9.dhfByhxZFbJx0XWlzxneadT4RQWdnxLu3FSN9ln65hCDOfavaTL1sc4h-jUR8i4zMmfdURw3FFcQIdSbm-BUg6M7FP_fp-cs9xBbNmRZa31gMd1aKdcajJ9SvlVrfUowYfGXM3VcNF8rtTFtW-gk1-KzU4u10U35XXbbMcW1moxE0Rqx_fKotDgk2VdITuuds5d5TiQzAXECqeCOCtNoDKktMkglltbnLxOaRl2ReZjGt-ctD2V0DbYNO4T_ndPSUDI6qD7dXQRed5uDcezJYoha3Qj3tFGBglEnox2Y6DWTbllqjwmfTGrU8Pr0yz4jQz7suGwmiCzHPxcpYxMzYQ",
    "encryptionKey": "Tlcyxz7Ts9ztRLQq5+pic0MIETblYimOo2d7idV/UFM="
  }
}

2. Acquire the Wallet Id

Make a request to GET /wallets using the userToken returned in Step 1 to retrieve the wallet information for a given user.

curl --request POST \
     --url 'https://api.circle.com/v1/w3s/wallets' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'authorization: Bearer <API_KEY>' \
     --header 'X-User-Token: <USER_TOKEN>' 
{
  "data": {
    "wallets": [
      {
        "id": "01899cf2-d415-7052-a207-f9862157e546",
        "state": "LIVE",
        "walletSetId": "01899cf2-d407-7f89-b4d9-84d63573f138",
        "custodyType": "ENDUSER",
        "userId": "2f1dcb5e-312a-4b15-8240-abeffc0e3463",
        "address": "0x075e62c80e55d024cfd8fd4e3d1184834461db57",
        "addressIndex": 0,
        "blockchain": "ETH-GOERLI",
        "accountType": "EOA",
        "updateDate": "2023-07-28T14:41:47Z",
        "createDate": "2023-07-28T14:41:47Z"
      }
    ]
  }
}

3. Transfer Testnet Currency

Transfer Testnet currency from an external wallet outside your Programmable Wallet infrastructure into your applicable wallet address. You can find faucets for these Testnets here. You can also transfer USDC on these Testnets using the USDC faucet. For more information regarding the differences between Testnet and Mainnet, see our guide Testnet vs Mainnet Differences.

Once an inbound transfer is made and complete to the address, Circle sends a notification to a subscribed endpoint. The Webhook notification will be similar to the one below.

{
  "subscriptionId": "d4c07d5f-f05f-4fe4-853d-4dd434806dfb",
  "notificationId": "05b3f4e5-ec27-44b8-aa40-3698577f6d92",
  "notificationType": "transactions.inbound",
  "notification": {
    "id": "2f4b6bcd-a752-5d8b-996b-92e3e04bd33b",
    "blockchain": "ETH-GOERLI",
    "walletId": "01899cf2-d415-7052-a207-f9862157e546",
    "tokenId": "73eab1a4-02e9-5ce6-bb5f-c6d0fbdb93bb",
    "userId": "2f1dcb5e-312a-4b15-8240-abeffc0e3463",
    "destinationAddress": "0x075e62c80e55d024cfd8fd4e3d1184834461db57",
    "amounts": [
      "10"
    ],
    "nftTokenIds": [],
    "state": "COMPLETED",
    "errorReason": "",
    "transactionType": "INBOUND",
    "createDate": "2023-07-28T16:03:08Z",
    "updateDate": "2023-07-28T16:06:40Z"
  },
  "timestamp": "2023-07-28T16:06:40.907831464Z",
  "version": 2
}

Alternatively, you can poll GET /transactions using the userId or userToken associated with your user. 

curl --request GET \
     --url 'https://api.circle.com/v1/w3s/transactions' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'authorization: Bearer <API_KEY>' \
     --header 'X-User-Token: <USER_TOKEN>'
{
  "data": {
    "transactions": [
      {
        "id": "97d22a88-6d25-5947-a7b6-61b3dc668057",
        "blockchain": "ETH-GOERLI",
        "tokenId": "3495b830-d0f9-524b-89c0-4408274fed6e",
        "walletId": "01899cf2-d415-7052-a207-f9862157e546",
        "sourceAddress": "0x6e5eaf34c73d1cd0be4e24f923b97cf38e10d1f3",
        "destinationAddress": "0x075e62c80e55d024cfd8fd4e3d1184834461db57",
        "transactionType": "INBOUND",
        "custodyType": "ENDUSER",
        "state": "CONFIRMED",
        "amounts": [
          "0.0788"
        ],
        "nfts": null,
        "txHash": "0xdd2f81a78605dcad759265c703fb2b4c507c5ea100319338422714bfcde77225",
        "blockHash": "0x4df6092fdb868331614771ff11944b43051cf6ed1067f8cfa55e9d40ef61426b",
        "blockHeight": 9423950,
        "networkFee": "",
        "firstConfirmDate": "2023-07-28T19:07:24Z",
        "operation": "TRANSFER",
        "userId": "2f1dcb5e-312a-4b15-8240-abeffc0e3463",
        "abiParameters": null,
        "createDate": "2023-07-28T19:07:34Z",
        "updateDate": "2023-07-28T19:07:37Z"
      }
    ]
  }
}

What’s Next

Congratulations! You’ve received your first transaction to your user-controlled wallet. To learn how to make a transfer out of your user-controlled wallet, check out the next guide.