Creating a FlowLink

Create a FlowLink with POST /flowlink by specifying an immutable source, destination, and receiver. Movmint returns a persistent deposit address. Examples in Go, TypeScript, Java, Rust, and Python.

Overview

POST /flowlink creates a FlowLink and returns the generated persistent DLT deposit address. The source, destination, and receiver fields are immutable once created.

POST https://api.sandbox.movmint.io/flowlink
Authorization: Bearer <access_token>
x-idempotency-key: <uuid>
Content-Type: application/json

Request

FieldRequiredDescription
source.assetyesSource asset: USDC, EURC, ETH, or BTC.
source.networkyesSource network: ethereum, base, solana, or bitcoin.
destination.typeyesCARD, BANK_ACCOUNT, or DLT_WALLET.
destination.assetyesTarget asset: USD, CAD, BSD, SD, USDC, ETH, or BTC.
destination.detailsyesType-specific delivery details (see below).
receiver.nameyesReceiver's name.
receiver.addressyesReceiver's postal address (street, city, postal_code, country required; state optional).
metadatanoArbitrary client-provided key/value data.

You must have an active Product subscription for the source/destination asset pair, or creation fails with 402.

Destination details by type

DLT_WALLET

{ "wallet_address": "0xfeed...", "network": "ethereum" }

network is one of ethereum, base, solana, bitcoin, sanddollar.

BANK_ACCOUNT

{
  "routing_number": "987654321",
  "account_number": "123456789",
  "account_holder_name": "Acme Corp",
  "account_holder_address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" },
  "bank_name": "Example Bank"
}

CARD

{
  "card_number": "4111111111111111",
  "cardholder_name": "Acme Corp",
  "cardholder_address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" }
}
📘

Sensitive data

Card and bank account numbers are submitted in plaintext over TLS, encrypted at rest, and masked on responses (e.g., 411111******1111). The receiver and account_holder/cardholder addresses use ISO 3166-1 alpha-2 country codes.

Code examples

The examples create a FlowLink that converts incoming USDC (Ethereum) to USD and delivers it to a bank account.

cURL

curl -X POST https://api.sandbox.movmint.io/flowlink \
  -H "Authorization: Bearer <access_token>" \
  -H "x-idempotency-key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "asset": "USDC", "network": "ethereum" },
    "destination": {
      "type": "BANK_ACCOUNT",
      "asset": "USD",
      "details": {
        "routing_number": "987654321",
        "account_number": "123456789",
        "account_holder_name": "Acme Corp",
        "account_holder_address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" },
        "bank_name": "Example Bank"
      }
    },
    "receiver": {
      "name": "Acme Corp",
      "address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" }
    },
    "metadata": { "purpose": "treasury-sweep" }
  }'

Go

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"

	"github.com/google/uuid"
)

const baseURL = "https://api.sandbox.movmint.io"

func main() {
	token := "<access_token>"

	body := map[string]any{
		"source": map[string]any{"asset": "USDC", "network": "ethereum"},
		"destination": map[string]any{
			"type":  "BANK_ACCOUNT",
			"asset": "USD",
			"details": map[string]any{
				"routing_number":      "987654321",
				"account_number":      "123456789",
				"account_holder_name": "Acme Corp",
				"account_holder_address": map[string]any{
					"street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS",
				},
				"bank_name": "Example Bank",
			},
		},
		"receiver": map[string]any{
			"name": "Acme Corp",
			"address": map[string]any{
				"street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS",
			},
		},
		"metadata": map[string]any{"purpose": "treasury-sweep"},
	}

	payload, _ := json.Marshal(body)
	req, _ := http.NewRequest(http.MethodPost, baseURL+"/flowlink", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("x-idempotency-key", uuid.NewString())
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	out, _ := io.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusCreated {
		log.Fatalf("create flowlink failed (%d): %s", resp.StatusCode, out)
	}
	fmt.Println(string(out))
}

TypeScript

import { randomUUID } from "crypto";

const BASE_URL = "https://api.sandbox.movmint.io";

async function createFlowLink(token: string) {
  const res = await fetch(`${BASE_URL}/flowlink`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "x-idempotency-key": randomUUID(),
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      source: { asset: "USDC", network: "ethereum" },
      destination: {
        type: "BANK_ACCOUNT",
        asset: "USD",
        details: {
          routing_number: "987654321",
          account_number: "123456789",
          account_holder_name: "Acme Corp",
          account_holder_address: { street: "1 Main St", city: "Nassau", postal_code: "00000", country: "BS" },
          bank_name: "Example Bank",
        },
      },
      receiver: {
        name: "Acme Corp",
        address: { street: "1 Main St", city: "Nassau", postal_code: "00000", country: "BS" },
      },
      metadata: { purpose: "treasury-sweep" },
    }),
  });

  if (res.status !== 201) {
    throw new Error(`Create FlowLink failed (${res.status}): ${await res.text()}`);
  }
  return res.json();
}

console.log(await createFlowLink("<access_token>"));

Java

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;

public class CreateFlowLink {

    private static final String BASE_URL = "https://api.sandbox.movmint.io";

    public static void main(String[] args) throws Exception {
        String token = "<access_token>";
        String payload = """
            {
              "source": { "asset": "USDC", "network": "ethereum" },
              "destination": {
                "type": "BANK_ACCOUNT",
                "asset": "USD",
                "details": {
                  "routing_number": "987654321",
                  "account_number": "123456789",
                  "account_holder_name": "Acme Corp",
                  "account_holder_address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" },
                  "bank_name": "Example Bank"
                }
              },
              "receiver": {
                "name": "Acme Corp",
                "address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" }
              },
              "metadata": { "purpose": "treasury-sweep" }
            }
            """;

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/flowlink"))
                .header("Authorization", "Bearer " + token)
                .header("x-idempotency-key", UUID.randomUUID().toString())
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

        HttpResponse<String> response = client.send(
                request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 201) {
            throw new RuntimeException("Create FlowLink failed (" + response.statusCode()
                    + "): " + response.body());
        }
        System.out.println(response.body());
    }
}

Rust

use serde_json::json;
use uuid::Uuid;

const BASE_URL: &str = "https://api.sandbox.movmint.io";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "<access_token>";

    let body = json!({
        "source": { "asset": "USDC", "network": "ethereum" },
        "destination": {
            "type": "BANK_ACCOUNT",
            "asset": "USD",
            "details": {
                "routing_number": "987654321",
                "account_number": "123456789",
                "account_holder_name": "Acme Corp",
                "account_holder_address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" },
                "bank_name": "Example Bank"
            }
        },
        "receiver": {
            "name": "Acme Corp",
            "address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" }
        },
        "metadata": { "purpose": "treasury-sweep" }
    });

    let client = reqwest::Client::new();
    let resp = client
        .post(format!("{BASE_URL}/flowlink"))
        .bearer_auth(token)
        .header("x-idempotency-key", Uuid::new_v4().to_string())
        .json(&body)
        .send()
        .await?;

    if resp.status().as_u16() != 201 {
        let status = resp.status();
        return Err(format!("create flowlink failed ({status}): {}", resp.text().await?).into());
    }

    let data: serde_json::Value = resp.json().await?;
    println!("{}", serde_json::to_string_pretty(&data)?);
    Ok(())
}

Python

import uuid
import requests

BASE_URL = "https://api.sandbox.movmint.io"


def create_flowlink(token: str) -> dict:
    resp = requests.post(
        f"{BASE_URL}/flowlink",
        headers={
            "Authorization": f"Bearer {token}",
            "x-idempotency-key": str(uuid.uuid4()),
            "Content-Type": "application/json",
        },
        json={
            "source": {"asset": "USDC", "network": "ethereum"},
            "destination": {
                "type": "BANK_ACCOUNT",
                "asset": "USD",
                "details": {
                    "routing_number": "987654321",
                    "account_number": "123456789",
                    "account_holder_name": "Acme Corp",
                    "account_holder_address": {
                        "street": "1 Main St", "city": "Nassau",
                        "postal_code": "00000", "country": "BS",
                    },
                    "bank_name": "Example Bank",
                },
            },
            "receiver": {
                "name": "Acme Corp",
                "address": {
                    "street": "1 Main St", "city": "Nassau",
                    "postal_code": "00000", "country": "BS",
                },
            },
            "metadata": {"purpose": "treasury-sweep"},
        },
        timeout=30,
    )
    resp.raise_for_status()  # expects 201
    return resp.json()


print(create_flowlink("<access_token>"))

Example response (201)

{
  "flowlink_id": "2b7a1f4c-9d8e-4a3b-bc12-3456789abcde",
  "organization_id": "1a2b3c4d-5e6f-7081-92a3-b4c5d6e7f809",
  "user_id": "0f9e8d7c-6b5a-4321-fedc-ba9876543210",
  "status": "active",
  "source": {
    "asset": "USDC",
    "network": "ethereum",
    "deposit_address": "0xabc123def4567890abc123def4567890abc12345",
    "deposit_address_id": "dpa_01H..."
  },
  "destination": {
    "type": "BANK_ACCOUNT",
    "asset": "USD",
    "details": {
      "routing_number": "987654321",
      "account_number": "*****6789",
      "account_holder_name": "Acme Corp",
      "bank_name": "Example Bank"
    }
  },
  "receiver": { "name": "Acme Corp", "address": { "street": "1 Main St", "city": "Nassau", "postal_code": "00000", "country": "BS" } },
  "metadata": { "purpose": "treasury-sweep" },
  "created_at": "2026-06-24T12:00:00Z",
  "updated_at": "2026-06-24T12:00:00Z"
}

Store flowlink_id (for lifecycle management and transactions) and source.deposit_address (where depositors send funds). The address is persistent and reusable.

Error responses

HTTPCause
400Invalid request parameters.
402No active Product subscription for the source/destination asset pair.
409A FlowLink with an equivalent configuration already exists.
500Internal server error — retry with backoff.

Next steps

Continue to Using a FlowLink to send deposits, manage the lifecycle, and read transaction history.


Did this page help you?