Create Bank Payment Intent

The Create Bank Payment Intent API enables seamless fiat-to-stablecoin transfers through traditional banking rails. This feature is perfect for onboarding users from traditional banking to crypto, supporting ACH, Wire, and SEPA payment methods for converting fiat currencies to stablecoins across multiple blockchain networks.

API EndpointCopied!

POST /api/v0/payment-intents/bank

AuthenticationCopied!

All requests require API key authentication using the following headers:

  • x-client-key: Your application's client key

  • x-client-secret: Your application's client secret

IdempotencyCopied!

The endpoint supports idempotency to prevent duplicate payments:

  • idempotency-key: Include a unique UUID v4 in the header

  • Subsequent requests with the same key return the original response

  • Keys expire after 24 hours

Supported Payment RailsCopied!

Our platform currently supports the following banking payment methods:

Payment Rail

Code

Description

Processing Time

Supported Regions

ACH Push

ach_push

US bank transfers (standard)

1-3 business days

United States

ACH Same Day

ach_same_day

US bank transfers (same-day)

Same business day

United States

Wire Transfer

wire

International wire transfers

Same day - 1 business day

Global

SEPA

sepa

European bank transfers

1-2 business days

European Union

SWIFT

swift

International SWIFT transfers

1-5 business days

Global

SPEI

spei

Mexican instant transfers

Real-time

Mexico

Supported Source CurrenciesCopied!

Currency

Code

Description

Compatible Payment Rails

USD

usd

US Dollar

ach_push, ach_same_day, wire

EUR

eur

Euro

sepa, wire, swift

MXN

mxn

Mexican Peso

spei, wire

Supported Destination NetworksCopied!

Network

Code

Description

Ethereum

ethereum

Main Ethereum network

Polygon

polygon

Polygon (Matic) network

Solana

solana

Solana blockchain

Base

base

Coinbase's Base network

Arbitrum

arbitrum

Arbitrum Layer 2

Optimism

optimism

Optimism Layer 2

Avalanche C-Chain

avalanche_c_chain

Avalanche C-Chain

Stellar

stellar

Stellar network

Tron

tron

Tron blockchain

Supported Destination StablecoinsCopied!

Currency

Code

Description

USDC

usdc

USD Coin

EURC

eurc

Euro Coin

Request ParametersCopied!

Required Parameters

Parameter

Type

Description

sourcePaymentRail

enum

The banking payment method to use for the transfer

destinationCurrency

enum

The stablecoin currency to convert TO (usdc, eurc)

destinationNetwork

enum

The blockchain network where stablecoin will be delivered

Optional Parameters

Parameter

Type

Description

sourceCurrency

enum

The fiat currency to convert FROM (defaults to usd)

destinationAddress

string

Wallet address for receiving funds (Ethereum 0x... or Solana format)

amount

string

Payment amount in source currency (omit for flexible amounts)

customer_first_name

string

Customer's first name (max 100 chars)

customer_last_name

string

Customer's last name (max 100 chars)

customer_email

string

Customer's email address

customer_address

string

Customer's physical address

customer_country

string

Customer's country

customer_countryISO

string

Customer's country ISO code

customer_province

string

Customer's province/state

customer_provinceISO

string

Customer's province/state ISO code

phoneNumber

string

Customer's phone number

Payment Rail Specific Parameters

ACH Transfers

Parameter

Type

Description

ach_reference

string

Reference for ACH transfers (max 10 chars, alphanumeric + spaces)

Wire Transfers

Parameter

Type

Description

wire_message

string

Message for wire transfers (max 256 chars)

SEPA Transfers

Parameter

Type

Description

sepa_reference

string

Reference for SEPA transfers (6-140 chars, specific character set)

ExamplesCopied!

1. USD Bank to USDC Conversion (ACH)

Convert $1000 USD from US bank account to USDC on Ethereum:

curl -X POST https://api.devdraft.ai/api/v0/payment-intents/bank \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -H "idempotency-key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "sourcePaymentRail": "ach_push",
    "sourceCurrency": "usd",
    "destinationCurrency": "usdc",
    "destinationNetwork": "ethereum",
    "destinationAddress": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1",
    "amount": "1000.00",
    "customer_first_name": "John",
    "customer_last_name": "Doe",
    "customer_email": "john.doe@example.com",
    "customer_address": "123 Main St, New York, NY 10001",
    "customer_country": "United States",
    "phoneNumber": "+1-555-123-4567",
    "ach_reference": "INV12345"
  }'

2. EUR SEPA to EURC Conversion

Convert €500 EUR from European bank account to EURC on Polygon:

curl -X POST https://api.devdraft.ai/api/v0/payment-intents/bank \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -H "idempotency-key: 550e8400-e29b-41d4-a716-446655440001" \
  -d '{
    "sourcePaymentRail": "sepa",
    "sourceCurrency": "eur",
    "destinationCurrency": "eurc",
    "destinationNetwork": "polygon",
    "destinationAddress": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1",
    "amount": "500.00",
    "customer_first_name": "Marie",
    "customer_last_name": "Dubois",
    "customer_email": "marie.dubois@example.com",
    "customer_address": "45 Rue de la Paix, 75002 Paris",
    "customer_country": "France",
    "phoneNumber": "+33-1-23-45-67-89",
    "sepa_reference": "REF-123456789"
  }'

3. USD to USDC on Solana (Wire Transfer)

Convert $5000 USD via wire transfer to USDC on Solana:

curl -X POST https://api.devdraft.ai/api/v0/payment-intents/bank \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -H "idempotency-key: 550e8400-e29b-41d4-a716-446655440002" \
  -d '{
    "sourcePaymentRail": "wire",
    "sourceCurrency": "usd",
    "destinationCurrency": "usdc",
    "destinationNetwork": "solana",
    "destinationAddress": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
    "amount": "5000.00",
    "customer_email": "customer@example.com",
    "wire_message": "Investment funds transfer"
  }'

4. Flexible Amount Payment Intent

Create a payment intent where users specify the amount during checkout:

curl -X POST https://api.devdraft.ai/api/v0/payment-intents/bank \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -H "idempotency-key: 550e8400-e29b-41d4-a716-446655440003" \
  -d '{
    "sourcePaymentRail": "ach_push",
    "sourceCurrency": "usd",
    "destinationCurrency": "usdc",
    "destinationNetwork": "polygon",
    "destinationAddress": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1",
    "customer_email": "customer@example.com"
  }'

5. Mexican Peso SPEI Transfer

Convert MXN via SPEI to USDC on Base:

curl -X POST https://api.devdraft.ai/api/v0/payment-intents/bank \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -H "idempotency-key: 550e8400-e29b-41d4-a716-446655440004" \
  -d '{
    "sourcePaymentRail": "spei",
    "sourceCurrency": "mxn",
    "destinationCurrency": "usdc",
    "destinationNetwork": "base",
    "destinationAddress": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1",
    "amount": "20000.00",
    "customer_email": "customer@example.com"
  }'

6. Same-Day ACH Transfer

Fast USD to USDC conversion using same-day ACH:

{
  "sourcePaymentRail": "ach_same_day",
  "sourceCurrency": "usd",
  "destinationCurrency": "usdc",
  "destinationNetwork": "arbitrum",
  "destinationAddress": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1",
  "amount": "750.00",
  "customer_email": "customer@example.com",
  "ach_reference": "URGENT123"
}

Response FormatCopied!

Success Response (201 Created)

{
  "id": "txn_01HZXK8M9N2P3Q4R5S6T7U8V9W",
  "bridge_transfer_id": "transfer_abc123xyz456",
  "state": "pending",
  "amount": "1000.00",
  "source": {
    "payment_rail": "ach_push",
    "currency": "usd"
  },
  "destination": {
    "payment_rail": "ethereum",
    "currency": "usdc",
    "to_address": "0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1"
  },
  "customer": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@example.com",
    "address": "123 Main St, New York, NY 10001",
    "country": "United States",
    "phone_number": "+1-555-123-4567"
  },
  "created_at": "2023-07-01T12:00:00.000Z",
  "updated_at": "2023-07-01T12:00:00.000Z"
}

Response Fields

Field

Type

Description

id

string

Unique transaction identifier in our database

bridge_transfer_id

string

External bridge service transfer ID

state

string

Current state: pending, processing, completed, failed, cancelled

amount

string

Payment amount (null for flexible amounts until user specifies)

source

object

Source payment details (bank information)

destination

object

Destination payment details (blockchain information)

customer

object

Customer information (if provided)

created_at

string

Creation timestamp (ISO 8601)

updated_at

string

Last update timestamp (ISO 8601)

Error ResponsesCopied!

400 Bad Request

{
  "statusCode": 400,
  "message": [
    "Please select a valid source payment rail",
    "Destination currency is required"
  ],
  "error": "Bad Request"
}

401 Unauthorized

{
  "statusCode": 401,
  "message": "Unauthorized - Invalid API credentials",
  "error": "Unauthorized"
}

404 Not Found

{
  "statusCode": 404,
  "message": "App not found",
  "error": "Not Found"
}

409 Conflict (Idempotency)

{
  "statusCode": 409,
  "message": "Idempotency key already used with different parameters",
  "error": "Conflict"
}

Payment Rail CharacteristicsCopied!

ACH Push (ach_push)

  • Processing Time: 1-3 business days

  • Cost: Low

  • Limits: Varies by bank (typically $10K-$100K daily)

  • Best For: Regular transfers, subscription payments

  • Reversibility: Yes (up to 60 days)

ACH Same Day (ach_same_day)

  • Processing Time: Same business day

  • Cost: Medium

  • Limits: Lower than standard ACH

  • Best For: Urgent transfers, time-sensitive payments

  • Reversibility: Yes (limited window)

Wire Transfer (wire)

  • Processing Time: Same day to 1 business day

  • Cost: High

  • Limits: High (varies by institution)

  • Best For: Large transfers, international payments

  • Reversibility: Very limited

SEPA (sepa)

  • Processing Time: 1-2 business days

  • Cost: Low to medium

  • Limits: €1M per transaction (varies by bank)

  • Best For: European transfers, EUR payments

  • Reversibility: Limited (fraud/error cases)

SWIFT (swift)

  • Processing Time: 1-5 business days

  • Cost: High

  • Limits: High (varies by institution)

  • Best For: International transfers, non-SEPA regions

  • Reversibility: Very limited

SPEI (spei)

  • Processing Time: Real-time (24/7)

  • Cost: Low

  • Limits: Varies by bank

  • Best For: Mexican peso transfers, instant payments

  • Reversibility: Very limited

Regional Compliance RequirementsCopied!

United States (ACH)

  • Customer Information: Full name, address required for amounts >$3K

  • AML/KYC: Enhanced due diligence for amounts >$10K

  • Documentation: Bank account verification may be required

European Union (SEPA)

  • Customer Information: Full name and address required

  • GDPR Compliance: Data protection requirements apply

  • Strong Customer Authentication: May be required for certain amounts

Mexico (SPEI)

  • Customer Information: RFC (tax ID) may be required for large amounts

  • Local Regulations: CNBV compliance requirements

  • Documentation: Proof of funds may be required

Fees and LimitsCopied!

Developer Fee

  • Standard Rate: 0.20% of transfer amount

  • Minimum Fee: Varies by payment rail

  • Maximum Fee: Capped based on amount

Network-Specific Considerations

Destination Network

Gas Fee Estimate

Confirmation Time

Ethereum

$5-$50

1-5 minutes

Polygon

$0.01-$0.10

30 seconds

Solana

$0.00025

30 seconds

Base

$0.10-$1

1-2 minutes

Arbitrum

$0.50-$2

1-2 minutes

Optimism

$0.50-$2

1-2 minutes

Avalanche

$1-$5

1-2 minutes

Use CasesCopied!

1. Fiat On-Ramp

Enable users to convert traditional bank funds into cryptocurrency for the first time.

2. Recurring Payments

Set up automatic conversion of salary or business income into stablecoins.

3. International Remittances

Facilitate cross-border payments with better rates than traditional remittance services.

4. Business Treasury Management

Allow businesses to convert operational funds into stablecoins for yield generation or payments.

5. DeFi Onboarding

Help users fund DeFi protocols directly from their bank accounts.

6. Payroll Conversion

Enable companies to pay employees in stablecoins while sourcing funds from traditional bank accounts.

Best PracticesCopied!

1. Amount Handling

  • Use string format for amounts to avoid precision issues

  • Validate minimum amounts based on payment rail fees

  • Consider currency conversion rates for cross-currency transfers

2. Error Handling

  • Handle bank rejection scenarios gracefully

  • Implement proper retry logic for network failures

  • Provide clear status updates throughout the transfer process

3. Reference Fields

  • Use descriptive references for ACH transfers (helps with reconciliation)

  • Include order/invoice numbers in wire messages

  • Follow SEPA reference format requirements

Integration ExamplesCopied!

JavaScript/TypeScript

interface CreateBankPaymentIntentRequest {
  sourcePaymentRail: 'ach_push' | 'ach_same_day' | 'wire' | 'sepa' | 'swift' | 'spei';
  sourceCurrency?: 'usd' | 'eur' | 'mxn';
  destinationCurrency: 'usdc' | 'eurc';
  destinationNetwork: string;
  destinationAddress?: string;
  amount?: string;
  customer_email?: string;
  ach_reference?: string;
  wire_message?: string;
  sepa_reference?: string;
  // ... other customer fields
}

async function createBankPaymentIntent(
  data: CreateBankPaymentIntentRequest
): Promise<PaymentIntentResponse> {
  const response = await fetch('/api/v0/payment-intents/bank', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-client-key': process.env.CLIENT_KEY!,
      'x-client-secret': process.env.CLIENT_SECRET!,
      'idempotency-key': crypto.randomUUID(),
    },
    body: JSON.stringify(data),
  });
  
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  
  return response.json();
}

// Example usage for ACH transfer
const achTransfer = await createBankPaymentIntent({
  sourcePaymentRail: 'ach_push',
  sourceCurrency: 'usd',
  destinationCurrency: 'usdc',
  destinationNetwork: 'ethereum',
  destinationAddress: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1',
  amount: '1000.00',
  customer_email: 'customer@example.com',
  ach_reference: 'INV12345'
});

Python

import requests
import uuid
from typing import Optional, Dict, Any

def create_bank_payment_intent(
    source_payment_rail: str,
    destination_currency: str,
    destination_network: str,
    source_currency: str = "usd",
    destination_address: Optional[str] = None,
    amount: Optional[str] = None,
    customer_email: Optional[str] = None,
    ach_reference: Optional[str] = None,
    wire_message: Optional[str] = None,
    sepa_reference: Optional[str] = None,
    **customer_data
) -> Dict[Any, Any]:
    
    url = "https://api.devdraft.ai/api/v0/payment-intents/bank"
    
    headers = {
        "Content-Type": "application/json",
        "x-client-key": os.getenv("CLIENT_KEY"),
        "x-client-secret": os.getenv("CLIENT_SECRET"),
        "idempotency-key": str(uuid.uuid4())
    }
    
    payload = {
        "sourcePaymentRail": source_payment_rail,
        "sourceCurrency": source_currency,
        "destinationCurrency": destination_currency,
        "destinationNetwork": destination_network,
        **({} if destination_address is None else {"destinationAddress": destination_address}),
        **({} if amount is None else {"amount": amount}),
        **({} if customer_email is None else {"customer_email": customer_email}),
        **({} if ach_reference is None else {"ach_reference": ach_reference}),
        **({} if wire_message is None else {"wire_message": wire_message}),
        **({} if sepa_reference is None else {"sepa_reference": sepa_reference}),
        **customer_data
    }
    
    response = requests.post(url, json=payload, headers=headers)
    response.raise_for_status()
    
    return response.json()

# Example usage for SEPA transfer
sepa_transfer = create_bank_payment_intent(
    source_payment_rail="sepa",
    source_currency="eur",
    destination_currency="eurc",
    destination_network="polygon",
    destination_address="0x742d35Cc6634C0532925a3b8D4C9db96c4b4d8e1",
    amount="500.00",
    customer_email="customer@example.com",
    sepa_reference="REF-123456789"
)

PHP

<?php

function createBankPaymentIntent($data) {
    $url = "https://api.devdraft.ai/api/v0/payment-intents/bank";
    
    $headers = [
        'Content-Type: application/json',
        'x-client-key: ' . $_ENV['CLIENT_KEY'],
        'x-client-secret: ' . $_ENV['CLIENT_SECRET'],
        'idempotency-key: ' . wp_generate_uuid4()
    ];
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode !== 201) {
        throw new Exception("HTTP Error: " . $httpCode);
    }
    
    return json_decode($response, true);
}

// Example usage for wire transfer
$wireTransfer = createBankPaymentIntent([
    'sourcePaymentRail' => 'wire',
    'sourceCurrency' => 'usd',
    'destinationCurrency' => 'usdc',
    'destinationNetwork' => 'solana',
    'destinationAddress' => '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
    'amount' => '5000.00',
    'customer_email' => 'customer@example.com',
    'wire_message' => 'Investment funds'
]);
?>

Monitoring and WebhooksCopied!

Transaction States

Monitor payment intent progression through these states:

  • pending: Payment intent created, awaiting bank transfer

  • processing: Bank transfer received, converting to stablecoin

  • completed: Stablecoin delivered to destination address

  • failed: Transfer failed (insufficient funds, invalid account, etc.)

  • cancelled: Transfer cancelled by user or system

Webhook Events

Set up webhooks to receive real-time updates:

  • payment_intent.created

  • payment_intent.processing

  • payment_intent.completed

  • payment_intent.failed

  • payment_intent.cancelled

SupportCopied!

For additional support or questions about the Create Bank Payment Intent API:

  1. Check our API status page for known issues

  2. Review the error codes and messages in your responses

  3. Contact our support team with your bridge_transfer_id for specific transaction issues

  4. Consult regional compliance guidelines for specific requirements