Quote

Request an FX quote with POST /fx/quote. Covers required fields, participant and address requirements, and how to configure source and destination funding, with examples in Go, TypeScript, Java, Rust, and Python.

Overview

POST /fx/quote prices a conversion and returns a quote_id you can later capture to execute. The quote locks the rate (market rate plus your client-specific spread and fees) until valid_until.

POST https://api.sandbox.movmint.io/fx/quote
Authorization: Bearer <access_token>
x-idempotency-key: <uuid>
Content-Type: application/json
HeaderRequiredDescription
AuthorizationyesBearer <access_token> from Authentication.
x-idempotency-keyyesA UUID you generate. Reuse it on retries to guarantee at-most-once quote creation.

Required fields

The request body has four top-level parts:

FieldRequiredDescription
from_currencyyesSource currency/asset code (e.g., BSD, USDC).
to_currencyyesTarget currency/asset code (e.g., USDC, USD).
amountyesAmount to convert. Interpreted as the source amount when quote_model is fixed_source, or the target amount when fixed_target.
quote_modelnofixed_source (default) or fixed_target. See pricing models.
participantsyesThe people/organizations involved in the transaction (originator and beneficiary). See below.
tx_configurationyesReference data, purpose of payment, and the source/target funding configuration.

Participants

participants is an array describing who is sending and receiving. Each participant has a participant_type:

participant_typeMeaning
ULTIMATE_ORIGINATORThe party on whose behalf funds originate.
ORIGINATORThe sending party.
BENEFICIARYThe receiving party.
ULTIMATE_BENEFICIARYThe party who ultimately receives the funds.

Required for every participant: participant_type, email, phone_number, and address.

Additional requirements:

  • sur_name and given_name are required for BENEFICIARY and ULTIMATE_BENEFICIARY.
  • individual_date_of_birth is required when the participant is an individual (format YYYY-MM-DD).
  • organization_name is used instead of a personal name when the participant is a company.
  • national_identifier with national_identifier_type (one of SSN, TIN, EIN, PASSPORT, DRIVERS_LICENSE, NATIONAL_ID) supports compliance screening.

Address requirements

Participant address is a required free-text field carrying the participant's full postal address (street, city, state/region, postal code, country). It is used for compliance screening and, where the delivery rail requires it (push-to-card, bank transfers), is transmitted to the delivery provider. Provide a complete, accurate address — incomplete addresses can cause delivery rails to reject the transaction.

📘

Why participant and address data matters

Movmint screens every transaction for sanctions and risk. Originator and beneficiary identity and address data are required inputs to that screening and to the travel-rule obligations of the delivery rails. Supplying complete data up front avoids holds and rejections at capture/delivery time.

Purpose of payment

tx_configuration.purpose_of_payment classifies the transaction for compliance and reporting. It must be one of the platform's accepted values, for example: "Payroll Expenses", "Goods bought / Goods sold", "Contractor Payment", "International Money Transfer", "Fees for advisory, technical, academic or specialist assistance", "Tax Payment", "Insurance payment", among others. Choose the value that best describes the underlying purpose.

Source and destination funding

tx_configuration.source_configuration and tx_configuration.target_configuration describe how funds enter and leave the conversion. Each has a source_type and an account_configuration whose shape depends on that type.

📘

Field naming

Both source and target configurations use the field name source_type to indicate the rail. In target_configuration, source_type denotes the target rail.

BANK_ACCOUNT

{
  "source_type": "BANK_ACCOUNT",
  "account_configuration": {
    "account_number": "123456789",
    "routing_number": "987654321",
    "account_type": "CHECKING"
  }
}

account_type is CHECKING or SAVINGS.

CARD

{
  "source_type": "CARD",
  "account_configuration": {
    "card_number": "4111111111111111",
    "expiry_date": "12/2027",
    "card_type": "DebitCard"
  }
}

expiry_date is MM/YYYY. card_type is DebitCard.

DLT_WALLET

{
  "source_type": "DLT_WALLET",
  "account_configuration": {
    "wallet_address": "0x123456789abcdef",
    "network": "ethereum"
  }
}

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

CLIENT_BALANCE

{
  "source_type": "CLIENT_BALANCE",
  "account_configuration": {
    "client_account_id": "12345678901234567"
  }
}

Use a prefunded balance as source or target. The account's asset must match from_currency (as source) or to_currency (as target), and the account must belong to your organization. When used as source, Movmint checks available_balance >= amount at quote time and rejects the quote if the balance is insufficient.

Example request

Convert 1,000 BSD to USDC, funding from a bank account and delivering to a DLT wallet.

cURL

curl -X POST https://api.sandbox.movmint.io/fx/quote \
  -H "Authorization: Bearer <access_token>" \
  -H "x-idempotency-key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "from_currency": "BSD",
    "to_currency": "USDC",
    "amount": 1000,
    "quote_model": "fixed_source",
    "participants": [
      {
        "participant_type": "ORIGINATOR",
        "given_name": "Jane",
        "sur_name": "Doe",
        "email": "[email protected]",
        "phone_number": "+12425550100",
        "address": "123 Bay Street, Nassau, Bahamas",
        "national_identifier": "000-00-0000",
        "national_identifier_type": "TIN",
        "individual_date_of_birth": "1990-01-25"
      },
      {
        "participant_type": "BENEFICIARY",
        "given_name": "John",
        "sur_name": "Smith",
        "email": "[email protected]",
        "phone_number": "+12025550199",
        "address": "1600 Market Street, Philadelphia, PA 19103, USA"
      }
    ],
    "tx_configuration": {
      "client_reference_id": "invoice-4821",
      "purpose_of_payment": "Contractor Payment",
      "source_configuration": {
        "source_type": "BANK_ACCOUNT",
        "account_configuration": {
          "account_number": "123456789",
          "routing_number": "987654321",
          "account_type": "CHECKING"
        }
      },
      "target_configuration": {
        "source_type": "DLT_WALLET",
        "account_configuration": {
          "wallet_address": "0x123456789abcdef",
          "network": "ethereum"
        }
      }
    }
  }'

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{
		"from_currency": "BSD",
		"to_currency":   "USDC",
		"amount":        1000,
		"quote_model":   "fixed_source",
		"participants": []map[string]any{
			{
				"participant_type":         "ORIGINATOR",
				"given_name":               "Jane",
				"sur_name":                 "Doe",
				"email":                    "[email protected]",
				"phone_number":             "+12425550100",
				"address":                  "123 Bay Street, Nassau, Bahamas",
				"individual_date_of_birth": "1990-01-25",
			},
			{
				"participant_type": "BENEFICIARY",
				"given_name":       "John",
				"sur_name":         "Smith",
				"email":            "[email protected]",
				"phone_number":     "+12025550199",
				"address":          "1600 Market Street, Philadelphia, PA 19103, USA",
			},
		},
		"tx_configuration": map[string]any{
			"client_reference_id": "invoice-4821",
			"purpose_of_payment":  "Contractor Payment",
			"source_configuration": map[string]any{
				"source_type": "BANK_ACCOUNT",
				"account_configuration": map[string]any{
					"account_number": "123456789",
					"routing_number": "987654321",
					"account_type":   "CHECKING",
				},
			},
			"target_configuration": map[string]any{
				"source_type": "DLT_WALLET",
				"account_configuration": map[string]any{
					"wallet_address": "0x123456789abcdef",
					"network":        "ethereum",
				},
			},
		},
	}

	payload, _ := json.Marshal(body)
	req, _ := http.NewRequest(http.MethodPost, baseURL+"/fx/quote", 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.StatusOK {
		log.Fatalf("quote 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 getQuote(token: string) {
  const res = await fetch(`${BASE_URL}/fx/quote`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "x-idempotency-key": randomUUID(),
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from_currency: "BSD",
      to_currency: "USDC",
      amount: 1000,
      quote_model: "fixed_source",
      participants: [
        {
          participant_type: "ORIGINATOR",
          given_name: "Jane",
          sur_name: "Doe",
          email: "[email protected]",
          phone_number: "+12425550100",
          address: "123 Bay Street, Nassau, Bahamas",
          individual_date_of_birth: "1990-01-25",
        },
        {
          participant_type: "BENEFICIARY",
          given_name: "John",
          sur_name: "Smith",
          email: "[email protected]",
          phone_number: "+12025550199",
          address: "1600 Market Street, Philadelphia, PA 19103, USA",
        },
      ],
      tx_configuration: {
        client_reference_id: "invoice-4821",
        purpose_of_payment: "Contractor Payment",
        source_configuration: {
          source_type: "BANK_ACCOUNT",
          account_configuration: {
            account_number: "123456789",
            routing_number: "987654321",
            account_type: "CHECKING",
          },
        },
        target_configuration: {
          source_type: "DLT_WALLET",
          account_configuration: {
            wallet_address: "0x123456789abcdef",
            network: "ethereum",
          },
        },
      },
    }),
  });

  if (!res.ok) {
    throw new Error(`Quote failed (${res.status}): ${await res.text()}`);
  }
  return res.json();
}

console.log(await getQuote("<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 Quote {

    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 = """
            {
              "from_currency": "BSD",
              "to_currency": "USDC",
              "amount": 1000,
              "quote_model": "fixed_source",
              "participants": [
                {
                  "participant_type": "ORIGINATOR",
                  "given_name": "Jane",
                  "sur_name": "Doe",
                  "email": "[email protected]",
                  "phone_number": "+12425550100",
                  "address": "123 Bay Street, Nassau, Bahamas",
                  "individual_date_of_birth": "1990-01-25"
                },
                {
                  "participant_type": "BENEFICIARY",
                  "given_name": "John",
                  "sur_name": "Smith",
                  "email": "[email protected]",
                  "phone_number": "+12025550199",
                  "address": "1600 Market Street, Philadelphia, PA 19103, USA"
                }
              ],
              "tx_configuration": {
                "client_reference_id": "invoice-4821",
                "purpose_of_payment": "Contractor Payment",
                "source_configuration": {
                  "source_type": "BANK_ACCOUNT",
                  "account_configuration": {
                    "account_number": "123456789",
                    "routing_number": "987654321",
                    "account_type": "CHECKING"
                  }
                },
                "target_configuration": {
                  "source_type": "DLT_WALLET",
                  "account_configuration": {
                    "wallet_address": "0x123456789abcdef",
                    "network": "ethereum"
                  }
                }
              }
            }
            """;

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/fx/quote"))
                .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() != 200) {
            throw new RuntimeException("Quote 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!({
        "from_currency": "BSD",
        "to_currency": "USDC",
        "amount": 1000,
        "quote_model": "fixed_source",
        "participants": [
            {
                "participant_type": "ORIGINATOR",
                "given_name": "Jane",
                "sur_name": "Doe",
                "email": "[email protected]",
                "phone_number": "+12425550100",
                "address": "123 Bay Street, Nassau, Bahamas",
                "individual_date_of_birth": "1990-01-25"
            },
            {
                "participant_type": "BENEFICIARY",
                "given_name": "John",
                "sur_name": "Smith",
                "email": "[email protected]",
                "phone_number": "+12025550199",
                "address": "1600 Market Street, Philadelphia, PA 19103, USA"
            }
        ],
        "tx_configuration": {
            "client_reference_id": "invoice-4821",
            "purpose_of_payment": "Contractor Payment",
            "source_configuration": {
                "source_type": "BANK_ACCOUNT",
                "account_configuration": {
                    "account_number": "123456789",
                    "routing_number": "987654321",
                    "account_type": "CHECKING"
                }
            },
            "target_configuration": {
                "source_type": "DLT_WALLET",
                "account_configuration": {
                    "wallet_address": "0x123456789abcdef",
                    "network": "ethereum"
                }
            }
        }
    });

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

    if !resp.status().is_success() {
        let status = resp.status();
        return Err(format!("quote 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 get_quote(token: str) -> dict:
    resp = requests.post(
        f"{BASE_URL}/fx/quote",
        headers={
            "Authorization": f"Bearer {token}",
            "x-idempotency-key": str(uuid.uuid4()),
            "Content-Type": "application/json",
        },
        json={
            "from_currency": "BSD",
            "to_currency": "USDC",
            "amount": 1000,
            "quote_model": "fixed_source",
            "participants": [
                {
                    "participant_type": "ORIGINATOR",
                    "given_name": "Jane",
                    "sur_name": "Doe",
                    "email": "[email protected]",
                    "phone_number": "+12425550100",
                    "address": "123 Bay Street, Nassau, Bahamas",
                    "individual_date_of_birth": "1990-01-25",
                },
                {
                    "participant_type": "BENEFICIARY",
                    "given_name": "John",
                    "sur_name": "Smith",
                    "email": "[email protected]",
                    "phone_number": "+12025550199",
                    "address": "1600 Market Street, Philadelphia, PA 19103, USA",
                },
            ],
            "tx_configuration": {
                "client_reference_id": "invoice-4821",
                "purpose_of_payment": "Contractor Payment",
                "source_configuration": {
                    "source_type": "BANK_ACCOUNT",
                    "account_configuration": {
                        "account_number": "123456789",
                        "routing_number": "987654321",
                        "account_type": "CHECKING",
                    },
                },
                "target_configuration": {
                    "source_type": "DLT_WALLET",
                    "account_configuration": {
                        "wallet_address": "0x123456789abcdef",
                        "network": "ethereum",
                    },
                },
            },
        },
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()


print(get_quote("<access_token>"))

Example response (200)

{
  "quote_id": "123e4567-e89b-12d3-a456-426614174000",
  "from_currency": "BSD",
  "to_currency": "USDC",
  "input_amount": 1000,
  "quoted_amount": 998,
  "expiry_seconds": 30,
  "valid_until": "2026-06-24T12:05:00Z",
  "created_at": "2026-06-24T12:04:30Z"
}
FieldDescription
quote_idIdentifier used to capture and execute the quote.
input_amountThe input amount being converted.
quoted_amountThe amount in the target currency at the locked rate.
expiry_secondsSeconds the quote remains valid from creation.
valid_untilAbsolute expiry timestamp — capture before this time.
created_atWhen the quote was created.

Error responses

HTTPCause
400Invalid request parameters (missing required fields, asset mismatch on a CLIENT_BALANCE config, insufficient client balance, etc.).
409A quote workflow is already in progress for this request (often a replayed idempotency key mid-flight).
500Internal server error — retry with backoff.

Next steps

Take the quote_id and capture the quote before valid_until to execute the conversion.


Did this page help you?