Quick start
- Log in to the CryptoXTS panel → Domains.
- Create or open your site domain and copy
API Key+API Secret(secret is shown once — store it safely). - Call
POST /api/v1/invoicesfrom your server. - Redirect the customer to
checkout_url. - When paid, CryptoXTS POSTs a signed webhook to your
callback_url.
Authentication
Every request requires both credentials. Keys are bound to one domain — you only see invoices for that domain.
X-API-KEY: cxts_xxxxxxxxxxxxxxxx X-API-SECRET: your_64_character_secret Accept: application/json Content-Type: application/json
You may also send the key as Authorization: Bearer cxts_… plus X-API-SECRET.
Origin / referer check
If domain whitelist enforcement is enabled, browser Origin / Referer hosts must match your registered domain (or a subdomain). Server-to-server calls without those headers are fine.
Security rules (read this)
- HTTPS only for API calls and webhook URLs.
- Verify every webhook with HMAC-SHA512 before marking an invoice paid in your system.
- Rotate keys in the panel if a secret may have leaked.
- Use unique
external_invoice_idvalues so retries stay idempotent. - Do not trust checkout page traffic alone — confirm via webhook or
GET /invoices/{uuid}. - Return
2xxfrom your webhook endpoint only after you safely processed the event.
Endpoints
Health check and credential test.
{
"ok": true,
"service": "cryptoxts",
"domain": "shop.example.com",
"domain_id": 1,
"server_time": "2026-08-03T16:00:00+00:00"
}
Lightweight revenue snapshot for dashboards.
{
"revenue_month_usd": "1234.56",
"pending_count": 3,
"today": { "count": 2, "amount_usd": "50.00" },
"synced_at": "2026-08-03T16:00:00+00:00"
}
Create a payment session. Returns 201 with a hosted checkout URL. Reusing the same open external_invoice_id returns the existing invoice.
Body
| Field | Type | Notes |
|---|---|---|
amount_usd | number | Required · min 0.01 |
external_invoice_id | string | Your system’s invoice / order id |
callback_url | url | Webhook target (HTTPS) |
success_url | url | Where to send the customer after pay |
cancel_url | url | Cancel / back link |
meta | object | Optional metadata (e.g. client_email, client_name) |
curl -X POST "https://cryptoxts.com/api/v1/invoices" \
-H "X-API-KEY: cxts_..." \
-H "X-API-SECRET: ..." \
-H "Content-Type: application/json" \
-d '{
"amount_usd": 49.99,
"external_invoice_id": "ORDER-1001",
"callback_url": "https://your.site/hooks/cryptoxts",
"success_url": "https://your.site/orders/1001/thanks",
"cancel_url": "https://your.site/orders/1001",
"meta": { "client_email": "[email protected]", "client_name": "Buyer" }
}'
{
"uuid": "9b2c…",
"status": "pending",
"amount_usd": "49.99",
"expires_at": "2026-08-03T17:00:00+00:00",
"checkout_url": "https://cryptoxts.com/checkout/…"
}
List invoices for your domain.
| Query | Notes |
|---|---|
status | pending, partially_paid, paid, expired, cancelled |
from / to | Date filters (YYYY-MM-DD) |
external_invoice_id | Exact match |
client_email | Looks in meta |
per_page | 1–100 (default 25) |
Fetch one invoice. Coin, network, and deposit address appear after the customer selects a coin on checkout.
{
"uuid": "9b2c…",
"status": "paid",
"status_label": "Paid",
"amount_usd": "49.99",
"coin": "btc",
"network": "bitcoin",
"address": "bc1q…",
"crypto_amount_locked": "0.00078000",
"amount_received": "0.00078000",
"remaining": "0",
"expires_at": "…",
"paid_at": "…",
"created_at": "…",
"checkout_url": "…",
"external_invoice_id": "ORDER-1001",
"client_email": "[email protected]",
"client_name": "Buyer",
"txid": "abc…",
"txids": ["abc…"]
}
Webhooks
On successful payment CryptoXTS POSTs JSON to callback_url (or your domain’s default webhook URL).
Headers
Content-Type: application/json X-CryptoXTS-Signature: <hmac_sha512_hex> X-CryptoXTS-Signature-Alg: hmac-sha512
Signature = HMAC-SHA512(raw_request_body, api_secret). Compare using a constant-time equals check.
Payload
{
"event": "invoice.paid",
"invoice_uuid": "9b2c…",
"external_invoice_id": "ORDER-1001",
"amount_usd": "49.99",
"coin": "btc",
"network": "bitcoin",
"crypto_amount": "0.00078000",
"amount_received": "0.00078000",
"txid": "abc…",
"txids": ["abc…"],
"paid_at": "2026-08-03T16:12:00+00:00",
"status": "paid"
}
PHP verify
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_CRYPTOXTS_SIGNATURE'] ?? '';
$expect = hash_hmac('sha512', $raw, $apiSecret);
if (!hash_equals($expect, $sig)) {
http_response_code(401);
exit('bad signature');
}
// mark invoice paid in your DB
http_response_code(200);
Node.js verify
const crypto = require('crypto');
function ok(rawBody, sig, secret) {
const expect = crypto
.createHmac('sha512', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expect),
Buffer.from(sig || '')
);
}
Errors & rate limits
| Code | Meaning |
|---|---|
| 401 | Missing or invalid API key / secret |
| 403 | Domain not allowed (origin whitelist) |
| 404 | Invoice not found on this domain |
| 422 | Validation error |
| 429 | Rate limited — slow down |
Limit: about 120 requests / minute per API credential / IP. Use exponential backoff on 429.
Invoice statuses
| Status | Meaning |
|---|---|
pending | Waiting for payment |
partially_paid | Underpaid — still open |
paid | Paid (webhook fired) |
expired | Timed out unpaid |
cancelled | Cancelled |
Out of scope (by design)
These are intentionally not in the public API so plugins cannot move or expose funds:
- Withdrawals / payouts
- Hot wallet balances or private keys
- Admin / owner settings
- Other merchants’ invoices
Need those capabilities? Use the merchant panel (login + 2FA), not this API.