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

# Get started with Flow payments

> Set up the JavaScript SDK for Flow payments, create a flow from your server, and complete a first wallet payment with submitFlowTransaction.

> [!NOTE]
>
> Fireblocks Flow is an enterprise feature. [Contact us](https://www.dynamic.xyz/book-a-call) to enable it for your environment.

This guide sets up the JavaScript SDK for [Flow payments](https://docs.dynamic.xyz/docs/flow/payments.md) and walks through a first payment from a connected wallet. Your server creates the flow, and the payer's page uses the SDK to attach a source, get a quote, and send the payment. The same setup covers every mode: `payment`, `deposit`, and `withdraw`.

## Prerequisites

* A Dynamic environment with Fireblocks Flow enabled.
* A Dynamic client created and initialized, as described in [Creating a Dynamic client](https://docs.dynamic.xyz/docs/javascript/reference/client/create-dynamic-client.md).
* A server that can call the Dynamic API. Your API token stays on that server.

## Enable chains in the Dynamic Console

Open **Chains & Networks** in the [Dynamic Console](https://console.dynamic.xyz/dashboard/chains-and-networks) and enable every chain your payers will pay from. Wallet payments support these chains:

| Chain | Console toggle | Extension package |
| :- | :- | :- |
| EVM (Ethereum, Base, Polygon, Arbitrum, etc.) | **EVM** | `@dynamic-labs-sdk/evm` |
| Solana | **Solana** | `@dynamic-labs-sdk/solana` |
| Bitcoin | **Bitcoin** | `@dynamic-labs-sdk/bitcoin` |
| Sui | **Sui** | `@dynamic-labs-sdk/sui` |
| TRON | **Tron** | `@dynamic-labs-sdk/tron` |

Each chain you enable appears when the payer connects a wallet. Deposit-address and exchange payments do not need a chain extension, because the payer pays outside your app. [Supported chains](https://docs.dynamic.xyz/docs/flow/supported-chains.md) lists the chains each payment source supports.

## Install chain extensions

Install the packages for the chains you enabled:

```bash theme={"system"}
npm install @dynamic-labs-sdk/evm @dynamic-labs-sdk/solana @dynamic-labs-sdk/bitcoin @dynamic-labs-sdk/sui @dynamic-labs-sdk/tron
```

Then add an extension for each chain when you create the client. Extensions register the wallet providers the SDK uses to find, connect, and sign with wallets on that chain.

```javascript theme={"system"}
import { createDynamicClient, initializeClient } from "@dynamic-labs-sdk/client";
import { addBitcoinExtension } from "@dynamic-labs-sdk/bitcoin";
import { addEvmExtension } from "@dynamic-labs-sdk/evm";
import { addWalletConnectEvmExtension } from "@dynamic-labs-sdk/evm/wallet-connect";
import { addSolanaExtension } from "@dynamic-labs-sdk/solana";
import { addWalletConnectSolanaExtension } from "@dynamic-labs-sdk/solana/wallet-connect";
import { addSuiExtension } from "@dynamic-labs-sdk/sui";
import { addTronExtension } from "@dynamic-labs-sdk/tron";

createDynamicClient({
  environmentId: "<YOUR_ENVIRONMENT_ID>",
});

// Add one extension per chain you enabled
addEvmExtension();
addSolanaExtension();
addBitcoinExtension();
addSuiExtension();
addTronExtension();

// Optional: let payers connect mobile wallets with a QR code
addWalletConnectEvmExtension();
addWalletConnectSolanaExtension();

initializeClient();
```

Add extensions only for the chains you enabled. The WalletConnect extensions are optional, and they let payers connect mobile wallets such as MetaMask Mobile or Phantom by scanning a QR code. [Adding extensions](https://docs.dynamic.xyz/docs/javascript/reference/adding-extensions.md) lists every extension.

## Create an API token

In the [Dynamic Console](https://console.dynamic.xyz), go to **Developer > API Tokens** and create a token with the `flow.write` scope. Your server uses it to create flows, and also to read and cancel them from the server and to manage fees.

Keep the token on your server and read it from an environment variable or a secrets manager. The payer's page never needs it: reading a flow and attaching a source need no credential, and attaching a source returns a session token that the SDK stores and sends for the rest of the payment. [Access and data](https://docs.dynamic.xyz/docs/flow/security.md) explains each credential.

## Create a flow from your server

Your server creates the flow and fixes its mode, amount, currency, settlement tokens, and destinations. The mode goes in the path. This example creates a `payment` flow for 25 USD that settles in USDC on Base, and reads the API token and environment ID from environment variables:

```bash theme={"system"}
curl --request POST \
  --url "https://app.dynamic.xyz/api/v0/server/$DYNAMIC_ENVIRONMENT_ID/flow/payment" \
  --header "Authorization: Bearer $DYNAMIC_API_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "amount": "25.00",
    "currency": "USD",
    "settlementConfig": {
      "strategy": "cheapest",
      "settlements": [
        {
          "chainName": "EVM",
          "chainId": "8453",
          "tokenAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "symbol": "USDC",
          "tokenDecimals": 6
        }
      ]
    },
    "destinationConfig": {
      "destinations": [
        { "chainName": "EVM", "type": "address", "identifier": "0xYourEvmDestinationAddress" }
      ]
    },
    "memo": { "orderId": "order_abc123" }
  }'
```

The response wraps the new flow in `flow`. Pass `flow.id` to the payer's page, where the SDK functions take it as `flowId`. Share the flow ID only with the payer, because it is enough to read the flow and to attach a source before the payment is sent.

The modes differ in who sets the amount:

| Mode | Amount |
| :- | :- |
| `payment` | Fixed when you create the flow, in `USD` or in `SETTLEMENT_TOKEN` when the flow has exactly one settlement token. |
| `deposit` | A suggestion. The payer can change it when they get a quote, as shown in [Deposit mode amount entry](https://docs.dynamic.xyz/docs/javascript/reference/flow-ui-guide.md#deposit-mode-amount-entry). |
| `withdraw` | Fixed in `USD`. Your platform pays out to the user and signs with its own wallet. |

The [Flow payments API guide](https://docs.dynamic.xyz/docs/flow/api.md#create-a-flow) lists every field of the create request.

> [!NOTE]
>
> **Optional: add your own fee.** Add a `feeConfig` to the create request to take a percentage of the payment for yourself or for your own customers. Recipients can be EVM or Solana addresses, with at most one recipient per address family. The fee applies to deposit-address payments and to wallet payments that need a swap. Direct wallet transfers and exchange payments carry no fee. [Adding your own fee](https://docs.dynamic.xyz/docs/flow/adding-your-own-fee.md) explains when the fee applies, and the [Fees API](https://docs.dynamic.xyz/docs/flow/fees.md) gives the config shape and how to claim fees.

> [!NOTE]
>
> **Optional: require an exact match.** Add `disableSwaps: true` when the payer must pay with a token and chain that already match one of your settlements. See [Conversions](https://docs.dynamic.xyz/docs/flow/conversions.md#requiring-an-exact-match).

## Send a first payment

On the payer's page, connect a wallet with your usual wallet connection UI, then attach it to the flow, get a quote, and send the payment with [`submitFlowTransaction`](https://docs.dynamic.xyz/docs/javascript/reference/client/submit-flow-transaction). `submitFlowTransaction` prepares the transaction, asks the wallet to sign and send it, and reports it to the flow.

```javascript theme={"system"}
import {
  attachFlowSource,
  getActiveNetworkId,
  getFlow,
  getFlowQuote,
  shouldPollFlow,
  submitFlowTransaction,
} from "@dynamic-labs-sdk/client";

const POLL_INTERVAL_MS = 3000;

const payWithWallet = async ({ flowId, walletAccount, fromTokenAddress }) => {
  // 1. Attach the connected wallet as the payment source
  const { networkId } = await getActiveNetworkId({ walletAccount });
  await attachFlowSource({
    flowId,
    sourceType: "wallet",
    fromAddress: walletAccount.address,
    fromChainName: walletAccount.chain,
    fromChainId: networkId,
  });

  // 2. Quote the token the payer chose; the quote is valid for 60 seconds
  const quoted = await getFlowQuote({ flowId, fromChainId: networkId, fromTokenAddress });
  // Show quoted.quote to the payer here and wait for them to confirm

  // 3. Prepare, sign, and report the transaction in one call
  let flow = await submitFlowTransaction({ flowId, walletAccount });

  // 4. Read the flow until it stops changing on its own
  while (shouldPollFlow({ flow })) {
    await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
    flow = await getFlow({ flowId });
  }

  return flow;
};
```

The payment is done when `flow.settlementState` is `completed`. A flow whose `executionState` is `source_confirmed` has received the payer's funds but has not finished delivering them, so keep reading it until settlement completes or fails. [Payment lifecycle and states](https://docs.dynamic.xyz/docs/flow/lifecycle-walkthrough.md) describes every state.

Decide fulfillment on your server, from [webhooks](https://docs.dynamic.xyz/docs/flow/webhooks.md) or a server read of the flow, rather than from what the payer's page reports. [Access and data](https://docs.dynamic.xyz/docs/flow/security.md#decide-fulfillment-on-your-server) explains why.

> [!TIP]
>
> **Using React on the web?** Instead of writing these steps, render the prebuilt [Flow payment widget](https://docs.dynamic.xyz/docs/javascript/building-ui/react-ui/flow-widget.md) with the flow ID. It connects the wallet, quotes, sends the payment, and shows the outcome, and it also offers exchange and deposit-address payments.

## Next steps

> [card] [Flow payment widget](https://docs.dynamic.xyz/docs/javascript/building-ui/react-ui/flow-widget.md)
>
> A prebuilt payment UI for React web apps.

> [card] [Build a custom payment UI](https://docs.dynamic.xyz/docs/javascript/reference/flow-ui-guide.md)
>
> Every payment source, quote refresh, errors, cancel, expiry, and reload.

> [card] [Handle Flow errors](https://docs.dynamic.xyz/docs/javascript/reference/flow-errors.md)
>
> The error classes each function throws and how to recover.

> [card] [Flow payments](https://docs.dynamic.xyz/docs/flow/payments.md)
>
> Modes, payment sources, and how you know a payment worked.

> [card] [Flow payments API guide](https://docs.dynamic.xyz/docs/flow/api.md)
>
> The HTTP requests behind each SDK function.


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