- Non-custodial
- Paid straight to your wallet
- 9 networks · USDT and USDC
Accept crypto.
Get paid straight to your wallet.
Ready-made crypto payment processing for your website, app or bot. Create an invoice with one API call, send the customer to our checkout page, and get a webhook once the network confirms the payment.
- Sandbox with no real money
- Clients for Node, PHP, Python, Go
- Signed webhooks with retries
a1f3…9c0e · TRONChoose a currency
Send the exact amount
Payment detected
Waiting for TRON confirmations
Confirmations
TRON: 19 blocks, about a minute
Paid
49.99 USDT is in the store's wallet
invoice.paid → your server 200 OKYou sell. We watch the blockchain.
Coinetic gives each customer a dedicated address, detects the payment, waits for the required number of confirmations, and only then tells your server it's paid. Funds move from the customer's wallet to yours, never through us.
9 networks. Customers pay with what they already hold
Native coins, USDT and USDC. Tokens are credited only by allowlisted contract address, so a fake “USDT” can't change an invoice's status.
Three steps, and you're accepting crypto
No nodes, no server-side wallets, no smart contracts on your end. We handle the checkout page, exchange rates, addresses and confirmations.
import { CoineticClient } from "./cryptopay.js";
const cp = new CoineticClient({
baseUrl: "https://pay.coinetic.money",
keyId: process.env.API_KEY,
secret: process.env.API_SECRET, // server-side only
});
const invoice = await cp.createInvoice({
order_id: "ORDER-1001",
price_amount: "49.99", // a string, not a number
price_currency: "USD",
return_url: "https://shop.example/orders/ORDER-1001",
}, "order-ORDER-1001"); // Idempotency-Keyrequire 'Cryptopay.php';
$cp = new \Cryptopay\Client('https://pay.coinetic.money', getenv('API_KEY'), getenv('API_SECRET'));
$invoice = $cp->createInvoice([
'order_id' => 'ORDER-1001',
'price_amount' => '49.99',
'price_currency' => 'USD',
'return_url' => 'https://shop.example/orders/ORDER-1001',
], 'order-ORDER-1001');from cryptopay import CoineticClient
cp = CoineticClient("https://pay.coinetic.money", os.environ["API_KEY"], os.environ["API_SECRET"])
invoice = cp.create_invoice({
"order_id": "ORDER-1001",
"price_amount": "49.99",
"price_currency": "USD",
"return_url": "https://shop.example/orders/ORDER-1001",
}, "order-ORDER-1001")cp := &cryptopayclient.Client{
BaseURL: "https://pay.coinetic.money",
KeyID: os.Getenv("API_KEY"),
Secret: os.Getenv("API_SECRET"),
HTTP: &http.Client{Timeout: 10 * time.Second},
}
inv, err := cp.CreateInvoice(ctx, cryptopayclient.CreateInvoice{
OrderID: "ORDER-1001",
PriceAmount: "49.99",
PriceCurrency: "USD",
ReturnURL: "https://shop.example/orders/ORDER-1001",
}, "order-ORDER-1001")// Express: send the customer to the Coinetic checkout page
app.post("/checkout", async (req, res) => {
const order = await createOrder(req);
const invoice = await cp.createInvoice({ /* same as step 1 */ }, `order-${order.id}`);
await saveInvoiceId(order.id, invoice.id);
res.redirect(303, invoice.checkout_url);
});$invoice = $cp->createInvoice([/* same as step 1 */], 'order-' . $order['id']);
save_invoice_id($order['id'], $invoice['id']);
header('Location: ' . $invoice['checkout_url'], true, 303);
exit;# Flask
@app.post("/checkout")
def checkout():
order = create_order(request)
invoice = cp.create_invoice({...}, f"order-{order.id}")
save_invoice_id(order.id, invoice["id"])
return redirect(invoice["checkout_url"], code=303)http.Redirect(w, r, inv.CheckoutURL, http.StatusSeeOther)import { verifyWebhook } from "./cryptopay.js";
app.post("/webhooks/coinetic", express.raw({ type: "application/json" }), async (req, res) => {
let event;
try { event = verifyWebhook(process.env.WEBHOOK_SECRET, req.headers, req.body); }
catch (e) { return res.status(e.status ?? 400).end(); } // invalid signature
const inv = await cp.getInvoice(event.data.invoice_id); // status comes from the API
if (inv.status === "paid" || inv.status === "overpaid") await fulfilOnce(inv.order_id);
res.sendStatus(200);
});$headers = array_change_key_case(getallheaders(), CASE_LOWER);
try {
$event = \Cryptopay\verify_webhook(getenv('WEBHOOK_SECRET'), $headers, file_get_contents('php://input'));
} catch (\Cryptopay\CryptopayException $e) {
http_response_code($e->status); exit;
}
$inv = $cp->getInvoice($event['data']['invoice_id']); // status comes from the API
if (in_array($inv['status'], ['paid', 'overpaid'], true)) fulfil_once($inv['order_id']);
http_response_code(200);from cryptopay import verify_webhook, CryptopayError
@app.post("/webhooks/coinetic")
def webhook():
headers = {k.lower(): v for k, v in request.headers.items()}
try:
event = verify_webhook(os.environ["WEBHOOK_SECRET"], headers, request.get_data())
except CryptopayError as e:
return "", e.status
inv = cp.get_invoice(event["data"]["invoice_id"]) # status comes from the API
if inv["status"] in ("paid", "overpaid"):
fulfil_once(inv["order_id"])
return "", 200Each client is a single file with no dependencies: download one for your language. For a step-by-step walkthrough, see the quickstart.
REST and webhooks. Idempotent. Predictable.
A small API that's hard to misuse. Get sandbox keys from the dashboard in a couple of minutes.
Idempotency-Keyon every mutating requestRetrying after a timeout returns the same invoice instead of creating a second one.- HMAC-SHA256 signaturesYour secret never leaves your server; a timestamp and nonce block replay attacks.
- Amounts are stringsNo floats: decimal strings and the asset's smallest units.
- Signature test vectorsVerify a client in any language in a minute.
POST /v1/invoices HTTP/1.1
Authorization: CP-HMAC key=ak_live_…, ts=1760000000, nonce=…, sig=…
Idempotency-Key: order-ORDER-1001
Content-Type: application/json
{"order_id":"ORDER-1001","price_amount":"49.99","price_currency":"USD"}{
"id": "inv_x7k2…",
"status": "created",
"checkout_url": "https://pay.coinetic.money/pay/inv_x7k2…#t=…",
"expires_at": "2026-10-12T15:30:00Z",
"livemode": true
}Six months of payments engineering, done
Checkout page
QR code, exact amount, network warning, live status and a countdown timer. English and Russian, light and dark themes.
Funds land in your wallet
BTC, LTC and TRON: addresses derived from your xpub. EVM: a smart address that can only sweep to your wallet. Solana: your own address.
Locked exchange rate
Price in USD or EUR. The crypto amount uses the median of three exchanges and is held for 20 minutes. USDT and USDC are 1:1.
Underpayments and overpayments
Dedicated statuses, top-ups to the same address, a tolerance for wallet rounding, and late stablecoin payments credited automatically.
Guaranteed webhooks
HMAC signatures, retries for up to 24 hours, per-invoice event ordering, a delivery log and one-click resend in the dashboard.
Sandbox
The same API with no real money: “Pay exact,” “Underpay,” “Overpay” and “Half amount” buttons cover every scenario.
We can't spend your money. Technically.
Accepting payments only requires your wallets' public data. Coinetic never asks for or stores private keys or seed phrases. Every address a customer pays to is derived from your key, and we verify that three times.
- Public keys onlyxpub/zpub for BTC, LTC and TRON, an address for Solana, and a collection wallet for EVM networks.
- Delayed wallet changesPassword, second factor, email notice and a window to cancel, even if someone gets into your dashboard.
- Fees billed separatelyWe never take a cut of the payment: once a month we send you an invoice, and you pay it in crypto.
How Coinetic differs from custodial processors
| Custodial processor | Coinetic | |
|---|---|---|
| Where funds sit after payment | In the processor's account until withdrawal | In your wallet, immediately |
| Who can spend the funds | The processor | Only you |
| Withdrawals | Requests, limits, waiting | Not needed |
| Fees | Usually deducted from each payment | Billed separately once a month |
| If the processor gets hacked | Every merchant's balance is at risk | We hold no keys to your money |
“Paid” only after network confirmations
Only the blockchain watcher changes the status. Not the checkout page, not the customer, not a URL parameter. If a block is rolled back, you get invoice.reorged.
createdInvoice created; the customer is choosing a coin
awaiting_paymentAddress and exact amount issued
detectedPayment seen on the network; don't fulfill yet
confirmingIn a block, confirmations n/N in progress
paidConfirmed; safe to fulfill the order
See how many confirmations we wait for on each network in Networks and assets.
One integration, any platform
Online stores
A “Pay with crypto” button right next to cards. Customers pay from any wallet or straight from an exchange.
SaaS and digital goods
Invoice metadata ties each payment to a user and plan. Fulfillment happens automatically on webhook.
Apps and bots
iOS, Android, Telegram: open the payment link, then bring the user back via return_url.
Frequently asked questions
What is non-custodial crypto payment processing?
It's payment processing that never holds customer funds. Coinetic gives the customer an address derived from your public key, watches the blockchain and reports the payment, but the funds go straight to your wallet. We can't spend or redirect them.
How long does integration take?
The code takes an evening: creating an invoice, a redirect and a webhook handler. Before that, you sign up in the dashboard, add your receiving wallets and test in the sandbox. See every step.
Which cryptocurrencies and networks are supported?
BTC, LTC, ETH, BNB, POL, TRX, SOL, plus USDT and USDC, across 9 networks: Bitcoin, Litecoin, Ethereum, BNB Smart Chain, Polygon, Base, Arbitrum One, TRON and Solana. Full list.
Do I need to run nodes or store keys on my server?
No. Coinetic handles network monitoring, addresses and confirmations. Your server only holds an API key for signing requests and a webhook secret.
What currency do I set prices in?
USD, EUR, USDT or USDC. The customer sees the amount in the coin they choose; for BTC, ETH and other volatile assets, the rate is locked for 20 minutes based on the median of three exchanges.
When is a payment considered paid?
Only after the required number of network confirmations: for example, 2 blocks on Bitcoin and 19 blocks on TRON. The “paid” status is set by the blockchain watcher, not by the checkout page or the customer. If a block is rolled back, you'll receive an invoice.reorged webhook.
What if a customer pays too little or on the wrong network?
An underpayment gets the underpaid status, and the customer tops up to the same address. A transfer on a different EVM network or with a fake token isn't credited, but it's visible on the invoice. Learn more.
Can I refund a customer?
Yes. POST /v1/refunds or a button in the dashboard creates a refund request. Since the payment landed in your wallet, you send the transfer yourself and record the hash; on EVM networks, Coinetic finds it on-chain automatically and sends a refund.sent webhook. How refunds work.
Does Coinetic work with mobile apps and Telegram bots?
Yes. Your server creates the invoice, and the app or bot opens the payment link in the system browser. The API secret never ships inside the app. How to open checkout.
How much does it cost?
A percentage of paid invoices only, with no setup fee; fees are billed separately once a month. Pricing and calculator.
Your first test payment in 15 minutes
Sign up, grab a sandbox key and run a payment with no real money.