Get up and running with StacksPay development in minutes. This guide will have you generating and processing StacksPay URLs quickly.
Prerequisites
Section titled “Prerequisites”- Node.js 16+ or Python 3.8+ or Rust 1.70+
- Basic understanding of URL encoding and QR codes
- Familiarity with Stacks addresses (c32 format)
Installation
Section titled “Installation”TypeScript/JavaScript
Section titled “TypeScript/JavaScript”npm install stacks-pay# oryarn add stacks-pay
Python
Section titled “Python”pip install stacks-pay
[dependencies]stacks-pay = "0.1"
Your First StacksPay URL
Section titled “Your First StacksPay URL”Basic Invoice (TypeScript)
Section titled “Basic Invoice (TypeScript)”import { encodeStacksPayURL, decodeStacksPayURL } from 'stacks-pay';
// Create a payment request for 1 STXconst paymentURL = encodeStacksPayURL({ operation: 'invoice', recipient: 'SP2RTE7F21N6GQ6BBZR7JGGRWAT0T5Q3Z9ZHB9KRS', token: 'STX', amount: '1000000', // 1 STX in micro-STX description: 'Coffee purchase'});
console.log(paymentURL);// Output: web+stx:stxpay1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw4tcy8w6tpdf5qq...
// Decode and verifyconst decoded = decodeStacksPayURL(paymentURL);console.log(decoded);// Output: { operation: 'invoice', recipient: 'SP2RTE...', ... }
Basic Support Link (Python)
Section titled “Basic Support Link (Python)”from stacks_pay import encode_stacks_pay_url, decode_stacks_pay_url
# Create a tip/support link (amount chosen by payer)payment_url = encode_stacks_pay_url({ 'operation': 'support', 'recipient': 'SP2RTE7F21N6GQ6BBZR7JGGRWAT0T5Q3Z9ZHB9KRS', 'description': 'Support my work', 'token': 'STX'})
print(payment_url)# Output: web+stx:stxpay1qpzgk5q8getf3ts3jn54khce6mua7lmqqqxw4tcy8w6tpdf5qq...
# Decodedecoded = decode_stacks_pay_url(payment_url)print(decoded)
Basic Mint Link (Rust)
Section titled “Basic Mint Link (Rust)”use stacks_pay::{encode_stacks_pay_url, decode_stacks_pay_url, StacksPayParams};
// Create an NFT mint linklet params = StacksPayParams { operation: "mint".to_string(), contract_address: Some("SP2RTE7F21N6GQ6BBZR7JGGRWAT0T5Q3Z9ZHB9KRS.my-nft".to_string()), function_name: Some("claim".to_string()), token: Some("STX".to_string()), amount: Some("500000".to_string()), // 0.5 STX mint price description: Some("Mint unique NFT #1234".to_string()), ..Default::default()};
let payment_url = encode_stacks_pay_url(¶ms)?;println!("{}", payment_url);
// Decodelet decoded = decode_stacks_pay_url(&payment_url)?;
Core Concepts
Section titled “Core Concepts”Operations
Section titled “Operations”StacksPay supports three primary operations:
invoice
- Fixed amount payments (e.g., product purchases).support
- Variable amount payments (e.g., tips, donations).mint
- A general-purpose operation for making payments to smart contracts. While often used for NFT minting, it can be used to call any public function that requires a payment.
For a detailed guide on using the mint
operation for general contract calls, see the Smart Contract Payments documentation.
Amount Handling
Section titled “Amount Handling”Always use base units for amounts:
- STX: Use micro-STX (µSTX) where 1 STX = 1,000,000 µSTX
- SIP-010 tokens: Use the token's base unit (10^decimals)
// Helper functions for STX conversionfunction stxToMicroStx(stx: number): string { return (stx * 1_000_000).toString();}
function microStxToStx(microStx: string): number { return parseInt(microStx) / 1_000_000;}
// Example usageconst amount = stxToMicroStx(2.5); // "2500000" for 2.5 STX
Address Validation
Section titled “Address Validation”Always validate Stacks addresses before creating payment URLs:
import { validateStacksAddress } from '@stacks/transactions';
function isValidStacksAddress(address: string): boolean { try { validateStacksAddress(address); return true; } catch { return false; }}
// Use in your applicationif (!isValidStacksAddress(recipient)) { throw new Error('Invalid Stacks address');}
URL Structure
Section titled “URL Structure”StacksPay URLs follow this pattern:
web+stx:stxpay1[bech32m-encoded-data]
The encoded data contains a query string with operation parameters:
invoice?recipient=SP123...&token=STX&amount=1000000&description=Purchase
QR Code Generation
Section titled “QR Code Generation”Display payment URLs as QR codes for mobile scanning:
import QRCode from 'qrcode';
async function generatePaymentQR(paymentURL: string): Promise<string> { return await QRCode.toDataURL(paymentURL, { errorCorrectionLevel: 'M', type: 'image/png', margin: 1, color: { dark: '#000000', light: '#FFFFFF' } });}
// Usageconst qrDataURL = await generatePaymentQR(paymentURL);// Display in <img src={qrDataURL} alt="Payment QR Code" />
Error Handling
Section titled “Error Handling”Always handle potential errors when encoding/decoding:
import { StacksPayError } from 'stacks-pay';
try { const paymentURL = encodeStacksPayURL({ operation: 'invoice', recipient: 'INVALID_ADDRESS', // This will throw an error amount: '1000000', token: 'STX' });} catch (error) { if (error instanceof StacksPayError) { console.error('StacksPay error:', error.message); // Handle specific StacksPay errors } else { console.error('Unexpected error:', error); }}
Testing Your Integration
Section titled “Testing Your Integration”Manual Testing
Section titled “Manual Testing”- Generate a payment URL
- Copy and paste into a StacksPay-compatible wallet
- Verify the wallet displays correct payment details
- Complete a test transaction on testnet
Automated Testing
Section titled “Automated Testing”import { encodeStacksPayURL, decodeStacksPayURL } from 'stacks-pay';
describe('StacksPay Integration', () => { test('should create valid invoice URL', () => { const params = { operation: 'invoice' as const, recipient: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM', // testnet address token: 'STX', amount: '1000000', description: 'Test payment' };
const url = encodeStacksPayURL(params); expect(url).toMatch(/^web\+stx:stxpay1/);
const decoded = decodeStacksPayURL(url); expect(decoded).toMatchObject(params); });});
Next Steps
Section titled “Next Steps”Now that you have the basics working:
- Explore Examples: Check out real-world integration patterns
- Read the SDK docs: Learn about advanced features and configuration
- Set up testing: Implement proper testing and validation
- API Reference: Dive deep into all available parameters and options
Common Gotchas
Section titled “Common Gotchas”Amount Format
Section titled “Amount Format”// ❌ Wrong - using decimal STXamount: '1.5'
// ✅ Correct - using micro-STXamount: '1500000'
Address Format
Section titled “Address Format”// ❌ Wrong - using legacy formatrecipient: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'
// ✅ Correct - using Stacks c32 formatrecipient: 'SP2RTE7F21N6GQ6BBZR7JGGRWAT0T5Q3Z9ZHB9KRS'
URL Encoding
Section titled “URL Encoding”// ❌ Wrong - manually encodingconst description = encodeURIComponent('My product')
// ✅ Correct - let the library handle itconst params = { description: 'My product' // Library handles URL encoding}
Ready to build? Start with the SDK documentation for detailed API reference and advanced usage patterns.