Quick start
- Create a merchant account.
- Create a project for your website, bot or service.
- Set a valid Website URL. This domain is linked to the project.
- Use Test API credentials to create test payments and verify redirects/webhooks.
- Switch the project to Live mode when your integration is ready.
- Replace test credentials with live credentials in your backend.
Important: API credentials must be used only on your backend/server side. Never place API secrets inside frontend JavaScript.
Project Website URL
Each project must have a valid Website URL. This URL links your project to a real domain.
| Rule | Description |
|---|---|
| Unique website | The same Website URL cannot be linked to multiple projects. |
| Valid domain | Localhost, IP addresses and invalid hosts are rejected. |
| Success URL domain | If success_url is sent in API request, it must use the same domain as Website URL. |
| Fail URL domain | If fail_url is sent in API request, it must use the same domain as Website URL. |
| Webhook URL | Webhook URL may be configured separately for payment notifications. |
Example: if your Website URL is https://example.com, then success_url and fail_url must also use example.com.
Test and Live mode
Each project has two API credential sets:
| Credential type | Example | Purpose |
|---|---|---|
| test | pk_test_xxxsk_test_xxx | Creates test payments. No real blockchain transfer is required. |
| live | pk_xxxsk_xxx | Creates real USDT TRC20 payments. |
New projects start in Test mode. Test payments do not increase project balance and cannot be withdrawn.
When the project is switched to Live mode, use live credentials for real payments.
Authentication
Every API request must include your project API key and a HMAC SHA-256 signature of the raw JSON body.
Content-Type: application/json
X-API-Key: pk_test_or_live_api_key
X-Signature: hmac_sha256(raw_json_body, sk_test_or_live_api_secret)
Use test key with test secret, and live key with live secret. Do not mix credential sets.
Keep your API secret private. Never expose it in browser JavaScript, frontend code or public repositories.
Create payment
Send a signed JSON request to create a hosted USDT TRC20 payment page.
https://crypto-pay.one/api/create-payment.php{
"order_id": "ORDER_12345",
"amount": "50.00",
"description": "Service payment",
"success_url": "https://merchant-site.com/success",
"fail_url": "https://merchant-site.com/fail"
}
Request parameters
| Parameter | Required | Description |
|---|---|---|
order_id | Yes | Your unique order ID. Use your own order number or invoice ID. |
amount | Yes | Payment amount in USDT. |
description | No | Short payment description shown in your integration records. |
success_url | No | Customer redirect URL after successful payment flow. Must match project Website URL domain. |
fail_url | No | Customer redirect URL after cancellation, expiration or failed payment flow. Must match project Website URL domain. |
Successful response
{
"ok": true,
"payment": {
"payment_id": 123,
"order_id": "ORDER_12345",
"status": "pending",
"amount": "50.00",
"pay_amount": "50.013400",
"currency": "USDT",
"network": "TRC20",
"address": "Txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"payment_url": "https://crypto-pay.one/pay/?id=123",
"expires_at": "2026-07-01 18:30:00",
"is_test": false
}
}
Redirect the customer to payment_url. The hosted checkout page will show the TRC20 address, exact amount and payment status.
Payment status
You can check payment status by payment ID.
https://crypto-pay.one/api/payment-status.php?payment_id=123| Status | Meaning |
|---|---|
| pending | Waiting for customer payment. |
| paid | The required USDT TRC20 transaction was detected and confirmed, or a test payment was completed in Test mode. |
| expired | The payment window ended before the customer completed the payment. |
| failed | The payment cannot be completed or was rejected by the system. |
Webhooks
When a payment becomes paid, Crypto Pay sends a signed POST request to your project webhook URL.
POST https://merchant-site.com/webhook.php
Content-Type: application/json
X-Signature: hmac_sha256(raw_json_body, sk_your_api_secret)
{
"payment_id": 123,
"app_id": 45,
"order_id": "ORDER_12345",
"status": "paid",
"amount": "50.00",
"pay_amount": "50.013400",
"currency": "USDT",
"network": "TRC20",
"txid": "transaction_hash_or_test_id",
"paid_at": "2026-07-01 18:04:12",
"is_test": false
}
Expected webhook response
HTTP/1.1 200 OK
The gateway automatically retries failed webhook delivery after 5 minutes, 15 minutes and 1 hour. If all retry attempts fail, the webhook is marked as failed.
Any HTTP 2xx response is treated as successful webhook delivery. Always verify the X-Signature header before updating an order on your side.
Important: Do not mark an order as paid only because the customer was redirected to your success URL. Always wait for a signed webhook with status paid before providing goods, credits, access or services.
Error responses
Every API error response contains ok: false and an error message.
{
"ok": false,
"error": "Invalid API key"
}
{
"ok": false,
"error": "Invalid signature"
}
{
"ok": false,
"error": "Project website is not configured."
}
{
"ok": false,
"error": "Success URL domain does not match project website."
}
{
"ok": false,
"error": "Fail URL domain does not match project website."
}
{
"ok": false,
"error": "Project is currently in Test mode. Use test API credentials or switch project to Live mode."
}
{
"ok": false,
"error": "Project is disabled."
}
{
"ok": false,
"error": "Amount must be greater than zero"
}
Always check the ok field before processing a response.
PHP example
This example creates a payment and redirects the customer to the hosted checkout page. Use pk_test_.../sk_test_... for test payments and pk_live_.../sk_live_... for real payments.
<?php
$apiKey = 'pk_test_your_api_key';
$apiSecret = 'sk_test_your_api_secret';
$body = json_encode([
'order_id' => 'ORDER_12345',
'amount' => '50.00',
'description' => 'Service payment',
'success_url' => 'https://merchant-site.com/success',
'fail_url' => 'https://merchant-site.com/fail'
], JSON_UNESCAPED_SLASHES);
$signature = hash_hmac('sha256', $body, $apiSecret);
$ch = curl_init('https://crypto-pay.one/api/create-payment.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . $apiKey,
'X-Signature: ' . $signature,
],
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($response === false) {
exit('Connection error: ' . $error);
}
$data = json_decode($response, true);
if (!empty($data['ok']) && !empty($data['payment']['payment_url'])) {
header('Location: ' . $data['payment']['payment_url']);
exit;
}
echo 'API error: ' . ($data['error'] ?? 'Unknown error');
Official plugins
Official integration plugins are available for popular e-commerce platforms.