> ## Documentation Index
> Fetch the complete documentation index at: https://docs.primevault.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a Transfer

> Send assets from a source to a destination.

**POST** `/api/external/transactions/`

Use a transfer when you already know the source, destination, blockchain, asset, and amount. You can [estimate the network fee](/transactions/estimate-transfer-fee) first. The returned `status` is the lifecycle source of truth.

## Request body

<ParamField body="source" type="TransferPartyData" required>
  Sending party.
</ParamField>

<ParamField body="destination" type="TransferPartyData" required>
  Receiving party.
</ParamField>

<ParamField body="amount" type="string" required>
  Decimal transfer amount.
</ParamField>

<ParamField body="asset" type="string" required>
  Asset symbol.
</ParamField>

<ParamField body="blockChain" type="string" required>
  Blockchain identifier.
</ParamField>

<ParamField body="category" type="string" required>
  Must be `"TRANSFER"`.
</ParamField>

<ParamField body="externalId" type="string">
  Client reference.
</ParamField>

<ParamField body="memo" type="string">
  Human-readable note.
</ParamField>

<ParamField body="feePayer" type="object">
  Vault that pays the network fee when the chain supports sponsored fee payment.

  <Expandable title="Properties">
    <ParamField body="feePayer.id" type="string" required>
      Vault ID that will pay the fee.
    </ParamField>
  </Expandable>
</ParamField>

<Note>
  The SDK accepts `chain` and serializes it as `blockChain`. It injects `category: "TRANSFER"`.
</Note>

## Response

Returns the new [Transaction](/api-basics/data-models#transaction). Its `status` is the lifecycle source of truth.

<ResponseField name="id" type="string">
  Transaction ID. Use it with [Retrieve Transaction](/transactions/retrieve-transaction) to track status.
</ResponseField>

<ResponseField name="orgId" type="string">
  Organization that owns the transaction.
</ResponseField>

<ResponseField name="vaultId" type="string">
  Vault the transaction runs from.
</ResponseField>

<ResponseField name="status" type="string">
  Lifecycle status. Track it until `COMPLETED`, `FAILED`, or `DECLINED`. See [TransactionStatus](/api-basics/data-models#transactionstatus).
</ResponseField>

<ResponseField name="transactionType" type="string">
  See [TransactionType](/api-basics/data-models#transactiontype).
</ResponseField>

<ResponseField name="category" type="string">
  For example `TRANSFER` or `CONTRACT_CALL`. See [TransactionCategory](/api-basics/data-models#transactioncategory).
</ResponseField>

<ResponseField name="subCategory" type="string">
  See [TransactionSubCategory](/api-basics/data-models#transactionsubcategory).
</ResponseField>

<ResponseField name="createdAt" type="string">
  Creation timestamp (ISO 8601).
</ResponseField>

<ResponseField name="updatedAt" type="string">
  Last update timestamp (ISO 8601).
</ResponseField>

<ResponseField name="isDeleted" type="boolean">
  Whether the transaction is deleted.
</ResponseField>

<ResponseField name="externalId" type="string">
  Your own reference, if you set one.
</ResponseField>

<ResponseField name="memo" type="string">
  Memo you attached, if any.
</ResponseField>

<ResponseField name="source" type="TransferPartyData">
  Where the funds come from. Which fields are present depends on `type`. See [TransferPartyData](/api-basics/data-models#transferpartydata).

  <Expandable title="Properties">
    <ResponseField name="type" type="string">
      `VAULT`, `BANK_ACCOUNT`, `CONTACT`, `EXTERNAL_ADDRESS`, or `EXTERNAL_BANK_ACCOUNT`.
    </ResponseField>

    <ResponseField name="id" type="string">
      ID of the vault, bank account, or contact.
    </ResponseField>

    <ResponseField name="name" type="string">
      Display name.
    </ResponseField>

    <ResponseField name="address" type="string">
      Wallet address, for crypto parties.
    </ResponseField>

    <ResponseField name="chain" type="string">
      Blockchain, for crypto parties.
    </ResponseField>

    <ResponseField name="paymentRail" type="string">
      Payment rail, for bank parties, such as `ACH`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="destination" type="TransferPartyData">
  Where the funds go. Same fields as `source`. See [TransferPartyData](/api-basics/data-models#transferpartydata).

  <Expandable title="Properties">
    <ResponseField name="type" type="string">
      `VAULT`, `BANK_ACCOUNT`, `CONTACT`, `EXTERNAL_ADDRESS`, or `EXTERNAL_BANK_ACCOUNT`.
    </ResponseField>

    <ResponseField name="id" type="string">
      ID of the vault, bank account, or contact.
    </ResponseField>

    <ResponseField name="name" type="string">
      Display name.
    </ResponseField>

    <ResponseField name="address" type="string">
      Wallet address, for crypto parties.
    </ResponseField>

    <ResponseField name="chain" type="string">
      Blockchain, for crypto parties.
    </ResponseField>

    <ResponseField name="paymentRail" type="string">
      Payment rail, for bank parties, such as `ACH`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="blockChain" type="string">
  Chain the transaction runs on.
</ResponseField>

<ResponseField name="asset" type="string">
  Asset moved.
</ResponseField>

<ResponseField name="amount" type="string">
  Amount as a decimal string.
</ResponseField>

## Approve the transaction

New transfers return `status: "PENDING"` and wait for approval. [Get the approval message](/approvals/get-approval-message) for the transaction `id`, sign it with your API user's key, then [submit the approval](/approvals/submit-approval-action). See [Approvals](/approvals/overview).

With the SDK, `createTransactionWithApproval(request)` creates and approves in one call. `createTransferTransaction(request)` only creates.

<RequestExample dropdown>
  ```json Request example theme={null}
  {
    "source": { "type": "VAULT", "id": "vault_123" },
    "destination": { "type": "CONTACT", "id": "contact_456" },
    "amount": "0.50",
    "asset": "ETH",
    "blockChain": "ETHEREUM",
    "category": "TRANSFER",
    "externalId": "invoice-1001",
    "memo": "Vendor payout #1001",
    "feePayer": { "id": "vault_234" }
  }
  ```

  ```bash cURL theme={null}
  # Sample only. Generate a new signed token for each request
  # (see Authentication). Tokens expire after 120 seconds.
  curl --request POST \
    --url "https://api.primevault.com/api/external/transactions/" \
    --header "Authorization: Bearer <signed JWT>" \
    --header "Api-Key: <API key>" \
    --header "Content-Type: application/json" \
    --data '{
      "source": { "type": "VAULT", "id": "vault_123" },
      "destination": { "type": "CONTACT", "id": "contact_456" },
      "amount": "0.50",
      "asset": "ETH",
      "blockChain": "ETHEREUM",
      "category": "TRANSFER",
      "externalId": "invoice-1001",
      "memo": "Vendor payout #1001",
      "feePayer": { "id": "vault_234" }
    }'
  ```

  ```typescript JavaScript SDK theme={null}
  interface CreateTransferTransactionRequest {
    source: TransferPartyData;
    destination: TransferPartyData;
    amount: string;
    asset: string;
    chain: string;
    externalId?: string;
    memo?: string;
    feePayer?: { id: string };
  }

  createTransferTransaction(
    request: CreateTransferTransactionRequest,
  ): Promise<Transaction>

  const tx = await apiClient.createTransferTransaction({
    source: { type: "VAULT", id: "vault_123" },
    destination: { type: "CONTACT", id: "contact_456" },
    amount: "0.50",
    asset: "ETH",
    chain: "ETHEREUM",
    externalId: "invoice-1001",
    memo: "Vendor payout #1001",
    feePayer: { id: "vault_234" },
  });
  console.log(tx.id, tx.status);
  ```
</RequestExample>

<ResponseExample dropdown>
  ```json Response example theme={null}
  {
    "id": "transaction_123",
    "orgId": "org_456",
    "vaultId": "vault_123",
    "status": "PENDING",
    "transactionType": "OUTGOING",
    "category": "TRANSFER",
    "subCategory": "EXTERNAL_TRANSFER",
    "createdAt": "2026-08-04T10:40:00Z",
    "updatedAt": "2026-08-04T10:40:00Z",
    "isDeleted": false,
    "externalId": "invoice-1001",
    "memo": "Vendor payout #1001",
    "source": {
      "type": "VAULT",
      "id": "vault_123",
      "subOrgId": "sub_org_123",
      "name": "Treasury Vault"
    },
    "destination": {
      "type": "CONTACT",
      "id": "contact_456",
      "name": "Operations Wallet",
      "address": "0xAbC1234567890abcdef1234567890abcdef1234",
      "chain": "ETHEREUM"
    },
    "blockChain": "ETHEREUM",
    "asset": "ETH",
    "amount": "0.50"
  }
  ```

  ```typescript JavaScript SDK theme={null}
  interface Transaction {
    id: string;
    orgId: string;
    vaultId: string;
    status: TransactionStatus | string;
    transactionType: TransactionType | string;
    category: TransactionCategory | string;
    subCategory: TransactionSubCategory | string;
    createdAt: string;
    updatedAt: string;
    isDeleted: boolean;
    amount: string;

    txHash?: string;
    error?: string;
    externalId?: string;
    createdById?: string;
    fees?: Fees;
    memo?: string;
    txnSignature?: string;
    txnSignatureData?: Record<string, unknown>;
    output?: TransactionOutput;
    amountInUSD?: string;
    nonce?: number;
    dAppId?: string;
    source?: TransferPartyData;
    destination?: TransferPartyData;
    quoteResponse?: QuoteResponseItem;
    depositInstructions?: DepositInstructions;
    operations?: TransactionOperation[];
    balanceChanges?: TransactionOperationBalanceChanges | null;
    blockChain?: string;
    asset?: string;

    /** Deprecated: use destination.address. */
    toAddress?: string;
    /** Deprecated: use destination.name. */
    toAddressName?: string;
    /** Deprecated: use destination.id. */
    toVaultId?: string;
    /** Deprecated: use source.address. */
    sourceAddress?: string;
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.