Developer Reference v1

API Reference

A lightweight REST API for creating and managing cryptocurrency payment orders. Authenticate with an API key, create an order, and poll for confirmation.

Base URL https://destroy.wtf
Get an API Key
POST /api/order/create
// Create a $25 BTC payment order
POST /api/order/create
Content-Type: application/json

{
  "api_key":     "your-api-key",
  "amount_usd":  25.00,
  "crypto_type": "BTC"
}

// 200 OK — returns crypto_address + crypto_amount
Protocol
HTTPS
JSON request & response
Invoice Range
$0.50$2,000
USD per order
Order Expiry
2 hours
From order creation
Networks
10 supported
BTC · ETH · LTC · SOL · BCH · BNB · DOGE · TRX · XRP · XMR
01

Overview

The DESTROY.WTF API is a RESTful JSON service for creating cryptocurrency payment orders, polling their status, and managing the order lifecycle. All endpoints accept and return JSON over HTTPS.

QS Quick start

Create a $25 BTC payment order with a single request:

cURL
curl -X POST "https://destroy.wtf/api/order/create" \
  -H "Content-Type: application/json" \
  -d '{"api_key":"YOUR_API_KEY","amount_usd":25.00,"crypto_type":"BTC"}'
02

Authentication

Merchant requests are authenticated with an API key. Generate one from the Dashboard after creating an account. Send the key in the JSON body for POST requests, or as a query parameter on endpoints that support GET. Query strings are convenient for server-side integrations but may appear in proxy logs and browser history, so prefer POST when possible.

Keep your API key secret — never expose it in client-side code or public repositories. Before creating orders, configure payout addresses for each cryptocurrency in the Dashboard; the gateway will not process payments without them.
API key in request body
// POST /api/order/create
{
  "api_key":     "550e8400-e29b-41d4-a716-446655440000",
  "amount_usd":  25.00,
  "crypto_type": "BTC"
}
03

Payment Flow

End-to-end flow for accepting a cryptocurrency payment.

01

Create an order

POST to /api/order/create with the USD amount, crypto type, and your API key. You receive a payment address and a hosted payment-page URL.

02

Direct the customer

Redirect to the payment_gateway_url, or display the address and amount in your own checkout UI.

03

Poll for status

Call /api/order/status periodically. Status progresses from PENDINGCONFIRMINGCOMPLETED.

04

Receive payout

Once confirmed, funds are forwarded to your configured payout address. The merchant_txid field returns the payout transaction ID.

There is no webhook system — poll /api/order/status to detect completion. The return_url is a customer-facing link shown on the hosted payment page after they pay.
04

Endpoints

Five endpoints cover the full payment lifecycle: create, look up, update, cancel, and discover available networks.

Endpoint

Create Order

POST /api/order/create API key

Creates a new cryptocurrency payment order. Returns a unique crypto_address to receive payment, the expected crypto_amount (locked at the current price), and a hosted payment-page URL you can redirect customers to.

api_key string Required
Your API key (UUID v4).
amount_usd float Required
Invoice amount in USD. Min 0.50, max 2000.
crypto_type string Optional
Cryptocurrency to accept. Defaults to LTC.
return_url string Optional
URL displayed on the payment page for the customer to return to your site after paying.
order_idstring
Unique order identifier (UUID v4).
crypto_amountstring
Amount the customer must send, formatted to 10 decimal places.
crypto_pricefloat
USD price of the crypto at order creation.
crypto_addressstring
Blockchain address to send payment to.
payment_gateway_urlstring
Hosted payment-page URL — redirect customers here.
expire_timestring
ISO-8601 UTC timestamp, 2 hours after creation.
destination_tagint
XRP only. Customer must include this tag in their payment.
POST /api/order/create
Content-Type: application/json

{
  "api_key":     "your-api-key",
  "amount_usd":  25.00,
  "crypto_type": "BTC",
  "return_url":  "https://shop.example.com/done"
}
{
  "success":             true,
  "order_id":            "550e8400-e29b-41d4-a716-446655440000",
  "crypto_type":         "BTC",
  "amount_usd":          25.00,
  "crypto_amount":       "0.0002561700",
  "crypto_price":        97591.23,
  "crypto_address":      "bc1q...example",
  "payment_gateway_url": "https://destroy.wtf/pay/550e8400-...",
  "created_at":          "2026-02-17T12:00:00+00:00",
  "expire_time":         "2026-02-17T14:00:00+00:00",
  "return_url":          "https://shop.example.com/done"
}
Endpoint

Order Status

GET /api/order/status Public / API key

Retrieves the current status and details of an order. Public lookups only need order_id. Merchants can also pass api_key to verify ownership. Also accepts POST with a JSON body.

order_id string Required
The order UUID to look up.
api_key string Optional
If provided, the API key must own the order.
paidbool
Whether the order has been fully paid.
tx_idstring
Incoming transaction IDs (comma-separated), or "N/A".
statusstring
Current order status — see Order Statuses.
withdrawnbool
Whether the payout to the merchant has been sent.
merchant_txidstring | null
Payout transaction ID once funds are sent.
paid_usdfloat
Actual USD value received based on crypto received.
GET /api/order/status?order_id=ORDER_ID

// Or POST with JSON body:
POST /api/order/status
Content-Type: application/json

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "api_key":  "your-api-key"
}
{
  "success":        true,
  "order_id":       "550e8400-...",
  "crypto_type":    "BTC",
  "amount_usd":     25.00,
  "crypto_amount":  "0.0002561700",
  "crypto_price":   97591.23,
  "crypto_address": "bc1q...example",
  "paid":           false,
  "tx_id":          "N/A",
  "status":         "PENDING",
  "withdrawn":      false,
  "merchant_txid":  null,
  "paid_usd":       0.00,
  "created_at":     "2026-02-17T12:00:00+00:00",
  "expire_time":    "2026-02-17T14:00:00+00:00"
}
Endpoint

Update Order

POST /api/order/update API key

Switches the cryptocurrency type for an existing unpaid order. A new payment address is issued and the crypto amount is re-priced at the current rate. The USD amount remains unchanged.

order_id string Required
The order UUID to update.
crypto_type string Required
New cryptocurrency to switch the order to.
api_key string Optional
Your API key. If provided, must match the order's owning key.
Orders that have received any payment (paid_usd > 0) cannot be updated. The previous payment address is replaced — funds sent to the old address after the switch will still be detected, but the order now expects the new crypto type.
POST /api/order/update
Content-Type: application/json

{
  "order_id":    "550e8400-...",
  "crypto_type": "ETH",
  "api_key":     "your-api-key"
}
{
  "success":        true,
  "message":        "Order updated successfully",
  "order_id":       "550e8400-...",
  "crypto_type":    "ETH",
  "crypto_amount":  "0.0076180000",
  "crypto_price":   3282.45,
  "crypto_address": "0xabc...example",
  // ... full order fields
}
Endpoint

Cancel Order

POST /api/order/cancel API key

Cancels a pending order. Only works if no payment has been received. Supports both POST JSON and GET query parameters.

order_id string Required
The order UUID to cancel.
api_key string Required
Your API key — must own the order.
POST /api/order/cancel
Content-Type: application/json

{
  "api_key":  "your-api-key",
  "order_id": "550e8400-..."
}
{
  "success":  true,
  "message":  "Order cancelled successfully",
  "order_id": "550e8400-...",
  "status":   "CANCELED",
  // ... full order fields
}
Endpoint

List Cryptocurrencies

GET /api/crypto Public

Returns the supported cryptocurrencies and their current USD prices, plus the percent change over three rolling windows (5m, 6h, 24h). When the server has been running for less than a window, that window's window_seconds reflects the actual history available; if no history exists yet, the window is omitted. Pass an api_key to filter to only the cryptos configured for that key.

api_key string Optional
If provided, filters to only cryptos configured for this key.
GET /api/crypto

// Or filter by API key:
GET /api/crypto?api_key=YOUR_API_KEY
{
  "success":   true,
  "supported": {
    "BTC":  97591.23,
    "ETH":  3282.45,
    "LTC":  128.45,
    "SOL":  195.67,
    // ... all configured cryptos
  },
  "changes": {
    "BTC": {
      "5m":  { "pct": 0.12, "window_seconds": 300 },
      "6h":  { "pct": 0.85, "window_seconds": 21600 },
      "24h": { "pct": 1.23, "window_seconds": 86400 }
    },
    // ... pct is signed (positive = up); window_seconds is the actual
    // history age used, which may be smaller than the window target right
    // after a restart
  }
}
05

Order Statuses

An order progresses through these statuses during its lifecycle. A payment is considered sufficient when it reaches at least 94% of the expected crypto amount.

PENDING
Order created, awaiting payment from the customer.
PARTIAL PAYMENT
Payment received but below the 94% threshold of the expected amount.
CONFIRMING
Payment at or above the threshold detected, awaiting blockchain confirmation.
COMPLETED
Payment fully confirmed. Payout to merchant will be processed automatically.
CANCELED
Order was cancelled via API or admin action. Only possible before payment.
Once an order reaches COMPLETED, the gateway automatically processes payouts. Check withdrawn and merchant_txid to confirm the payout has been sent.
06

Error Handling

All error responses follow a consistent JSON shape. The HTTP status code is 200 for business-logic errors (invalid parameters, not found) and 429 for rate-limited requests.

Error response shape
{
  "success": false,
  "error":   "Human-readable error message"
}
"No api_key"
The api_key parameter is missing or empty.
"Invalid api_key"
API key format is invalid or the key does not exist.
"Invalid order ID"
The order_id is not a valid UUID v4.
"Order not found"
No order exists with the given ID.
"Unsupported cryptocurrency"
The requested crypto_type is not recognized.
"Unauthorized: api_key does not own this order"
The API key provided does not match the order's owning key.
"Amount must be between 0.5 and 2000 USD"
The amount_usd is outside the allowed range.
"Crypto price not available"
Price data has not yet been fetched for this crypto.
"Rate limit exceeded"
Too many requests — HTTP 429. See Rate Limits.
07

Rate Limits

The API enforces rate limits per IP address to protect against abuse. Authenticated users with a valid session receive a higher limit.

Default limit
5 / sec
Unauthenticated requests
Authenticated limit
15 / sec
Logged-in users with a valid session
Block duration
30 sec
Wait before retrying
Status code
429
Too Many Requests
If you sit behind Cloudflare, the real client IP is read from the CF-Connecting-IP header. Implement exponential backoff in your polling logic to stay within limits.
08

Code Examples

End-to-end examples covering order creation and status polling.

import requests, time

API_KEY  = "your-api-key"
BASE_URL = "https://destroy.wtf"

# 1. Create an order
resp = requests.post(f"{BASE_URL}/api/order/create", json={
    "api_key":     API_KEY,
    "amount_usd":  25.00,
    "crypto_type": "BTC",
    "return_url":  "https://your.shop/success",
}).json()

order_id = resp["order_id"]
print(f"Pay: {resp['payment_gateway_url']}")

# 2. Poll until COMPLETED
while True:
    status = requests.get(
        f"{BASE_URL}/api/order/status",
        params={"order_id": order_id, "api_key": API_KEY},
    ).json()

    print(f"Status: {status['status']}")

    if status["status"] == "COMPLETED":
        print(f"Paid! TX: {status['tx_id']}")
        break

    if status["status"] == "CANCELED":
        print("Order was cancelled.")
        break

    time.sleep(15)
# Create an order
curl -X POST "https://destroy.wtf/api/order/create" \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "your-api-key",
    "amount_usd": 25.00,
    "crypto_type": "BTC"
  }'

# Check order status
curl -X POST "https://destroy.wtf/api/order/status" \
  -H "Content-Type: application/json" \
  -d '{"order_id":"ORDER_ID","api_key":"your-api-key"}'

# Cancel an order
curl -X POST "https://destroy.wtf/api/order/cancel" \
  -H "Content-Type: application/json" \
  -d '{"api_key":"your-api-key","order_id":"ORDER_ID"}'
const BASE_URL = "https://destroy.wtf";
const API_KEY  = "your-api-key";

// 1. Create an order
const res = await fetch(`${BASE_URL}/api/order/create`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    api_key:     API_KEY,
    amount_usd:  25.00,
    crypto_type: "BTC",
    return_url:  "https://your.shop/success",
  }),
});

const order = await res.json();
console.log("Payment URL:", order.payment_gateway_url);

// 2. Poll for status
const check = await fetch(`${BASE_URL}/api/order/status`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ order_id: order.order_id, api_key: API_KEY }),
});

const status = await check.json();
console.log("Status:", status.status);
09

Webhooks

The gateway can push lifecycle events to an HTTPS endpoint you control. Manage endpoints from the Webhooks tab in your Dashboard. Each event is delivered as a JSON POST signed with a per-endpoint HMAC secret.

order.created
A new order was created.
order.status_changed
Status transitioned — payload includes old_status and status.
order.updated
Order details refreshed.
order.payout_review
Payout flagged for manual review.
order.payout_review_cleared
An admin cleared the review flag.
order.payout_indeterminateAdmin-only
XMR payout returned an indeterminate RPC result.
order.payout_stuckAdmin-only
XMR payout has been indeterminate for over an hour.
RF Request format
Webhook delivery
POST https://your-endpoint
Content-Type: application/json
X-Gateway-Event: order.status_changed
X-Gateway-Event-Id: 9b3...c1
X-Gateway-Timestamp: 1716120000
X-Gateway-Signature: sha256=<hex>

{
  "id":      "9b3...c1",
  "type":    "order.status_changed",
  "created": "2026-05-19T13:00:00+00:00",
  "data": {
    "order_id":    "550e8400-...",
    "status":      "COMPLETED",
    "old_status":  "PENDING",
    "amount_usd":  19.99,
    "paid_usd":    19.99,
    "crypto_type": "BTC"
  }
}
SV Signature verification
import hmac, hashlib

signature = request.headers['X-Gateway-Signature'].split('=', 1)[1]
timestamp = request.headers['X-Gateway-Timestamp']

expected = hmac.new(
    bytes.fromhex(WEBHOOK_SECRET),
    f"{timestamp}.{request.body.decode()}".encode(),
    hashlib.sha256,
).hexdigest()

assert hmac.compare_digest(signature, expected)
const crypto = require('crypto');

const sig = req.header('X-Gateway-Signature').split('=')[1];
const ts  = req.header('X-Gateway-Timestamp');

const expected = crypto
  .createHmac('sha256', Buffer.from(process.env.WEBHOOK_SECRET, 'hex'))
  .update(ts + '.' + rawBody)
  .digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
  throw new Error('bad signature');
}
RP Retry policy

Non-2xx responses (or timeouts) are retried up to 8 times with exponential backoff starting at 30 seconds and doubling each attempt (cap ~64 minutes). After 8 failed attempts the delivery is marked exhausted. After 20 consecutive failures across any deliveries the endpoint auto-disables — re-enable it from the Dashboard once your receiver is fixed.

Best practices. Respond within 5 seconds — defer slow work to a background queue. Treat X-Gateway-Event-Id as the idempotency key and store seen IDs so retries are no-ops. Always verify the signature before reading the body.