Quickstart
Overview
This guide will walk you through integrating Unter payments into your application in under 15 minutes. You'll learn how to accept cryptocurrency payments with just a few API calls.
What you'll build: A simple payment flow that creates a payment request and processes the payment.
What you'll need:
An Unter merchant account with API keys
A basic understanding of REST APIs
A development environment (Node.js, Python, or PHP)
Step 1: Get Your API Key
Log into the Unter merchant portal
Navigate to Settings β API Keys
Create a new API key with these permissions:
create_paymentsview_paymentsmanage_payments
Copy your API key - it starts with
unter_and you'll only see it onceStore it securely in your environment variables
# Add to your .env file
UNTER_API_KEY=unter_abc123def456ghi789...Step 2: Explore Available Chains and Tokens
Before creating payments, discover what cryptocurrencies you can receive:
# Get all supported blockchains with their tokens
curl https://api.unter.tech/api/public/chains?include_tokens=trueThis returns chains like Ethereum, Polygon, and Solana with their available tokens (USDC, ETH, USDT, etc.).
Key points:
No authentication required for chain/token endpoints
Use the numeric
token_idwhen creating payment requestsDifferent chains support different tokens
Step 3: Create Your First Payment Request
Let's create a payment request for $10 USDC on Ethereum:
Find USDC on Ethereum
First, identify the token and chain IDs:
curl https://api.unter.tech/api/public/chains/1/tokens?stablecoins_only=trueFrom the response, you'll see USDC has:
token_id: 1 (example)chain_id: 1 (Ethereum)decimals: 6
Create the Payment Request
curl -X POST https://api.unter.tech/api/payment-requests \
-H "X-API-Key: unter_YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"amount": "10000000",
"token_id": 1,
"chain_id": 1,
"recipient_address": "0x742C4B8C2515Ad1D8e1C71e8e24c8D5F9A1a8B5A",
"external_id": "order_123",
"description": "Premium subscription payment"
}'Understanding the amount:
USDC has 6 decimals
$10.00 = 10,000,000 (add 6 zeros)
Always use strings, never floats
Success Response:
{
"data": {
"public_id": "550e8400-e29b-41d4-a716-446655440000",
"shortcode": "A4B2C8XZ",
"payment_url": "https://pay.unter.tech/pay/A4B2C8XZ",
"amount": {
"raw": "10000000",
"formatted": "10.00",
"decimals": 6
},
"status": "active",
"expires_at": "2024-08-15T18:00:00.000Z"
}
}Step 4: Handle Webhook Events
Create a webhook endpoint and configure it in your settings to receive payment notifications:
JavaScript (Express.js)
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use('/webhooks', express.raw({ type: 'application/json' }));
const WEBHOOK_SECRET = process.env.UNTER_WEBHOOK_SECRET; // From merchant portal
function verifyWebhookSignature(payload, signature, secret) {
const elements = {};
signature.split(',').forEach(pair => {
const [key, value] = pair.split('=');
elements[key] = value;
});
if (!elements.t || !elements.v1) return false;
const timestamp = parseInt(elements.t);
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(elements.v1, 'hex')
);
}
app.post('/webhooks/unter', (req, res) => {
const signature = req.headers['unter-signature'];
const payload = req.body.toString();
// Verify signature
if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(400).send('Invalid signature');
}
const event = JSON.parse(payload);
switch (event.type) {
case 'payment.succeeded':
handlePaymentSuccess(event.data.object);
break;
case 'payment.failed':
handlePaymentFailure(event.data.object);
break;
}
res.status(200).send('OK');
});
function handlePaymentSuccess(payment) {
console.log('Payment succeeded:', payment.id);
console.log('Amount:', payment.amount.formatted, payment.currency);
console.log('Order:', payment.reference);
// Update your database
// Send confirmation email
// Fulfill the order
}
function handlePaymentFailure(payment) {
console.log('Payment failed:', payment.id);
// Update order status
// Notify customer
}
app.listen(3000);Common Gotchas
1. Amount Format
β Wrong: "amount": 10.5 (number)
β
Correct: "amount": "10500000" (string in smallest unit)
2. Token/Chain Validation
β Wrong: Using token_id without checking if it exists on the chain β Correct: Validate token exists on specified chain first
3. Webhook Security
β Wrong: Processing webhooks without signature verification β Correct: Always verify webhook signatures
4. Error Handling
β Wrong: Not handling API errors gracefully β Correct: Implement proper try/catch with specific error handling
Next Steps
Now that you have a working integration:
Set up proper webhook handling for production
Learn about all API endpoints for advanced features
Implement error handling for edge cases
Add payment cancellation functionality
Explore all supported chains and tokens
Last updated