Payment Links API
Payment Links
The Payment Links service (client.paymentLinks
) allows you to create payment requests that can be shared with customers. When a customer accesses a payment link, they will be directed to a checkout page where they can complete the payment using SUI or other supported cryptocurrencies.
Create a Payment Link
Create a new payment link using the SDK:
import { PaymentDestinationType } from '@suipay/api';
// Create payment link with POLAR_BALANCE destination
const paymentLink = await client.paymentLinks.create({
amount_usdc: 100,
description: 'Test payment',
destination_type: PaymentDestinationType.POLAR_BALANCE
});
console.log(`Payment URL: ${paymentLink.url}`);
Method Signature
client.paymentLinks.create(options: CreatePaymentLinkRequest): Promise<PaymentLink>
Request Parameters
amount_usdc
number
Yes
The amount in USDC to be paid
description
string
No
A description of what the payment is for
destination_type
PaymentDestinationType
Yes
Where the funds should be sent after payment
custom_sui_address
string
Conditional
Required when destination_type is CUSTOM_ADDRESS
bank_account_id
string
Conditional
Required when destination_type is BANK_ACCOUNT
Response Type
interface PaymentLink {
id: string;
amount_usdc: number;
description: string;
destination_type: PaymentDestinationType;
custom_sui_address: string | null;
bank_account_id: string | null;
enabled: boolean;
created_at: string;
url: string;
}
Usage Examples
import { PaymentDestinationType } from '@suipay/api';
// Create payment link with POLAR_BALANCE destination
const basicPayment = await client.paymentLinks.create({
amount_usdc: 50,
description: 'Service payment',
destination_type: PaymentDestinationType.POLAR_BALANCE
});
// Create payment link with custom SUI address
const customAddressPayment = await client.paymentLinks.create({
amount_usdc: 100,
description: 'Payment to custom wallet',
destination_type: PaymentDestinationType.CUSTOM_ADDRESS,
custom_sui_address: '0x1234567890abcdef1234567890abcdef12345678'
});
// Create payment link with bank account destination
const bankPayment = await client.paymentLinks.create({
amount_usdc: 200,
description: 'Payment to bank account',
destination_type: PaymentDestinationType.BANK_ACCOUNT,
bank_account_id: 'bank_account_id_here'
});
console.log(`Share this payment link: ${basicPayment.url}`);
List Payment Links
Retrieve all payment links for your account:
const paymentLinks = await client.paymentLinks.list();
console.log(`Found ${paymentLinks.length} payment link(s)`);
paymentLinks.forEach(link => {
console.log(`${link.description}: ${link.amount_usdc} USDC`);
console.log(`Status: ${link.enabled ? 'Active' : 'Disabled'}`);
console.log(`URL: ${link.url}`);
});
Method Signature
client.paymentLinks.list(): Promise<PaymentLinkSummary[]>
Response Type
interface PaymentLinkSummary {
id: string;
amount_usdc: number;
description: string;
enabled: boolean;
created_at: string;
}
Get Payment Link
Retrieve details of a specific payment link:
const paymentLinkId = 'payment_link_id_here';
const paymentLink = await client.paymentLinks.get(paymentLinkId);
console.log(`Payment Link: ${paymentLink.description}`);
console.log(`Amount: ${paymentLink.amount_usdc} USDC`);
console.log(`Status: ${paymentLink.enabled ? 'Active' : 'Disabled'}`);
console.log(`Destination: ${paymentLink.destination_type}`);
console.log(`URL: ${paymentLink.url}`);
// Check payment status
if (paymentLink.paid) {
console.log(`✅ Payment completed at: ${paymentLink.paid_at}`);
console.log(`Transaction: ${paymentLink.transaction_digest}`);
} else {
console.log('⏳ Payment pending');
}
Method Signature
client.paymentLinks.get(id: string): Promise<PaymentLink>
Response Type
interface PaymentLink {
id: string;
user_id: string;
amount_usdc: number;
description?: string;
shopify_payment_session_id?: string;
destination_type: PaymentDestinationType;
custom_sui_address?: string;
bank_account_id?: string;
enabled: boolean;
off_ramp_status: OffRampStatus;
sui_usdc_transfer_tx?: string;
solana_usdc_transfer_tx?: string;
cctp_message_hash?: string;
off_ramp_error?: string;
off_ramp_started_at?: string;
off_ramp_completed_at?: string;
bridge_transfer_id?: string;
sui_wallet_deposit_address?: string;
polar_balance_processed: boolean;
created_at: string;
expires_at?: string;
paid: boolean;
paid_at?: string;
transaction_digest?: string;
transaction_payer?: string;
refunded: boolean;
refund_digest?: string;
woocommerce_metadata?: any;
}
Payment Link States and Monitoring
Checking Payment Status
Monitor payment link status and track completion:
async function checkPaymentStatus(paymentLinkId: string) {
const paymentLink = await client.paymentLinks.get(paymentLinkId);
console.log(`Payment Link: ${paymentLink.description}`);
console.log(`Amount: ${paymentLink.amount_usdc} USDC`);
if (!paymentLink.enabled) {
console.log('❌ Payment link is disabled');
return;
}
if (paymentLink.paid) {
console.log('✅ Payment completed!');
console.log(` Paid at: ${new Date(paymentLink.paid_at!).toLocaleString()}`);
console.log(` Transaction: ${paymentLink.transaction_digest}`);
console.log(` Payer: ${paymentLink.transaction_payer}`);
// Check off-ramp status for bank account destinations
if (paymentLink.destination_type === PaymentDestinationType.BANK_ACCOUNT) {
console.log(` Off-ramp status: ${paymentLink.off_ramp_status}`);
}
} else {
console.log('⏳ Payment pending');
if (paymentLink.expires_at) {
const expiryDate = new Date(paymentLink.expires_at);
console.log(` Expires: ${expiryDate.toLocaleString()}`);
}
}
if (paymentLink.refunded) {
console.log('🔄 Payment has been refunded');
console.log(` Refund transaction: ${paymentLink.refund_digest}`);
}
}
Payment Link Fields
id
string
Unique payment link identifier
user_id
string
Associated user identifier
amount_usdc
number
Payment amount in USDC
description
string?
Optional payment description
shopify_payment_session_id
string?
Shopify integration session ID
destination_type
PaymentDestinationType
Where funds are sent after payment
custom_sui_address
string?
Custom SUI address (for CUSTOM_ADDRESS type)
bank_account_id
string?
Bank account ID (for BANK_ACCOUNT type)
enabled
boolean
Whether the payment link is active
off_ramp_status
OffRampStatus
Current off-ramp processing status
sui_usdc_transfer_tx
string?
SUI USDC transfer transaction hash
solana_usdc_transfer_tx
string?
Solana USDC transfer transaction hash
cctp_message_hash
string?
CCTP (Cross-Chain Transfer Protocol) message hash
off_ramp_error
string?
Error message if off-ramp processing failed
off_ramp_started_at
string?
When off-ramp processing started
off_ramp_completed_at
string?
When off-ramp processing completed
bridge_transfer_id
string?
Bridge service transfer identifier
sui_wallet_deposit_address
string?
SUI wallet deposit address used
polar_balance_processed
boolean
Whether funds have been processed to balance
created_at
string
Payment link creation timestamp
expires_at
string?
When the payment link expires
paid
boolean
Whether the payment has been completed
paid_at
string?
When the payment was completed
transaction_digest
string?
The SUI transaction hash of the payment
transaction_payer
string?
The SUI address of the payer
refunded
boolean
Whether the payment has been refunded
refund_digest
string?
The SUI transaction hash of the refund
woocommerce_metadata
any?
WooCommerce integration metadata
Off-ramp Status Enum
enum OffRampStatus {
PENDING = 'PENDING',
CCTP_TRANSFER_INITIATED = 'CCTP_TRANSFER_INITIATED',
CCTP_TRANSFER_COMPLETED = 'CCTP_TRANSFER_COMPLETED',
BRIDGE_TRANSFER_INITIATED = 'BRIDGE_TRANSFER_INITIATED',
BRIDGE_TRANSFER_COMPLETED = 'BRIDGE_TRANSFER_COMPLETED',
COMPLETED = 'COMPLETED',
FAILED = 'FAILED'
}
Off-ramp Processing Monitoring
Monitor the off-ramp processing status for bank account destinations:
async function monitorOffRampStatus(paymentLinkId: string) {
const paymentLink = await client.paymentLinks.get(paymentLinkId);
if (!paymentLink.paid) {
console.log('Payment not yet received');
return;
}
console.log(`Off-ramp Status: ${paymentLink.off_ramp_status}`);
switch (paymentLink.off_ramp_status) {
case 'PENDING':
console.log('⏳ Processing payment...');
break;
case 'CCTP_TRANSFER_INITIATED':
console.log('🔄 Cross-chain transfer started');
break;
case 'CCTP_TRANSFER_COMPLETED':
console.log('✅ Cross-chain transfer complete');
break;
case 'BRIDGE_TRANSFER_INITIATED':
console.log('🏦 Bank transfer initiated');
break;
case 'BRIDGE_TRANSFER_COMPLETED':
case 'COMPLETED':
console.log('✅ All processing complete!');
break;
case 'FAILED':
console.log('❌ Processing failed:', paymentLink.off_ramp_error);
break;
}
}
Destination Types
POLAR_BALANCE
Funds are added to your SuiPay balance and can be withdrawn later:
const balancePayment = await client.paymentLinks.create({
amount_usdc: 100,
description: 'Add to balance',
destination_type: PaymentDestinationType.POLAR_BALANCE
});
// Funds will be added to your polar_balance_usdc after payment
BANK_ACCOUNT
Funds are automatically sent to your connected bank account:
// First, get your bank accounts
const bankAccounts = await client.user.getBankAccounts();
const primaryAccount = bankAccounts.find(account => account.is_verified);
if (primaryAccount) {
const bankPayment = await client.paymentLinks.create({
amount_usdc: 200,
description: 'Payment to bank',
destination_type: PaymentDestinationType.BANK_ACCOUNT,
bank_account_id: primaryAccount.id
});
} else {
console.log('No verified bank account available');
}
Requirements:
KYC verification must be completed (
user.kyc_complete === true
)Bank account must be connected and verified
More complex processing with multiple steps
CUSTOM_ADDRESS
Funds are sent directly to a specified SUI address:
const customPayment = await client.paymentLinks.create({
amount_usdc: 50,
description: 'Direct wallet payment',
destination_type: PaymentDestinationType.CUSTOM_ADDRESS,
custom_sui_address: '0x1234567890abcdef1234567890abcdef12345678'
});
Requirements:
Valid SUI address starting with "0x"
Address format is validated during creation
Error Handling
Handle common errors when working with payment links:
import {
SuiPayValidationError,
SuiPayAuthenticationError
} from '@suipay/api';
try {
const paymentLink = await client.paymentLinks.create({
amount_usdc: 100,
description: 'Test payment',
destination_type: PaymentDestinationType.BANK_ACCOUNT,
bank_account_id: 'invalid_bank_id'
});
} catch (error) {
if (error instanceof SuiPayValidationError) {
console.error('Validation error:', error.response?.error);
// Common issues: invalid bank_account_id, missing custom_sui_address
} else if (error instanceof SuiPayAuthenticationError) {
console.error('Authentication failed');
} else {
console.error('Unexpected error:', error);
}
}
Complete Example
Here's a comprehensive example showing payment link creation and monitoring:
import { PaymentDestinationType, OffRampStatus } from '@suipay/api';
async function createAndMonitorPayment() {
try {
// Create payment link
const paymentLink = await client.paymentLinks.create({
amount_usdc: 100,
description: 'Service payment',
destination_type: PaymentDestinationType.POLAR_BALANCE
});
console.log(`Payment link created: ${paymentLink.url}`);
console.log('Share this link with your customer');
// Monitor payment status (you might do this in a webhook or polling)
const checkStatus = async () => {
const updated = await client.paymentLinks.get(paymentLink.id);
if (updated.paid) {
console.log('✅ Payment received!');
console.log(`Transaction: ${updated.transaction_digest}`);
console.log(`From: ${updated.transaction_payer}`);
return true;
} else {
console.log('⏳ Still waiting for payment...');
return false;
}
};
// Poll every 30 seconds (in production, use webhooks instead)
const pollInterval = setInterval(async () => {
const completed = await checkStatus();
if (completed) {
clearInterval(pollInterval);
}
}, 30000);
} catch (error) {
console.error('Error creating payment link:', error);
}
}
Important Notes
Minimum payment: 0.01 USDC
Expiration: Payment links can have expiration times
Status tracking: Use webhooks or polling to monitor payment status
Off-ramp timing: Bank account destinations take longer due to settlement times
Transaction hashes: Stored for audit trails and verification
Last updated