Skip to main content

Payments API

Our payment API is how you accept crypto payments from your customers. This guide covers everything from creating simple payments to advanced features like pay-what-you-want pricing and payment splits.

Overview

ZendFi payments support:

  • Multiple tokens: USDC, SOL, USDT
  • Instant settlement: Funds arrive directly in your wallet
  • QR codes: Mobile wallet support via Solana Pay
  • Pay-what-you-want: Flexible pricing for donations and tips
  • Payment splits: Revenue sharing between multiple wallets
  • Idempotency: Safe retry handling

Create Payment

Create a new payment request that customers can pay via QR code or payment link.

Endpoint

POST /api/v1/payments

Authentication

Authorization: Bearer YOUR_API_KEY

Request Parameters

ParameterTypeRequiredDescription
amountnumberYesPayment amount in USD (min: 0.01, max: 10,000)
currencystringYesCurrency code (currently only "USD")
tokenstringNoToken to receive: "USDC", "SOL", "USDT" (default: "USDC")
descriptionstringNoPayment description shown to customer
customer_emailstringNoCustomer's email for receipts
customer_namestringNoCustomer's name
metadataobjectNoCustom key-value pairs (max 16KB)
idempotency_keystringNoUnique key for idempotent requests
redirect_urlstringNoURL to redirect after successful payment
splitsarrayNoPayment split configuration

Response Fields

FieldTypeDescription
payment_idstringUnique payment identifier
merchant_namestringYour business name
amount_usdnumberPayment amount in USD
amount_tokennumberAmount in selected token
tokenstringToken type
statusstringPayment status
payment_urlstringURL for payment page
qr_codestringSolana Pay URI for QR codes
wallet_addressstringDestination wallet address
expires_atdatetimePayment expiration (15 minutes)
created_atdatetimeCreation timestamp

Example: Simple USDC Payment

curl -X POST https://api.zendfi.tech/api/v1/payments \
-H "Authorization: Bearer zfi_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"amount": 49.99,
"currency": "USD",
"token": "USDC",
"description": "Pro Plan - Monthly Subscription",
"customer_email": "customer@example.com",
"metadata": {
"order_id": "ORD-12345",
"plan": "pro_monthly"
}
}'

Response:

{
"payment_id": "pay_abc123xyz789",
"merchant_name": "My Awesome Store",
"amount_usd": 49.99,
"amount_token": 49.99,
"token": "USDC",
"currency": "USD",
"description": "Pro Plan - Monthly Subscription",
"status": "pending",
"payment_url": "https://zendfi.tech/pay/pay_abc123xyz789",
"qr_code": "solana:7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU?amount=49.99&spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&reference=pay_abc123xyz789&label=My%20Awesome%20Store&message=Pro%20Plan%20-%20Monthly%20Subscription",
"wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
"expires_at": "2025-10-26T12:15:00Z",
"created_at": "2025-10-26T12:00:00Z",
"solana_network": "mainnet-beta"
}

Example: SOL Payment

curl -X POST https://api.zendfi.tech/api/v1/payments \
-H "Authorization: Bearer zfi_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"amount": 100.00,
"currency": "USD",
"token": "SOL",
"description": "NFT Minting Fee"
}'

Response:

{
"payment_id": "pay_sol123xyz",
"amount_usd": 100.00,
"amount_token": 0.5263,
"token": "SOL",
"status": "pending",
"payment_url": "https://zendfi.tech/pay/pay_sol123xyz",
"qr_code": "solana:7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU?amount=0.5263&reference=pay_sol123xyz",
"expires_at": "2025-10-26T12:15:00Z"
}
SOL Price Conversion

When using SOL, the amount_token is calculated at the current SOL/USD rate. The rate is locked for the 15-minute payment window.

Get Payment

Retrieve details of an existing payment.

Endpoint

GET /api/v1/payments/:payment_id

Example

curl https://api.zendfi.tech/api/v1/payments/pay_abc123xyz789 \
-H "Authorization: Bearer zfi_live_abc123..."

Response:

{
"payment_id": "pay_abc123xyz789",
"amount_usd": 49.99,
"token": "USDC",
"status": "confirmed",
"transaction_signature": "5KzZ8LWvZh7NYjJvPhHGYnNrB2rKqb2...",
"confirmed_at": "2025-10-26T12:05:00Z",
"created_at": "2025-10-26T12:00:00Z"
}

Payment Statuses

StatusDescription
pendingPayment created, waiting for customer
confirmingTransaction detected, awaiting confirmation
confirmedPayment successful! ✅
failedPayment failed or rejected
expired15-minute window expired
refundedPayment was refunded

Pay-What-You-Want (PWYW)

Enable flexible pricing for donations, tips, or suggested pricing.

Request Parameters

ParameterTypeDescription
allow_custom_amountbooleanEnable PWYW mode
minimum_amountnumberMinimum accepted amount
maximum_amountnumberMaximum accepted amount
suggested_amountnumberDefault suggested amount

Example

curl -X POST https://api.zendfi.tech/api/v1/payments \
-H "Authorization: Bearer zfi_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"currency": "USD",
"token": "USDC",
"description": "Support our project! ☕",
"allow_custom_amount": true,
"minimum_amount": 1.00,
"maximum_amount": 1000.00,
"suggested_amount": 5.00
}'

Payment Splits

Split payments between multiple recipients automatically.

Split Configuration

FieldTypeDescription
recipient_walletstringSolana wallet address
percentagenumberSplit percentage (0.01 to 100)
descriptionstringSplit description
Split Rules
  • Total percentages must equal exactly 100%
  • Each percentage must be between 0.01% and 100%
  • Maximum 10 recipients per payment

Example: 80/20 Split

curl -X POST https://api.zendfi.tech/api/v1/payments \
-H "Authorization: Bearer zfi_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"amount": 100.00,
"currency": "USD",
"token": "USDC",
"description": "Marketplace Purchase",
"splits": [
{
"recipient_wallet": "SellerWallet123...",
"percentage": 80,
"description": "Seller"
},
{
"recipient_wallet": "PlatformWallet456...",
"percentage": 20,
"description": "Platform Fee"
}
]
}'

Idempotency

Prevent duplicate payments with idempotency keys.

curl -X POST https://api.zendfi.tech/api/v1/payments \
-H "Authorization: Bearer zfi_live_abc123..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_12345_attempt_1" \
-d '{
"amount": 49.99,
"currency": "USD",
"token": "USDC",
"description": "Order #12345"
}'
Idempotency Best Practices
  • Use unique keys per payment intent (e.g., order_id + timestamp)
  • Keys are valid for 24 hours
  • Retrying with the same key returns the original payment

Build Transaction (Advanced)

For advanced integrations, get the raw Solana transaction to sign in your own wallet.

Endpoint

POST /api/v1/payments/:payment_id/build-transaction

Request

curl -X POST https://api.zendfi.tech/api/v1/payments/pay_abc123xyz789/build-transaction \
-H "Authorization: Bearer zfi_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"payer_wallet": "CustomerWalletAddress..."
}'

Response

{
"transaction": "AQAAAAAAAAAAAAAAAAAAAAABAAEDAw...",
"message": "Base64 encoded transaction ready for signing"
}

Error Responses

400 Bad Request

{
"error": "Invalid payment parameters",
"details": "Amount must be greater than 0"
}

401 Unauthorized

{
"error": "Invalid or missing API key"
}

404 Not Found

{
"error": "Payment not found",
"payment_id": "pay_invalid123"
}

500 Internal Server Error

{
"error": "Internal server error",
"message": "Please try again later"
}

Webhook Events

Payment-related webhook events:

EventDescription
payment.createdNew payment created
payment.pendingWaiting for customer payment
payment.confirmingTransaction detected
payment.confirmedPayment successful!
payment.failedPayment failed
payment.expiredPayment window expired

See the Webhooks documentation for complete details.

Code Examples

Node.js with SDK

import { zendfi } from '@zendfi/sdk';

// Zero-config: API key auto-loaded from ZENDFI_API_KEY env var

// Create payment
const payment = await zendfi.createPayment({
amount: 49.99,
description: 'Pro Plan',
customer_email: 'customer@example.com'
});

// Get payment status
const status = await zendfi.getPayment(payment.id);
console.log(`Status: ${status.status}`);

Python

import requests

ZENDFI_API_KEY = "zfi_live_abc123..."
BASE_URL = "https://api.zendfi.tech"

# Create payment
response = requests.post(
f"{BASE_URL}/api/v1/payments",
headers={
"Authorization": f"Bearer {ZENDFI_API_KEY}",
"Content-Type": "application/json"
},
json={
"amount": 49.99,
"currency": "USD",
"token": "USDC",
"description": "Pro Plan"
}
)

payment = response.json()
print(f"Payment URL: {payment['payment_url']}")

Next Steps

Ask AI about the docs...