Gunakan alat ini untuk mengecek apakah IP perangkat/server Anda dapat menjangkau server Cutiezy atau terblokir firewall. Masukkan IP yang ingin dicek di bawah.
Tes interaktif di atas mengecek koneksi dari browser Anda. Jika bot atau website Anda dihosting di VPS / cPanel Hosting / Cloud Server, alamat IP yang mengakses Cutiezy adalah IP publik server VPS Anda (bukan IP browser Anda). Jika script bot/toko Anda gagal terhubung (timeout / 403), kemungkinan IP VPS Anda yang terblokir firewall server. Lakukan pengujian langsung dari server VPS Anda menggunakan panduan di bawah.
Jalankan perintah cURL berikut di terminal SSH VPS atau server Anda untuk memastikan IP server Anda tidak terblokir:
curl -i -s "https://cutiezy.id/zy-pay/api/ping.php"
<?php
// Simpan sebagai test-koneksi.php di hosting/VPS Anda lalu akses via browser
$ch = curl_init("https://cutiezy.id/zy-pay/api/ping.php");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);
if ($curlErr) {
echo "<h2 style='color:red'>โ KONEKSI GAGAL / TIMEOUT</h2>";
echo "<p>Error cURL: " . htmlspecialchars($curlErr) . "</p>";
echo "<p>Segera hubungi Admin WhatsApp Cutiezy untuk unblock IP server Anda.</p>";
} elseif ($httpCode === 403 || $httpCode >= 400) {
echo "<h2 style='color:red'>โ KONEKSI DITOLAK / TERBLOKIR FIREWALL SERVER (HTTP $httpCode)</h2>";
echo "<p>IP server Anda terblokir oleh firewall server Cutiezy. Segera salin respon berikut dan kirim ke Admin WhatsApp:</p>";
echo "<pre>" . htmlspecialchars($response) . "</pre>";
} else {
echo "<h2 style='color:green'>โ
KONEKSI BERHASIL (HTTP $httpCode)</h2>";
echo "<pre>" . htmlspecialchars($response) . "</pre>";
}
?>
import requests
try:
res = requests.get("https://cutiezy.id/zy-pay/api/ping.php", timeout=15)
print(f"Status HTTP: {res.status_code}")
print(res.json())
except requests.exceptions.RequestException as e:
print(f"โ KONEKSI GAGAL / IP TERBLOKIR: {e}")
print("Hubungi Admin WhatsApp Cutiezy untuk unblock IP server Anda.")
// Skrip tes koneksi Node.js (Untuk Bot Panel Pterodactyl, Baileys, Discord, VPS)
// Pilihan A: Menggunakan Fetch (Node.js 18+ bawaan tanpa library luar)
async function testZyPayPing() {
try {
const res = await fetch("https://cutiezy.id/zy-pay/api/ping.php", {
headers: { "Accept": "application/json" },
signal: AbortSignal.timeout(15000)
});
const data = await res.json();
console.log("โ
KONEKSI BERHASIL (HTTP " + res.status + "):", data);
console.log("๐ IP Penembak Bot / Node Pterodactyl Anda:", data.ip_penembak || data.client_ip);
console.log("๐ Status Proteksi Server:", data.status_ip);
} catch (err) {
console.error("โ KONEKSI GAGAL / IP BOT DIBLOKIR FIREWALL:", err.message);
console.error("๐ Jika pakai Panel Pterodactyl, IP yang diblokir adalah IP Node server Pterodactyl Anda.");
console.error("๐ Segera kirimkan IP ke Admin WhatsApp Cutiezy untuk di-unblock.");
}
}
testZyPayPing();
/* Pilihan B: Menggunakan Axios (npm i axios)
const axios = require('axios');
axios.get("https://cutiezy.id/zy-pay/api/ping.php", { timeout: 15000 })
.then(res => console.log("โ
KONEKSI SUKSES:", res.data))
.catch(err => console.error("โ KONEKSI GAGAL / IP TERBLOKIR:", err.message));
*/
| Gejala / Pesan Error | Penyebab | Solusi |
|---|---|---|
cURL error 28: Operation timed out |
IP diblokir firewall (CSF/iptables) | Hubungi Admin untuk unblock IP |
cURL error 7: Failed to connect |
Koneksi ditolak oleh firewall / port tertutup | Hubungi Admin untuk unblock IP |
ETIMEDOUT / ECONNREFUSED / AxiosError |
IP Node server Pterodactyl / VPS diblokir firewall | Hubungi Admin WA untuk unblock IP Node bot |
HTTP 403 Forbidden / Access Denied |
ModSecurity / WAF / Proteksi bot mendeteksi anomali | Kirim IP ke Admin untuk dibuatkan whitelist |
Salin IP Anda (cek via command curl -s ifconfig.me di VPS) dan hubungi Admin Cutiezy untuk pembukaan blokir seketika.
Tersedia panduan resmi & script siap copy-paste untuk platform populer:
Get started with Cutiezy API in minutes!
# Base URL
https://cutiezy.id/zy-pay/api/v1/
# Authentication Header
X-API-Key: ak_7d8f9e1a2b3c4d5e6f7a8b9c0d1e2f3
# First API Call (Create Payment)
curl -X POST "https://cutiezy.id/zy-pay/api/v1/create-payment" \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{"amount": 10000, "description": "Test payment"}'
API Keys
All API requests require authentication via API Key.
X-API-Key: ak_7d8f9e1a2b3c4d5e6f7a8b9c0d1e2f3
Settings โ API KeysAPI rate limits to ensure service stability.
| Endpoint | Limit | Window | Description |
|---|---|---|---|
POST /create-payment |
1 request | 3 seconds | Prevent duplicate payments |
GET /check-payment |
10 requests | 1 second | Status checking |
GET /mutations |
5 requests | 10 seconds | History retrieval |
GET /balance |
10 requests | 1 second | Check Cutiezy balance |
All endpoints |
100 requests | 1 minute | Global rate limit |
Create a new QRIS payment request.
{
"amount": 10000,
"description": "Payment for order #123",
"webhook_url": "https://your-webhook.com/callback",
"public_theme": "theme2"
}
| Parameter | Type | Required | Description | Constraints |
|---|---|---|---|---|
amount Required |
integer | โ | Payment amount in IDR | 1,000 - 10,000,000 |
description Optional |
string | โ | Payment description | Max 255 characters |
webhook_url Optional |
string | โ | Webhook URL for notifications | Valid HTTPS URL |
public_theme Optional |
string | โ | Theme for the public payment page | theme1, theme2, or theme3 (default: theme1) |
{
"success": true,
"message": "Payment created successfully",
"data": {
"transaction_id": "QRIS20241230123045ABCDEF",
"reference_id": 12345,
"amount": 10000,
"fee": 50,
"total_amount": 10075,
"payment_method": "QRIS",
"qris_image_url": "https://cutiezy.id/zy-pay/dashboard/qris/temp/qris_example.jpg",
"qris_image_base64": "data:image/jpeg;base64,...",
"qris_string": "00020101021126670014...",
"expired_at": "2024-12-30 12:45:45",
"status": "pending",
"public_payment_url": "https://cutiezy.id/zy-pay/pay.php?id=HASHED_123",
"public_theme": "theme2",
"check_status_url": "https://cutiezy.id/zy-pay/api/v1/check-payment/QRIS20241230123045ABCDEF",
"webhook_url": "https://your-webhook.com/callback",
"created_at": "2024-12-30 12:30:45"
}
}
// Fee = 0.5% of amount (rounded down) fee = Math.floor(amount * 0.5 / 100); // Total = Amount + Fee total_amount = amount + fee;
Check payment status by transaction ID. Supports both URL path and query parameter.
OR: GET /check-payment?transaction_id={transaction_id}
OR: GET /check-payment?id={reference_id}
{
"success": true,
"data": {
"transaction_id": "QRIS20241230123045ABCDEF",
"reference_id": 12345,
"amount": 10000,
"fee": 50,
"total_amount": 10075,
"status": "paid",
"payment_method": "QRIS",
"qris_image_url": "https://cutiezy.id/qris/QRIS20241230123045ABCDEF.png",
"expired_at": "2024-12-30 12:45:45",
"paid_at": "2024-12-30 12:33:20",
"settlement_at": "2024-12-30 20:33:20",
"description": "Payment for order #123",
"created_at": "2024-12-30 12:30:45",
"updated_at": "2024-12-30 12:33:20"
}
}
Cancel a pending payment before it expires or gets paid.
{
"transaction_id": "QRIS20241230123045ABCDEF"
}
OR:
{
"id": 12345
}
{
"success": true,
"message": "Payment cancelled successfully",
"data": {
"transaction_id": "QRIS20241230123045ABCDEF",
"reference_id": 12345,
"status": "cancelled",
"cancelled_at": "2024-12-30 12:35:10"
}
}
Get transaction history with filtering, pagination, and date range.
| Parameter | Type | Default | Description |
|---|---|---|---|
start_date |
string | Current month 1st | Format: YYYY-MM-DD |
end_date |
string | Today | Format: YYYY-MM-DD |
status |
string | (all) | Filter by status |
page |
integer | 1 | Page number (โฅ1) |
limit |
integer | 50 | Items per page (max 100) |
GET /mutations?start_date=2024-12-01&end_date=2024-12-31&status=paid&page=1&limit=20
{
"success": true,
"data": [
{
"transaction_id": "QRIS20241230123045ABCDEF",
"reference_id": 12345,
"amount": 10000,
"fee": 50,
"total_amount": 10075,
"status": "paid",
"payment_method": "QRIS",
"qris_image_url": "https://cutiezy.id/qris/QRIS20241230123045ABCDEF.png",
"expired_at": "2024-12-30 12:45:45",
"paid_at": "2024-12-30 12:33:20",
"description": "Payment for order #123",
"created_at": "2024-12-30 12:30:45"
}
],
"pagination": {
"total": 45,
"page": 1,
"limit": 20,
"pages": 3
},
"filters": {
"start_date": "2024-12-01",
"end_date": "2024-12-31",
"status": "paid"
}
}
Get user profile information, balance, and transaction statistics.
{
"success": true,
"data": {
"user": {
"user_id": 1,
"username": "johndoe",
"email": "[email protected]",
"role": "user"
},
"balance": {
"available": 1500000.00,
"currency": "IDR"
},
"cutiezy": {
"connected": true,
"card": "41680512",
"username": "cutiezy_user",
"name": "John Doe",
"level": "Basic",
"balance": 150000,
"balance_formatted": "Rp 150.000"
},
"stats": {
"total": {
"pending": 2,
"paid": 45,
"expired": 3,
"cancelled": 1,
"total_amount": 4500000
},
"today": {
"transactions": 5,
"paid_amount": 250000
}
},
"settings": {
"fee_percentage": 0.5,
"min_amount": 1000,
"max_amount": 10000000
}
}
}
Memeriksa saldo dan status akun Cutiezy yang terhubung dengan akun Zy-Pay Anda (berdasarkan ID Card member).
GET dan POST. API Key dapat dikirimkan melalui header X-API-Key, Authorization: Bearer, ataupun query parameter ?api_key=....
X-API-Key: ak_your_api_key_here
curl -X GET "https://cutiezy.id/zy-pay/api/v1/balance" \ -H "X-API-Key: ak_your_api_key_here"
<?php
$apiKey = "ak_your_api_key_here";
$ch = curl_init("https://cutiezy.id/zy-pay/api/v1/balance");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-Key: " . $apiKey,
"Accept: application/json"
],
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
echo "Saldo Cutiezy: " . $result['data']['balance_formatted'];
?>
{
"success": true,
"status": true,
"message": "OK",
"data": {
"user_id": 1,
"username": "johndoe",
"cutiezy_connected": true,
"cutiezy_card": "41680512",
"cutiezy_username": "cutiezy_user",
"cutiezy_name": "John Doe",
"cutiezy_level": "Basic",
"balance": 150000,
"balance_formatted": "Rp 150.000",
"currency": "IDR",
"settlement_balance": 25000,
"settlement_balance_formatted": "Rp 25.000"
},
"timestamp": "2026-09-15 05:30:00"
}
{
"success": false,
"status": false,
"error": "ID Card Cutiezy belum dihubungkan pada akun ini. Hubungkan ID Card di menu Profile.",
"data": {
"cutiezy_connected": false,
"user_id": 1,
"username": "johndoe",
"balance": 0,
"settlement_balance": 25000
},
"timestamp": "2026-09-15 05:30:00"
}
Real-time notifications for payment events sent to your webhook URL.
Profile โ Webhook Settingswebhook_url parameter in create-payment request// Verify webhook signature
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
{
"event": "payment.paid",
"data": {
"transaction_id": "QRIS20241230123045ABCDEF",
"reference_id": 12345,
"amount": 10000,
"fee": 50,
"total_amount": 10075,
"status": "paid",
"payment_method": "QRIS",
"description": "Payment for order #123",
"paid_at": "2024-12-30 12:33:20",
"expired_at": "2024-12-30 12:45:45",
"settlement_at": "2024-12-30 20:33:20",
"created_at": "2024-12-30 12:30:45"
},
"timestamp": "2024-12-30 12:33:21"
}
| Header | Description | Example |
|---|---|---|
X-Webhook-Signature |
HMAC SHA256 signature | sha256=abc123... |
X-Webhook-Event |
Event type | payment.paid |
Content-Type |
Payload format | application/json |
User-Agent |
Sender identifier | ZyPay-Webhook/1.0 |
| Event | Description | Trigger Condition |
|---|---|---|
payment.pending |
Payment created | When user creates payment via API |
payment.paid |
Payment successful | When QRIS is scanned & paid |
payment.expired |
Payment expired | 30 minutes after creation (no payment) |
payment.cancelled |
Payment cancelled | User cancels via API or dashboard |
<?php
$apiKey = "ak_7d8f9e1a2b3c4d5e6f7a8b9c0d1e2f3";
$url = "https://cutiezy.id/zy-pay/api/v1/create-payment";
$data = [
"amount" => 10000,
"description" => "Order #123",
"webhook_url" => "https://your-store.com/webhook/payment"
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
"X-API-Key: $apiKey",
"Content-Type: application/json",
"Accept: application/json"
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($httpCode === 201) {
$result = json_decode($response, true);
if ($result['success']) {
echo "QRIS Image: " . $result['data']['qris_image_url'];
echo "Transaction ID: " . $result['data']['transaction_id'];
}
} else {
echo "Error $httpCode: $error";
}
?>
const axios = require('axios');
class CutiezyAPI {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseURL = 'https://cutiezy.id/zy-pay/api/v1';
}
async createPayment(amount, description, webhookUrl) {
try {
const response = await axios.post(
`${this.baseURL}/create-payment`,
{ amount, description, webhook_url: webhookUrl },
{
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
throw new Error(`Create payment failed: ${error.response?.data?.error || error.message}`);
}
}
async checkPayment(transactionId) {
try {
const response = await axios.get(
`${this.baseURL}/check-payment/${transactionId}`,
{
headers: {
'X-API-Key': this.apiKey
}
}
);
return response.data.data;
} catch (error) {
throw new Error(`Check payment failed: ${error.response?.data?.error || error.message}`);
}
}
async getMutations(options = {}) {
const params = new URLSearchParams({
start_date: options.startDate || new Date().toISOString().split('T')[0],
end_date: options.endDate || new Date().toISOString().split('T')[0],
status: options.status || '',
page: options.page || 1,
limit: options.limit || 50
});
try {
const response = await axios.get(
`${this.baseURL}/mutations?${params}`,
{
headers: {
'X-API-Key': this.apiKey
}
}
);
return response.data;
} catch (error) {
throw new Error(`Get mutations failed: ${error.response?.data?.error || error.message}`);
}
}
}
// Usage
const api = new CutiezyAPI('your_api_key_here');
const payment = await api.createPayment(10000, 'Test payment');
from flask import Flask, request, jsonify
import hmac
import hashlib
import json
from datetime import datetime
app = Flask(__name__)
WEBHOOK_SECRET = "your_webhook_secret_here"
def verify_signature(payload, signature):
"""Verify webhook signature"""
expected = hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
@app.route('/webhook/payment', methods=['POST'])
def payment_webhook():
try:
# Get headers and payload
signature = request.headers.get('X-Webhook-Signature', '')
event = request.headers.get('X-Webhook-Event', '')
payload = request.get_data()
# Verify signature
if not verify_signature(payload, signature):
return jsonify({'error': 'Invalid signature'}), 401
data = json.loads(payload)
# Process based on event type
if event == 'payment.paid':
transaction_id = data['data']['transaction_id']
amount = data['data']['amount']
# Update your database
print(f"[{datetime.now()}] Payment received: {transaction_id} - Rp {amount:,}")
# Return success response
return jsonify({'status': 'success'}), 200
elif event == 'payment.expired':
# Handle expired payment
pass
elif event == 'payment.cancelled':
# Handle cancelled payment
pass
return jsonify({'status': 'processed'}), 200
except Exception as e:
print(f"Webhook error: {str(e)}")
return jsonify({'error': 'Processing failed'}), 500
if __name__ == '__main__':
app.run(port=5000, debug=True)
#!/bin/bash
API_KEY="your_api_key_here"
BASE_URL="https://cutiezy.id/zy-pay/api/v1"
# 1. Create Payment
echo "Creating payment..."
CREATE_RESPONSE=$(curl -s -X POST "$BASE_URL/create-payment" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"description": "Test payment"
}')
TRANSACTION_ID=$(echo $CREATE_RESPONSE | jq -r '.data.transaction_id')
echo "Transaction ID: $TRANSACTION_ID"
echo "QRIS URL: $(echo $CREATE_RESPONSE | jq -r '.data.qris_image_url')"
# 2. Check Payment Status (polling example)
echo -e "\nChecking payment status..."
for i in {1..30}; do
STATUS_RESPONSE=$(curl -s -X GET "$BASE_URL/check-payment/$TRANSACTION_ID" \
-H "X-API-Key: $API_KEY")
STATUS=$(echo $STATUS_RESPONSE | jq -r '.data.status')
echo "Attempt $i: Status = $STATUS"
if [ "$STATUS" = "paid" ]; then
echo "โ
Payment successful!"
break
elif [ "$STATUS" = "expired" ] || [ "$STATUS" = "cancel" ]; then
echo "โ Payment failed: $STATUS"
break
fi
sleep 10 # Check every 10 seconds
done
# 3. Get Transaction History
echo -e "\nGetting transaction history..."
curl -s -X GET "$BASE_URL/mutations?limit=5" \
-H "X-API-Key: $API_KEY" | jq '.'
| HTTP Code | Error Code | Description | Solution |
|---|---|---|---|
| 400 | INVALID_REQUEST | Invalid JSON format or missing required fields | Check request body format |
| 400 | INVALID_AMOUNT | Amount outside valid range (1,000-10,000,000) | Adjust amount |
| 401 | UNAUTHORIZED | Invalid or missing API key | Check API key |
| 403 | FORBIDDEN | Insufficient permissions | Check user role |
| 404 | NOT_FOUND | Transaction not found | Check transaction ID |
| 409 | ALREADY_PROCESSED | Transaction already paid/expired/cancelled | Check transaction status |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests | Wait and retry |
| 500 | INTERNAL_ERROR | Internal server error | Contact support |
| 503 | SERVICE_UNAVAILABLE | Service temporarily unavailable | Retry later |
{
"success": false,
"error": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please wait 3 seconds before trying again.",
"timestamp": "2024-12-30 12:30:45",
"details": {
"cooldown_seconds": 3,
"endpoint": "create-payment"
}
}
GET /api/v1/balance untuk cek saldo akun Cutiezy yang terhubung.GET /api/v1/profile.GET /api/h2h/balance.php untuk integrasi Host-to-Host.