---
title: "Initiate a transfer from a Link account"
method: POST
path: "/api/link/v1/enterprises/{enterpriseId}/accounts/{accountId}/transfers"
tags: ["Link Transfers"]
---

# Initiate a transfer from a Link account

`POST /api/link/v1/enterprises/{enterpriseId}/accounts/{accountId}/transfers`

## Request

- Base URL: `https://developers.bitgo.com`
- URL: `https://developers.bitgo.com/api/link/v1/enterprises/{enterpriseId}/accounts/{accountId}/transfers`
- Auth: none declared. Required headers: `user-id`

The destination kind is selected by `destination.kind` and dispatched
server-side. Supported kinds today: on-chain address (`'address'`) and
BitGo wallet (`'wallet'`).

## Path parameters

- `enterpriseId` string, required
- `accountId` string, required

## Headers

- `user-id` string, required

## Request body

- object: Transfer initiation request body. Carries the amount, the asset to move (as a `(genericAsset, network)` pair), the optional venue sub-account bucket, and the discriminated `destination` describing where the funds should land.
  - `externalId` string, required: Client-supplied idempotency key, scoped to the source `accountId`. Two requests with the same `externalId` and identical hard fields (amount, asset, network, destination, …) resolve to the same `LinkTransfer` — the second call is reconciled against the first and the venue is **not** charged twice. A retry that disagrees on any hard field returns 409 `TransferIdempotencyConflict`. Required. Callers should generate a stable identifier (e.g. UUIDv4) per logical transfer and reuse it across retries.
  - `amount` string, required: Amount to withdraw in Big Units (always positive — direction is implied).
  - `genericAsset` string, required: Generic asset symbol (chain-agnostic, e.g. `usdc`). Paired with `network` the service resolves a venue-specific raw asset. Using a generic-asset + network pair (rather than a BitGo concrete symbol) lets the endpoint support assets BitGo doesn't yet carry a concrete symbol for.
  - `accountSubType` string: Optional venue sub-account / bucket (e.g. `SPOT` vs `MARGIN`). Required for venues that hold balances across multiple sub-types where the caller needs to disambiguate which bucket to debit. When omitted, the venue's default sub-account is used.
  - `destination` union, required: Discriminated union of every supported transfer destination. New destination kinds (internal Link account, etc.) join this union as separate variants — the service dispatches on `kind` to pick the per-kind subroutine.
    - TransferAddressDestination: On-chain address destination — withdraws to an arbitrary blockchain address. `memo` is optional and used by chains that require an extra routing tag (XRP destination tag, XLM memo, BNB memo, etc.).
      - `kind` 'address', required
      - `toAddress` string, required
      - `network` string, required: Network identifier (e.g. `ethereum`, `bitcoin`).
      - `memo` string
    - TransferWalletDestination: BitGo wallet destination — withdraws to the on-chain deposit address associated with the given walletId + asset. The caller never needs to know the actual on-chain address; the service resolves it automatically.
      - `kind` 'wallet', required
      - `walletId` string, required
      - `network` string, required: Network identifier (e.g. `ethereum`, `bitcoin`).
    - TransferAccountDestination: Internal Link account destination — moves funds between two Link accounts at the same venue.
      - `kind` 'account', required
      - `accountId` string, required
      - `accountSubType` string
  - `venueOtp` string: Venue-specific one-time password (TOTP code). Required only when the venue has OTP withdrawal protection enabled. When omitted and the venue requires OTP, the transfer is created with `status: "pending_otp"` and `reason.code: "OtpRequired"`. Call the retry endpoint with a fresh code to proceed.
  - `notes` string

## Response `201`

Created

- V1TransferResponse: Single transfer response object
  - `id` string, required
  - `accountId` string, required
  - `status` 'pending_policy_evaluation' | 'processing' | 'pending_approval' | 'pending' | 'completed' | 'failed' | 'failed_retriable' | 'pending_otp' | 'canceled' | 'rejected', required
  - `amount` string, required
  - `genericAsset` string
  - `rawAsset` string, required
  - `displayAsset` string, required
  - `rawNetwork` string
  - `fromAsset` string
  - `fromNetwork` string
  - `fromId` string
  - `fromType` 'address' | 'bitgo_wallet' | 'link_account' | 'venue_account'
  - `toAsset` string
  - `toNetwork` string
  - `toId` string
  - `toType` 'address' | 'bitgo_wallet' | 'link_account' | 'venue_account'
  - `toMemo` string: Destination memo / destination tag for this transfer, stored verbatim at initiation: an explicit `destination.memo`, or the `?dt=`-style suffix parsed off `toAddress` (`toId` keeps the raw address with the suffix). Absent for chains without memos and for transfers that predate memo capture.
  - `initiatedBy` string
  - `fromName` string
  - `toName` string
  - `fromVenueId` string
  - `toVenueId` string
  - `accountSubType` string: Normalized sub-account-type for the transfer's owning Link account. Absent when a sub-type could not be determined. For pass-through values (no matching venue configuration), this carries the raw venue label and `rawAccountSubType` / `accountSubTypeLabel` are absent.
  - `rawAccountSubType` string: Venue-raw sub-type label, projected from venue config. Absent for pass-through values.
  - `accountSubTypeLabel` string: Human-readable sub-type display label, projected from venue config. Absent for single-sub-type venues or pass-through values.
  - `fromAccountSubType` string: Source-leg normalized sub-account-type. Only set for `link_account` legs that ingested with a sub-type.
  - `fromRawAccountSubType` string
  - `fromAccountSubTypeLabel` string
  - `toAccountSubType` string: Destination-leg normalized sub-account-type. Only set for `link_account` legs that ingested with a sub-type.
  - `toRawAccountSubType` string
  - `toAccountSubTypeLabel` string
  - `cryptoDetail` object: Crypto detail response for a transfer
    - `confirmations` number
    - `createdAt` string, date-time, required
    - `feeAmount` string
    - `feeAsset` string
    - `feeNetwork` string
    - `feeRawAsset` string
    - `feeRawNetwork` string
    - `fromAddress` string
    - `hash` string, required
    - `id` string, required
    - `linkTransferId` string, required
    - `status` 'unconfirmed' | 'confirmed' | 'failed' | 'canceled' | 'unknown', required
    - `toAddress` string
    - `toMemo` string: Destination memo / destination tag captured for this crypto leg: an explicit `destination.memo`, or the `?dt=`-style suffix parsed off `toAddress`. Absent for chains without memos or when the leg carries none.
    - `updatedAt` string, date-time, required
  - `bitgoDetail` object: BitGo detail response for a transfer
    - `bitgoWalletAddress` string
    - `createdAt` string, date-time, required
    - `evaluationId` string
    - `id` string, required
    - `linkTransferId` string, required
    - `pendingApprovalId` string
    - `transactionRequestId` string
    - `transferId` string
    - `updatedAt` string, date-time, required
    - `walletId` string
  - `venueDetail` object: Venue detail response for a transfer
    - `createdAt` string, date-time, required
    - `id` string, required
    - `linkTransferId` string, required
    - `updatedAt` string, date-time, required
    - `venueCreatedDate` string, date-time, required
    - `venueModifiedDate` string, date-time, required
    - `venueTransactionId` string
    - `venueTransferId` string
  - `reason` object: Normalized failure context. Set when `status` is `failed` (terminal), `failed_retriable` (the venue rejected this attempt but the same transfer can be retried under the same `externalId` once external state changes), or `pending_otp` (the venue requires a TOTP code the user must supply; call the retry endpoint with `venueOtp` to proceed). `code` is a stable string the caller can branch on; `message` is a human-readable description from the venue.
    - `code` string, required
    - `message` string, required
  - `notes` string
  - `sortTimestamp` string, date-time
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `409`: Conflict
- `422`: Unprocessable Entity
- `451`: Unavailable For Legal Reasons
- `500`: Internal Server Error

## Changes

> 57 revisions in range; 1 not diffed.

- **2026-10-15** `296f3ff58f6f`: 1 warning, 2 info
  - added the new `pending_otp` enum value to the `status` response property for the response status `201`
  - added the optional property `cryptoDetail/toMemo` to the response with the `201` status
  - added the optional property `toMemo` to the response with the `201` status
- **2026-09-24** `b3e9978eb1f7`: 1 info
  - added the non-success response with the status `451`
- **2026-08-13** `996b41eb1818`: 2 info
  - added the new optional request property `notes`
  - added the optional property `notes` to the response with the `201` status

[Operation history](https://skmtc.dev/bitgo/apis/bitgo-api/changes/api/link/v1/enterprises/:enterpriseId/accounts/:accountId/transfers/post.md)

---

[API](https://skmtc.dev/bitgo/apis/bitgo-api.md) - [All operations](https://skmtc.dev/bitgo/apis/bitgo-api/llms.txt) - [OpenAPI document](https://skmtc.dev/bitgo/apis/bitgo-api/revisions/6b6e050a7f84?raw)
