API Reference
Accept cryptocurrency payments that settle directly into your own wallet. Non-custodial — the gateway never holds funds.
Base URL https://cryptoipg.com JSON Bearer auth
Authentication
Send your secret API key as a bearer token on every protected request:
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Create keys in your dashboard under your website → API keys. The secret is shown once — keep it server-side only. To create live invoices your domain must be verified and you must have a wallet (plain address) for the coin you charge in.
Quickstart
curl -X POST https://cryptoipg.com/api/v1/invoices \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 49.99,
"currency": "EUR",
"asset": "BTC",
"network": "bitcoin",
"order_id": "ORDER-1024",
"redirect_url": "https://yourshop.com/thank-you"
}'
Response 201 Created:
{
"invoice": {
"id": "b1e7c0f2-5a3d-4e9b-9f21-8c7d6e5a4b30",
"status": "awaiting_payment",
"asset": "BTC",
"network": "bitcoin",
"amount": "0.00098421",
"amount_paid": "0",
"address": "bc1qexampleaddressxxxxxxxxxxxxxxxxxxxxx",
"price_amount": "49.99",
"price_currency": "EUR",
"confirmations": 0,
"required_confirmations": 2,
"expires_at": "2026-07-06 12:30:00",
"order_id": "ORDER-1024",
"checkout_url": "https://cryptoipg.com/pay/b1e7c0f2-..."
}
}
Then redirect the customer to checkout_url (hosted page with QR, coin switching, live status), or show address + amount yourself and poll for status.
Create an invoice
POST/api/v1/invoices auth
| Field | Type | Req | Description |
|---|---|---|---|
amount | number | yes | Price to charge, in currency. |
asset | string | yes | Coin code (see Assets). |
network | string | yes | Chain the coin is on. |
currency | string | no | ISO fiat (EUR, USD…). Defaults to your website's currency. |
order_id | string | no | Your reference. Returned on the invoice and webhooks — use it to match your order. |
description | string | no | Shown on the checkout. |
buyer_email | string | no | Customer email, for your records. |
redirect_url | string | no | Where the customer returns after paying. |
The crypto amount is priced at a live rate at creation and frozen, with a tiny unique offset so payments are matchable — the customer must send the exact amount.
Responses
201 | Created — { "invoice": { … } } |
401 | { "error": "missing_api_key" | "invalid_api_key" } |
422 | { "error": "invalid_request", "message": "…" } — e.g. no wallet for that network, unknown asset, amount ≤ 0. |
Retrieve an invoice
GET/api/v1/invoices/{id} auth
| Field | Description |
|---|---|
id | Invoice id (UUID); also in the checkout URL. |
status | Lifecycle status (see below). |
asset / network | Coin and chain. |
amount | Crypto amount to pay (exact string). |
amount_paid | Crypto received so far. |
address | Deposit address (your wallet). |
price_amount / price_currency | The fiat price you set. |
confirmations / required_confirmations | Confirmation progress. |
expires_at | When payment stops being accepted (UTC). |
order_id | Your reference. |
checkout_url | Hosted checkout page. |
Public status no key
GET/pay/{id}/status
Returns the same invoice fields without your secret key — safe to call from a browser, app, or bot. Ideal for polling a checkout you rendered yourself.
curl https://cryptoipg.com/pay/b1e7c0f2-.../status
Webhooks
The reliable way to learn a payment succeeded — don't depend on the customer returning. Add your HTTPS endpoint in your website → Webhooks and copy the signing secret (whsec_…). On payment we send:
POST https://yourserver.com/your-webhook
Content-Type: application/json
X-CryptoIPG-Event: invoice.paid
X-CryptoIPG-Delivery: <delivery-uuid>
X-CryptoIPG-Signature: sha256=<hex-hmac>
{
"id": "<delivery-uuid>",
"event": "invoice.paid",
"created_at": "2026-07-06T12:15:04+00:00",
"data": {
"id": "b1e7c0f2-...",
"order_id": "ORDER-1024",
"asset": "BTC",
"network": "bitcoin",
"amount": "0.00098421",
"address": "bc1q...",
"price_amount": "49.99",
"price_currency": "EUR"
}
}
Treat the event field as authoritative; match your order via data.order_id.
Verify the signature
HMAC-SHA256 the raw body with your secret and compare (constant-time):
$payload = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $payload, $WEBHOOK_SECRET);
if (!hash_equals($expected, $_SERVER['HTTP_X_CRYPTOIPG_SIGNATURE'] ?? '')) {
http_response_code(401); exit;
}
Respond 2xx to acknowledge. Failures retry: 30s → 2m → 10m → 30m → 2h → 6h (6 attempts, then exhausted). Handle retries idempotently.
Assets & networks
| Asset | Network(s) |
|---|---|
BTC | bitcoin |
LTC | litecoin |
DOGE | dogecoin |
ETH | ethereum |
TRX | tron |
SOL | solana |
DOT | polkadot |
USDT / USDC | ethereum, tron, solana |
Invoice statuses
| Status | Meaning |
|---|---|
awaiting_payment | Waiting for funds. |
detected | Payment seen (0 conf). |
confirming | Gathering confirmations. |
underpaid | Received less than required. |
paid / overpaid / completed | Settled — fulfill the order. |
expired | Window elapsed, no payment. |
failed / refunded | Terminal states. |
Examples
PHP
$ch = curl_init('https://cryptoipg.com/api/v1/invoices');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $SECRET,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => 49.99, 'currency' => 'EUR',
'asset' => 'BTC', 'network' => 'bitcoin',
'order_id' => 'ORDER-1024',
]),
]);
$invoice = json_decode(curl_exec($ch), true)['invoice'];
header('Location: ' . $invoice['checkout_url']);
Node.js
const res = await fetch("https://cryptoipg.com/api/v1/invoices", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CRYPTOIPG_SECRET}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: 49.99, currency: "EUR",
asset: "BTC", network: "bitcoin",
order_id: "ORDER-1024",
}),
});
const { invoice } = await res.json();
console.log(invoice.checkout_url, invoice.address, invoice.amount);
Python
import requests
r = requests.post(
"https://cryptoipg.com/api/v1/invoices",
headers={"Authorization": f"Bearer {SECRET}"},
json={"amount": 49.99, "currency": "EUR",
"asset": "BTC", "network": "bitcoin", "order_id": "ORDER-1024"},
)
invoice = r.json()["invoice"]
print(invoice["checkout_url"], invoice["amount"], invoice["address"])
Bot polling
# poll the public status endpoint (no secret key needed)
import requests, time
inv_id = invoice["id"]
while True:
s = requests.get(f"https://cryptoipg.com/pay/{inv_id}/status").json()
if s["status"] in ("paid", "overpaid", "completed"):
deliver_product(); break
if s["status"] in ("expired", "failed"):
break
time.sleep(15)
Notes & limits
Test vs live: use a sk_test_… key while integrating. Exact amounts: payments match by unique amount — send exactly amount. Idempotency: each create makes a new invoice; reuse the returned id rather than duplicating per order_id. Fees: network fees are paid by the customer on top. Timestamps are UTC.
Non-custodial software. You are responsible for tax, sanctions, and licensing (incl. EU MiCA) in your jurisdiction. Not legal or financial advice.