Developer Docs
Integrate PayCow's crypto payment gateway into your platform in minutes. Accept USDT payments on ERC-20 with real-time blockchain confirmation.
Overview
PayCow provides a simple RESTful API to create and track crypto payment sessions. Your backend creates a payment session and redirects the end user to our hosted checkout page, which handles all blockchain interactions automatically.
https://paycow.netAll API requests must be made over HTTPS.
Integration Flow
The typical integration works as follows:
1. Your server → POST /api/payment/create → receives { paymentId, checkoutUrl }
2. Redirect your user to checkoutUrl
3. PayCow monitors the blockchain and marks payment as PAID
4. Your server polls GET /payment/data/:id to check status
Authentication
All API requests require your API key and secret, passed as HTTP headers. You receive these credentials after your operator account is approved by the PayCow admin.
x-api-key: your_api_key_here x-api-secret: your_api_secret_here
Finding Your Credentials
Log into your operator dashboard at /dashboard.html. Your API Key and Secret are displayed in the Credentials section of your profile.
Error Handling
PayCow uses standard HTTP status codes. Error responses return a JSON body with a msg field explaining the problem.
| Status Code | Meaning |
|---|---|
| 200 / 201 | Success |
| 400 | Bad Request — missing or invalid parameters |
| 401 | Unauthorized — invalid or missing credentials |
| 403 | Forbidden — account suspended or inactive |
| 404 | Not Found — resource does not exist |
| 500 | Internal Server Error — try again later |
Create Payment
Creates a new payment session and returns a unique payment ID and hosted checkout URL to redirect your user to.
Request Body
| Field | Type | Description |
|---|---|---|
| amount required | number | Payment amount in USDT (e.g. 50.00) |
| userId required | string | Your platform's unique user identifier |
| network required | string | Blockchain network — currently only ERC20 is supported |
| currency optional | string | Currency code, default: USDT |
Example Request
curl -X POST https://paycow.net/api/payment/create \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-api-secret: YOUR_API_SECRET" \
-d '{
"amount": 50.00,
"userId": "user_123456",
"network": "ERC20"
}'
Success Response 200
{
"sessionId": "648f3a...",
"paymentUrl": "https://paycow.net/payment/648f3a...",
"paymentReference": "a1b2c3d4e5f6a7b8",
"depositAddress": "0xABCDEF...",
"expiresAt": "2026-03-12T22:30:00.000Z"
}
Get Payment Status
Retrieves the current status and details of a payment session. Poll this endpoint to track the lifecycle of a payment.
Path Parameters
| Parameter | Description |
|---|---|
| paymentId required | The payment ID returned from POST /api/payment/create |
Example Request
curl https://paycow.net/payment/data/648f3a...
Success Response 200
{
"_id": "648f3a...",
"userId": "user_123456",
"amountRequested": 50.00,
"amountReceived": 50.00,
"currencyInfo": "USDT",
"depositAddress": "0xABCDEF...",
"depositNetwork": "ERC20",
"status": "PAID",
"confirmations": 12,
"paymentReference": "PAY-8X91KZ",
"txHash": "0x1a2b3c...",
"expiresAt": "2026-03-12T22:30:00.000Z",
"createdAt": "2026-03-12T21:30:00.000Z"
}
Payment States
A payment session progresses through these states during its lifecycle:
- PENDING Awaiting deposit from the user. The checkout page is active.
- DETECTED An incoming transaction has been detected on-chain, awaiting confirmations.
- CONFIRMING Transaction found, accumulating block confirmations (requires 12).
- PAID Payment confirmed with sufficient confirmations. Credits the operator balance.
- EXPIRED The payment window elapsed without a detected deposit.
- REJECTED Payment manually declined by the operator.
Security & Best Practices
Ensuring the security of your integration is paramount. Follow these guidelines to protect your credentials and your users' funds.
1. API Credential Safety
Your API Secret should be treated like a password. Never include it in frontend code, mobile apps, or any client-side environment. Always execute API calls from your secure backend server.
2. Idempotency & References
Use the userId field to link payments to your internal users. Store the PayCow sessionId and paymentReference in your database to prevent duplicate processing and for audit purposes.
3. Blockchain Confirmations
PayCow requires 12 confirmations on the Ethereum blockchain for ERC20 USDT transfers before marking a payment as PAID. This protects against chain reorgs and ensures finality. While the state is CONFIRMING, you should wait for the final PAID status before delivering goods or services.
4. HTTPS Only
All production traffic to paycow.net is forced over HTTPS. Ensure your local development environment also uses secure connections when communicating with our API.
Code Examples
Node.js — Create a Payment
const response = await fetch('https://paycow.net/api/payment/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.PAYCOW_API_KEY,
'x-api-secret': process.env.PAYCOW_API_SECRET,
},
body: JSON.stringify({
amount: 50.00,
userId: 'user_123456',
network: 'ERC20',
}),
});
const { sessionId, paymentUrl } = await response.json();
res.redirect(paymentUrl);
Python — Create a Payment
import requests
import os
url = "https://paycow.net/api/payment/create"
headers = {
"Content-Type": "application/json",
"x-api-key": os.getenv("PAYCOW_API_KEY"),
"x-api-secret": os.getenv("PAYCOW_API_SECRET")
}
data = {
"amount": 50.00,
"userId": "user_123456",
"network": "ERC20"
}
response = requests.post(url, json=data, headers=headers)
result = response.json()
# Redirect user to result['paymentUrl']
Go — Create a Payment
package main
import (
"bytes"
"encoding/json"
"net/http"
"os"
)
func main() {
url := "https://paycow.net/api/payment/create"
data := map[string]interface{}{
"amount": 50.00,
"userId": "user_123456",
"network": "ERC20",
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-api-key", os.Getenv("PAYCOW_API_KEY"))
req.Header.Set("x-api-secret", os.Getenv("PAYCOW_API_SECRET"))
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
// Parse resp.Body to get paymentUrl
}
PHP — Create a Payment
$ch = curl_init('https://paycow.net/api/payment/create');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'amount' => 50.00,
'userId' => $user_id,
'network' => 'ERC20'
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'x-api-key: ' . getenv('PAYCOW_API_KEY'),
'x-api-secret: ' . getenv('PAYCOW_API_SECRET'),
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = json_decode(curl_exec($ch), true);
header('Location: ' . $result['paymentUrl']);
C# — Create a Payment
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
var data = new { amount = 50.00, userId = "user_123456", network = "ERC20" };
var content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("PAYCOW_API_KEY"));
client.DefaultRequestHeaders.Add("x-api-secret", Environment.GetEnvironmentVariable("PAYCOW_API_SECRET"));
var response = await client.PostAsync("https://paycow.net/api/payment/create", content);
var result = await response.Content.ReadAsStringAsync();
// Parse JSON and redirect to paymentUrl
Rust — Create a Payment
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box> {
let client = reqwest::Client::new();
let mut headers = HeaderMap::new();
headers.insert("x-api-key", HeaderValue::from_str(&std::env::var("PAYCOW_API_KEY")?)?);
headers.insert("x-api-secret", HeaderValue::from_str(&std::env::var("PAYCOW_API_SECRET")?)?);
let data = json!({ "amount": 50.0, "userId": "user_1", "network": "ERC20" });
let res = client.post("https://paycow.net/api/payment/create")
.headers(headers)
.json(&data)
.send().await?.json::<serde_json::Value>().await?;
println!("URL: {}", res["paymentUrl"]);
Ok(())
}