Creating Payments
Learn how to create payment links and accept payments from customers
Overview
To accept a payment, you'll create a payment via the API, which returns a checkout_url. Redirect your customer to this URL to complete the payment.
Endpoint
POST https://payzo.cc/api/v1/payments
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Yes | Amount in cents (e.g., 1000 = $10.00). Minimum: 50 ($0.50) |
currency | string | No | Currency code. Default: "usd" |
success_url | string | Yes | URL to redirect customer after successful payment |
cancel_url | string | No | URL to redirect customer if they cancel |
customer_email | string | No | Customer's email address |
customer_name | string | No | Customer's name |
description | string | No | Payment description (internal use) |
metadata | object | No | Custom key-value data to attach to payment |
Response
Success (201 Created)
{
"id": "pay_abc123def456",
"status": "pending",
"amount": 5000,
"currency": "usd",
"checkout_url": "https://payzo.cc/checkout/my-shop/pay_abc123def456",
"created_at": "2025-01-12T10:30:00.000Z"
}
| Field | Description |
|---|---|
id | Unique payment identifier |
status | Payment status: pending, completed, failed, expired |
amount | Amount in cents |
currency | Currency code |
checkout_url | URL to redirect your customer to |
created_at | ISO 8601 timestamp |
Complete Example
Node.js / Express
const express = require('express');
const app = express();
app.post('/create-payment', async (req, res) => {
try {
// Create payment with Payzo
const response = await fetch('https://payzo.cc/api/v1/payments', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PAYZO_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 5000, // $50.00
currency: 'usd',
success_url: 'https://yoursite.com/payment/success',
cancel_url: 'https://yoursite.com/payment/cancel',
customer_email: req.body.email,
customer_name: req.body.name,
metadata: {
order_id: req.body.orderId,
user_id: req.body.userId,
product: req.body.product
}
})
});
if (!response.ok) {
const error = await response.json();
return res.status(400).json({ error: error.error });
}
const payment = await response.json();
// Save payment ID to your database
await db.orders.update({
id: req.body.orderId,
payzo_payment_id: payment.id,
status: 'pending_payment'
});
// Redirect customer to checkout
res.json({ checkout_url: payment.checkout_url });
} catch (error) {
console.error('Payment creation error:', error);
res.status(500).json({ error: 'Failed to create payment' });
}
});
Python / Flask
from flask import Flask, request, jsonify
import requests
import os
app = Flask(__name__)
@app.route('/create-payment', methods=['POST'])
def create_payment():
try:
# Create payment with Payzo
response = requests.post(
'https://payzo.cc/api/v1/payments',
headers={
'Authorization': f'Bearer {os.getenv("PAYZO_API_KEY")}',
'Content-Type': 'application/json'
},
json={
'amount': 5000, # $50.00
'currency': 'usd',
'success_url': 'https://yoursite.com/payment/success',
'cancel_url': 'https://yoursite.com/payment/cancel',
'customer_email': request.json.get('email'),
'customer_name': request.json.get('name'),
'metadata': {
'order_id': request.json.get('order_id'),
'user_id': request.json.get('user_id'),
'product': request.json.get('product')
}
}
)
if not response.ok:
error = response.json()
return jsonify({'error': error.get('error')}), 400
payment = response.json()
# Save payment ID to your database
# db.orders.update(...)
# Return checkout URL to frontend
return jsonify({'checkout_url': payment['checkout_url']})
except Exception as e:
print(f'Payment creation error: {e}')
return jsonify({'error': 'Failed to create payment'}), 500
PHP
<?php
function createPayment($amount, $email, $orderId) {
$apiKey = getenv('PAYZO_API_KEY');
$data = [
'amount' => 5000, // $50.00
'currency' => 'usd',
'success_url' => 'https://yoursite.com/payment/success',
'cancel_url' => 'https://yoursite.com/payment/cancel',
'customer_email' => $email,
'metadata' => [
'order_id' => $orderId
]
];
$ch = curl_init('https://payzo.cc/api/v1/payments');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 201) {
$error = json_decode($response, true);
throw new Exception($error['error']);
}
$payment = json_decode($response, true);
// Save to database
// updateOrder($orderId, $payment['id']);
return $payment['checkout_url'];
}
// Usage
try {
$checkoutUrl = createPayment(5000, 'customer@example.com', 'order_123');
header('Location: ' . $checkoutUrl);
exit;
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Metadata Usage
Use metadata to store custom information:
metadata: {
order_id: 'ORD-12345',
user_id: 'user_789',
product_name: 'Premium Plan',
quantity: 1,
discount_code: 'SAVE20'
}
This data will be:
- Returned in webhook notifications
- Visible in your dashboard
- Included when retrieving payment details
Error Handling
Common Errors
Amount Too Small
{
"error": "Amount must be at least 50 cents"
}
Solution: Ensure amount is ≥ 50 (cents).
Missing Success URL
{
"error": "success_url is required"
}
Solution: Always include success_url.
Invalid API Key
{
"error": "Invalid API key"
}
Solution: Check your API key in the Authorization header.
Payment Flow
Here's how the complete payment process works:
1. Customer → Your Site
Customer clicks "Buy Now" button
2. Your Site → Payzo API
POST /api/v1/payments (create payment)
3. Payzo API → Your Site
Returns checkout_url
4. Your Site → Customer
Redirects customer to checkout_url
5. Customer → Payzo Checkout
Customer enters payment details (card info)
6. Payzo → Payment Processor
Securely processes card payment
7. Payment Processor → Payzo
Payment succeeded
8. Payzo → Your Webhook
POST payment.completed event
9. Payzo → Customer
Redirects to your success_url
10. Your Webhook → Your System
Fulfills order (e.g., deliver game items)
Best Practices
1. Always Store Payment IDs
// Save payment ID to your database before redirecting
await db.orders.create({
id: orderId,
payzo_payment_id: payment.id,
amount: payment.amount,
status: 'pending'
});
// Then redirect
res.redirect(payment.checkout_url);
2. Use Webhooks, Not Polling
// Bad: Don't poll for status
setInterval(async () => {
const status = await checkPaymentStatus(paymentId);
}, 5000);
// Good: Use webhooks
app.post('/webhook', (req, res) => {
const { event, payment } = req.body;
if (event === 'payment.completed') {
completeOrder(payment.metadata.order_id);
}
});
3. Validate Amounts
// Always validate on your server
const amount = Math.round(req.body.amount);
if (amount < 50) {
return res.status(400).json({ error: 'Minimum $0.50' });
}