Skip to main content
POST
https://sandbox.finhub.cloud
/
api
/
v2.1
/
transfers
/
{accountId}
/
prepare
Transfers & Payments API
curl --request POST \
  --url https://sandbox.finhub.cloud/api/v2.1/transfers/{accountId}/prepare \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --header 'X-Session-Id: <x-session-id>' \
  --header 'X-Tenant-ID: <x-tenant-id>' \
  --data '
{
  "transferType": "<string>",
  "amount": {
    "value": 123,
    "currency": "<string>"
  },
  "beneficiaryId": "<string>",
  "reference": "<string>",
  "description": "<string>",
  "orderId": "<string>"
}
'
{
  "success": true,
  "data": {
    "allowedOperations": ["INTERNAL", "SEPA", "SEPA_INSTANT", "SWIFT"],
    "beneficiaries": [
      {
        "beneficiaryId": "ben_12345",
        "name": "John Doe",
        "iban": "DE89370400440532013000",
        "type": "SEPA"
      }
    ],
    "limits": {
      "daily": {
        "value": 50000.00,
        "currency": "EUR",
        "used": 1000.00,
        "remaining": 49000.00
      },
      "perTransaction": {
        "value": 10000.00,
        "currency": "EUR"
      }
    },
    "fees": {
      "INTERNAL": {"value": 0, "currency": "EUR"},
      "SEPA": {"value": 1.50, "currency": "EUR"},
      "SEPA_INSTANT": {"value": 2.50, "currency": "EUR"},
      "SWIFT": {"value": 25.00, "currency": "EUR"}
    }
  }
}

Transfers & Payments API

APIs for the three-step transfer workflow: prepare, execute, and monitor transfers.
Base URL: https://sandbox.finhub.cloud/api/v2.1/fintrans
For complete details on authentication and headers, refer to the Standard HTTP Headers reference documentation.

Transfer Prerequisites Checklist

Before executing transfers:
  • Account ACTIVATED
  • Wallet ACTIVE with sufficient balance
  • Beneficiary pre-registered (recommended)
  • Payment consent created (if required by category)
  • Approval workflow configured (for high-value transfers)

Complete Transfer Flow

3-Step Process

Step 1: Prepare Transfer Order

  • Validates transfer details and beneficiary
  • Calculates fees and total debit amount
  • Reserves funds in the source account
  • Returns preparedOrderId with validUntil timestamp
  • Critical: Order expires after 15 minutes and must be executed before validUntil

Step 2: Execute Transfer Order

  • Confirms payment consent (if required)
  • Processes multi-level approvals (for high-value transactions)
  • Attaches supporting documents (for transactions above threshold)
  • Executes the actual payment
  • Returns executionId and transaction reference

Step 3: Monitor Status

  • Track execution progress (PENDING → PROCESSING → COMPLETED)
  • View state transition history
  • Check settlement status
  • Download transaction receipt

Two-Phase Pattern Explained

15-Minute Expiration: Prepared orders are only valid for 15 minutes from creation. You must execute the order before the validUntil timestamp or the order will expire and need to be prepared again.

Why Two Phases?

The prepare/execute pattern provides several benefits:
  1. Pre-Validation - Catch errors before committing funds
  2. Fee Transparency - Show exact fees before execution
  3. Balance Reservation - Prevent overdrafts during execution
  4. Compliance Window - Allow time for high-value transaction document upload
  5. User Confirmation - Give users time to review and confirm
  6. Idempotency - Prevent duplicate transfers

Timing Example

// Prepare at 10:00:00
const prepared = await prepareTransfer(accountId, {
  amount: { value: '10000', scale: 2, currency: 'EUR' },
  target: { beneficiaryRef: 'ben_123' }
});

console.log('Prepared Order ID:', prepared.preparedOrderId);
console.log('Valid Until:', prepared.validUntil); // 2026-01-13T10:15:00Z

// You have until 10:15:00 to execute (15 minutes)
// After 10:15:00, the order expires and returns error:
// "Prepared order expired or not found"

// Execute before expiration
if (Date.now() < new Date(prepared.validUntil).getTime()) {
  const result = await executeTransfer(accountId, prepared.preparedOrderId);
  console.log('Executed!', result.executionId);
} else {
  console.error('Order expired - prepare again');
}

High-Value Transaction Flow

For transactions above the threshold (typically €10,000), additional documents are required:
// 1. Prepare high-value transfer
const prepared = await prepareTransfer(accountId, {
  amount: { value: '1500000', scale: 2, currency: 'EUR' } // €15,000
});

// 2. Upload supporting documents (BEFORE execute)
const documents = [
  { type: 'PROOF_OF_FUNDS', content: proofOfFundsBase64 },
  { type: 'INVOICE', content: invoiceBase64 },
  { type: 'CONTRACT', content: contractBase64 }
];

for (const doc of documents) {
  await uploadPaymentDocument(walletId, prepared.preparedOrderId, doc);
}

// 3. Execute with consent confirmation
await executeTransfer(accountId, prepared.preparedOrderId, {
  consentConfirmation: {
    consentId: 'consent_abc123',
    confirmed: true,
    timestamp: new Date().toISOString(),
    channel: 'WEB',
    signature: 'user_digital_signature'
  },
  authenticationCode: '123456', // 2FA code
  supportingDocuments: documents.map(d => d.documentId)
});

Get Allowed Operations

Returns available transfer types, saved beneficiaries, current limits, and applicable fees.

Request

accountId
string
required
Source account ID for the transfer
Authorization
string
required
Bearer token for authentication
X-Tenant-ID
string
required
Tenant identifier
X-Session-Id
string
Active session ID (optional)

Code Examples

curl -X GET "https://sandbox.finhub.cloud/api/v2.1/transfers/acc_12345/allowed-ops" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID"

Response

allowedOperations
array
List of available transfer types (INTERNAL, SEPA, SEPA_INSTANT, SWIFT)
beneficiaries
array
Saved beneficiaries for quick transfers
limits
object
Current transaction limits and usage
fees
object
Fee structure per transfer type
{
  "success": true,
  "data": {
    "allowedOperations": ["INTERNAL", "SEPA", "SEPA_INSTANT", "SWIFT"],
    "beneficiaries": [
      {
        "beneficiaryId": "ben_12345",
        "name": "John Doe",
        "iban": "DE89370400440532013000",
        "type": "SEPA"
      }
    ],
    "limits": {
      "daily": {
        "value": 50000.00,
        "currency": "EUR",
        "used": 1000.00,
        "remaining": 49000.00
      },
      "perTransaction": {
        "value": 10000.00,
        "currency": "EUR"
      }
    },
    "fees": {
      "INTERNAL": {"value": 0, "currency": "EUR"},
      "SEPA": {"value": 1.50, "currency": "EUR"},
      "SEPA_INSTANT": {"value": 2.50, "currency": "EUR"},
      "SWIFT": {"value": 25.00, "currency": "EUR"}
    }
  }
}

Prepare Transfer

Validates transfer details and stages the order for execution. Returns fees and estimated arrival.

Request

accountId
string
required
Source account ID for the transfer
Authorization
string
required
Bearer token for authentication
X-Session-Id
string
required
Active session ID
X-Tenant-ID
string
required
Tenant identifier
transferType
string
required
Type of transfer: INTERNAL, SEPA, SEPA_INSTANT, or SWIFT
amount
object
required
Transfer amount details
beneficiaryId
string
required
ID of the beneficiary to receive the transfer
reference
string
Payment reference (max 140 characters)
description
string
Internal description for the transfer

Code Examples

curl -X POST "https://sandbox.finhub.cloud/api/v2.1/transfers/acc_12345/prepare" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "X-Session-Id: YOUR_SESSION_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "transferType": "SEPA",
    "amount": {
      "value": 500.00,
      "currency": "EUR"
    },
    "beneficiaryId": "ben_12345",
    "reference": "Invoice Payment",
    "description": "Payment for services"
  }'

Response

orderId
string
Unique identifier for the prepared order
status
string
Order status (PREPARED)
amount
object
Transfer amount
fees
object
Applicable fees for this transfer
totalDebit
object
Total amount to be debited (amount + fees)
estimatedArrival
string
Estimated arrival date
expiresAt
string
Order expiration timestamp (must execute before this time)
{
  "success": true,
  "data": {
    "orderId": "ord_12345",
    "status": "PREPARED",
    "amount": {
      "value": 500.00,
      "currency": "EUR"
    },
    "fees": {
      "value": 1.50,
      "currency": "EUR"
    },
    "totalDebit": {
      "value": 501.50,
      "currency": "EUR"
    },
    "estimatedArrival": "2024-01-17",
    "expiresAt": "2024-01-15T11:00:00Z"
  }
}

Execute Transfer

Executes a prepared transfer order. The order must be executed before it expires.

Request

accountId
string
required
Source account ID
Authorization
string
required
Bearer token for authentication
X-Session-Id
string
required
Active session ID
X-Tenant-ID
string
required
Tenant identifier
orderId
string
required
Order ID from the prepare step

Code Examples

curl -X POST "https://sandbox.finhub.cloud/api/v2.1/transfers/acc_12345/execute" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "X-Session-Id: YOUR_SESSION_ID" \
  -H "Content-Type: application/json" \
  -d '{"orderId": "ord_12345"}'

Response

transactionId
string
Unique transaction identifier for tracking
orderId
string
Original order ID
status
string
Transaction status (PROCESSING, COMPLETED, FAILED)
executedAt
string
ISO 8601 timestamp of execution
estimatedCompletion
string
Estimated completion timestamp
{
  "success": true,
  "data": {
    "transactionId": "txn_67890",
    "orderId": "ord_12345",
    "status": "PROCESSING",
    "executedAt": "2024-01-15T10:35:00Z",
    "estimatedCompletion": "2024-01-17T12:00:00Z"
  }
}

Transfer Types

INTERNAL

Speed: Instant
Fee: Free
Between FinHub accounts

SEPA

Speed: 1-2 business days
Fee: €1.50
Eurozone bank transfers

SEPA_INSTANT

Speed: Under 10 seconds
Fee: €2.50
Real-time Eurozone transfers

SWIFT

Speed: 2-5 business days
Fee: €25.00
International wire transfers

Direct Transfer Operations

These endpoints create transfers directly without the prepare/execute workflow.

Create Top-up Transfer

POST /api/v2.1/fintrans/{accountId}/transfers/types.topup
Adds funds to an account (deposit).
curl -X POST "https://sandbox.finhub.cloud/api/v2.1/fintrans/acc_12345/transfers/types.topup" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {"value": 1000.00, "currency": "EUR"},
    "reference": "Deposit",
    "sourceDetails": {"method": "BANK_TRANSFER"}
  }'
{
  "success": true,
  "data": {
    "transactionId": "txn_topup_12345",
    "type": "TOPUP",
    "amount": {"value": 1000.00, "currency": "EUR"},
    "status": "COMPLETED",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

Create Withdrawal Transfer

POST /api/v2.1/fintrans/{accountId}/transfers/types.withdraw
Withdraws funds from an account.
curl -X POST "https://sandbox.finhub.cloud/api/v2.1/fintrans/acc_12345/transfers/types.withdraw" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {"value": 500.00, "currency": "EUR"},
    "destinationIban": "DE89370400440532013000",
    "reference": "Withdrawal"
  }'
{
  "success": true,
  "data": {
    "transactionId": "txn_withdraw_12345",
    "type": "WITHDRAW",
    "amount": {"value": 500.00, "currency": "EUR"},
    "fees": {"value": 1.50, "currency": "EUR"},
    "status": "PROCESSING",
    "estimatedCompletion": "2024-01-17T12:00:00Z"
  }
}

Create Standard Transfer

POST /api/v2.1/fintrans/{accountId}/transfers/types.transfer
Creates a direct account-to-account transfer.
curl -X POST "https://sandbox.finhub.cloud/api/v2.1/fintrans/acc_12345/transfers/types.transfer" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {"value": 250.00, "currency": "EUR"},
    "destinationAccountId": "acc_67890",
    "reference": "Payment for services"
  }'
{
  "success": true,
  "data": {
    "transactionId": "txn_transfer_12345",
    "type": "TRANSFER",
    "amount": {"value": 250.00, "currency": "EUR"},
    "status": "COMPLETED",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

Create Purchase Transfer

POST /api/v2.1/fintrans/{accountId}/transfers/types.purchase
Creates a purchase transaction (e.g., card payment, merchant payment).
curl -X POST "https://sandbox.finhub.cloud/api/v2.1/fintrans/acc_12345/transfers/types.purchase" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {"value": 99.99, "currency": "EUR"},
    "merchantId": "merchant_12345",
    "merchantName": "Online Store",
    "reference": "Order #12345"
  }'
{
  "success": true,
  "data": {
    "transactionId": "txn_purchase_12345",
    "type": "PURCHASE",
    "amount": {"value": 99.99, "currency": "EUR"},
    "merchantName": "Online Store",
    "status": "COMPLETED",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

Create Sale Transfer

POST /api/v2.1/fintrans/{accountId}/transfers/types.sale
Creates a sale transaction (receiving payment as a merchant).
curl -X POST "https://sandbox.finhub.cloud/api/v2.1/fintrans/acc_12345/transfers/types.sale" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Tenant-ID: YOUR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {"value": 150.00, "currency": "EUR"},
    "customerReference": "CUST-001",
    "description": "Product sale"
  }'
{
  "success": true,
  "data": {
    "transactionId": "txn_sale_12345",
    "type": "SALE",
    "amount": {"value": 150.00, "currency": "EUR"},
    "status": "COMPLETED",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

Operation Types Summary

TypeDescriptionUse Case
topupAdd fundsDeposits, incoming transfers
withdrawRemove fundsBank withdrawals
transferMove between accountsP2P, internal transfers
purchaseDebit for purchaseCard payments, merchant payments
saleCredit from saleMerchant receiving payments

Transfer Status Flow

StatusDescriptionNext Step
PREPAREDOrder validated, funds reservedExecute within 15 min
EXECUTINGPayment being processedWait for completion
COMPLETEDTransfer successfulNone
FAILEDTransfer failedReview error, retry
CANCELLEDManually cancelledCreate new order

Idempotency (Prevent Duplicates)

Use X-Idempotency-Key header to prevent duplicate transfers:
const idempotencyKey = `transfer-${Date.now()}-${Math.random()}`;

await fetch(url, {
  method: 'POST',
  headers: {
    'X-Idempotency-Key': idempotencyKey,
    ...otherHeaders
  },
  body: JSON.stringify(transferData)
});
Important: Same key within 24 hours = same response (no duplicate charge)

Response Codes

CodeDescription
200Transfer status retrieved successfully
201Transfer prepared/executed successfully
400Invalid request data or prepared order expired (>15 min)
403Insufficient funds or limits exceeded
404Account, order, or beneficiary not found
409Duplicate idempotency key
422Missing consent or approval required
500Internal server error

API Schema Reference

For the complete OpenAPI schema specification, see the API Schema Mapping document:

Changelog

VersionDateChanges
v1.02026-01-13Comprehensive transfer operations documentation