---
title: "Send Ethereum ERC-20 tokens from a virtual account to the blockchain"
method: POST
path: "/v3/offchain/ethereum/erc20/transfer"
tags: ["Blockchain operations"]
---

# Send Ethereum ERC-20 tokens from a virtual account to the blockchain

`POST /v3/offchain/ethereum/erc20/transfer`

## Request

- Base URL: `https://api.tatum.io`
- URL: `https://api.tatum.io/v3/offchain/ethereum/erc20/transfer`
- Auth: API key in header `x-api-key`

/v3/offchain/ethereum/erc20/transfer

#### 4 credits per API call.

  

Send Ethereum ERC-20 tokens from a virtual account to the blockchain. This will create Tatum internal withdrawal request with ID. If every system works as expected, withdrawal request is marked as complete and transaction id is assigned to it.

*   If Ethereum server connection is unavailable, withdrawal request is cancelled.
*   If blockchain transfer is successful, but is it not possible to reach Tatum, transaction id of blockchain transaction is returned and withdrawal request must be completed manually, otherwise all other withdrawals will be pending.

It is possible to perform ledger to blockchain transaction for ledger accounts without blockchain address assigned to them.  
This operation needs the private key of the blockchain address. Every time the funds are transferred, the transaction must be signed with the corresponding private key. No one should ever send it's own private keys to the internet because there is a strong possibility of stealing keys and losing funds. In this method, it is possible to enter privateKey or signatureId. PrivateKey should be used only for quick development on testnet versions of blockchain when there is no risk of losing funds. In production, [Tatum KMS](https://github.com/tatumio/tatum-kms) should be used for the highest security standards, and signatureId should be present in the request. Alternatively, using the Tatum client library for supported languages.

## Request body

- union
  - TransferErc20
    - `senderAccountId` string, required: Sender account ID
    - `address` string, required: Blockchain address to send ERC20 token to
    - `amount` string, required: Amount to be sent.
    - `compliant` boolean: Compliance check, if withdrawal is not compliant, it will not be processed.
    - `gasLimit` string: Gas limit for transaction in gas price. If not set, automatic calculation will be used.
    - `gasPrice` string: Gas price in Gwei. If not set, automatic calculation will be used.
    - `privateKey` string, required: Private key of sender address. Either mnemonic and index, privateKey or signature Id must be present - depends on the type of account and xpub.
    - `nonce` number: The nonce to be set to the transaction; if not present, the last known nonce will be used
    - `paymentId` string: Identifier of the payment, shown for created Transaction within Tatum sender account.
    - `senderNote` string: Note visible to owner of withdrawing account
  - TransferErc20Mnemonic
    - `senderAccountId` string, required: Sender account ID
    - `address` string, required: Blockchain address to send ERC20 token to
    - `amount` string, required: Amount to be sent.
    - `compliant` boolean: Compliance check, if withdrawal is not compliant, it will not be processed.
    - `gasLimit` string: Gas limit for transaction in gas price. If not set, automatic calculation will be used.
    - `gasPrice` string: Gas price in Gwei. If not set, automatic calculation will be used.
    - `mnemonic` string, required: Mnemonic to generate private key for sender address. Either mnemonic and index, or privateKey must be present - depends on the type of account and xpub.
    - `index` integer, required: Derivation index of sender address.
    - `nonce` number: The nonce to be set to the transaction; if not present, the last known nonce will be used
    - `paymentId` string: Identifier of the payment, shown for created Transaction within Tatum sender account.
    - `senderNote` string: Note visible to owner of withdrawing account
  - TransferErc20KMS
    - `senderAccountId` string, required: Sender account ID
    - `address` string, required: Blockchain address to send ERC20 token to
    - `amount` string, required: Amount to be sent.
    - `compliant` boolean: Compliance check, if withdrawal is not compliant, it will not be processed.
    - `gasLimit` string: Gas limit for transaction in gas price. If not set, automatic calculation will be used.
    - `gasPrice` string: Gas price in Gwei. If not set, automatic calculation will be used.
    - `signatureId` string, uuid, required: Identifier of the mnemonic / private key associated in signing application. When hash identifies mnemonic, index must be present to represent specific account to pay from. Private key, mnemonic or signature Id must be present.
    - `index` integer: Derivation index of sender address.
    - `nonce` number: The nonce to be set to the transaction; if not present, the last known nonce will be used
    - `paymentId` string: Identifier of the payment, shown for created Transaction within Tatum sender account.
    - `senderNote` string: Note visible to owner of withdrawing account

## Response `200`

OK

- union
  - OffchainTransactionResult
    - `id` string, required: ID of withdrawal. If transaction is not valid in blockchain, use this id to cancel withdrawal.
    - `txId` string, required: TX hash of successful transaction.
    - `completed` boolean, required: If set to "true", the withdrawal has been completed in the virtual account; if set to "false", the withdrawal has not been completed and you have to <a href="https://apidoc.tatum.io/tag/Withdrawal#operation/completeWithdrawal" target="_blank">complete it manually</a>
  - OffchainTransactionSignatureResult
    - `signatureId` string, uuid, required: ID of prepared payment template to sign. This is should be stored on a client side to retrieve ID of the blockchain transaction, when signing application signs the transaction and broadcasts it to the blockchain.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized. Not valid or inactive subscription key present in the HTTP Header.
- `403`: Forbidden. The request is authenticated, but it is not possible to required perform operation due to logical error or invalid permissions.
- `500`: Internal server error. There was an error on the server during the processing of the request.

---

[API](https://skmtc.dev/tatum/apis/virtual-accounts.md) - [All operations](https://skmtc.dev/tatum/apis/virtual-accounts/llms.txt) - [OpenAPI document](https://skmtc.dev/tatum/apis/virtual-accounts/revisions/ba220553084b?raw)
