---
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`

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: "failed_retriable"` 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' | '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'
  - `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
    - `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) or `failed_retriable` (the venue rejected this attempt but the same transfer can be retried under the same `externalId` once external state changes). `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
- `500` — Internal Server Error

---

[API](https://skmtc.net/bitgo/apis/bitgo-api.md) · [All operations](https://skmtc.net/bitgo/apis/bitgo-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/bitgo/bitgo-api/revisions/e445c15e5bee/schema)
