/ DOCS
HOME DASHBOARD

404.cash API

Swap-as-a-Service. Embed no-KYC crypto exchange on any website.

404.cash lets you embed a fully functional crypto swap widget on your website. Users swap directly — you earn from every trade. 16 exchange engines, 4,600+ coins, zero KYC.

Base URL: https://api.404.cash — All endpoints require authentication via API key.

Quick Start

Get a swap widget running on your site in 3 steps:

1. Create an account

Register at dash.404.cash to get your API key and widget key.

2. Embed the widget

<div id="swap-widget"></div>
<script src="https://swap.404.cash/widget.js"
  data-widget-key="wk_your_key_here"
  data-element="#swap-widget"
  data-theme="dark">
</script>

3. Receive webhooks

Configure a webhook URL in your dashboard to get notified when swaps complete. All webhooks are signed with HMAC-SHA256.

Authentication

All API requests require an X-API-Key header with your merchant API key.

curl -H "X-API-Key: mk_your_api_key_here" \
  https://api.404.cash/v1/merchant/profile

API keys are generated in the dashboard under API Keys. You can create multiple keys and revoke them independently.

Never expose your API key in client-side code. Use it only from your server.

Embed Widget

The swap widget is a self-contained JavaScript bundle hosted at swap.404.cash. It renders inside any container element.

Basic embed

<div id="swap-widget"></div>
<script src="https://swap.404.cash/widget.js"
  data-widget-key="wk_your_key_here"
  data-element="#swap-widget">
</script>

Iframe embed

<iframe
  src="https://swap.404.cash/?key=wk_your_key_here&theme=dark"
  width="420" height="600"
  style="border: none; border-radius: 16px;">
</iframe>

Widget Configuration

Configure your widget via data attributes or query parameters:

ParameterTypeDescription
data-widget-keystringYour widget key (required)
data-themestringdark or light
data-accenthexAccent color, e.g. #00ff41
data-localestringLanguage: en, zh-TW, ru, es, ar, pt, ja, ko, fr, de
data-fromstringDefault "from" ticker, e.g. btc
data-tostringDefault "to" ticker, e.g. xmr
data-ghostbooleanEnable Ghost Mode (XMR privacy routing)
data-provider-linkbooleanShow provider link on trade page

Earnings

Merchants earn from every swap that runs through their widget. There are two modes:

ModeHow it worksPayout
Custodial rev-share404.cash settles the swap custodially and credits the merchant a share of swap revenue to an internal BTC balance.Withdraw as XMR
Referral fallbackA plain non-custodial swap attributed to the platform's referral; the merchant earns a referral credit.Referral credit
Internal BTC balances accrue automatically per settled swap and can be withdrawn as XMR from the dashboard. The widget and dashboard are free — there is no platform fee. On custodial swaps, 404.cash credits a share of the swap revenue (net of settlement cost) to your balance.

Merchant Profile

GET /v1/merchant/profile

Get your merchant profile, internal BTC balance, and referral info.

{
  "id": "mc_abc123",
  "name": "My Project",
  "email": "me@example.com",
  "btc_balance": 0.00231500,
  "referral_code": "ref_xyz",
  "webhook_url": "https://example.com/webhook",
  "created_at": 1711900000
}

Widgets

POST /v1/widgets

Create a new swap widget. Returns the widget key for embedding.

{
  "widget_key": "wk_abc123def456"
}
GET /v1/widgets

List all your widgets with their configuration.

{
  "widgets": [
    {
      "id": "wk_abc123",
      "label": "Main Widget",
      "theme": "dark",
      "from_tickers": ["btc", "eth"],
      "to_tickers": ["xmr"],
      "created_at": 1711900000
    }
  ]
}
PUT /v1/widgets/:id

Update a widget's theme, allowed tickers, label, accent color, locale, and other settings.

{
  "ok": true
}

Swaps

GET /v1/swaps

List swaps for your merchant account. Supports limit, offset, status, and widget_id query params.

{
  "swaps": [
    {
      "id": "sw_abc123",
      "from_ticker": "btc",
      "to_ticker": "xmr",
      "amount_from": 0.01,
      "status": "finished",
      "engine": "changenow",
      "widget_id": "wk_abc123",
      "created_at": 1711900000
    }
  ],
  "total": 1
}
GET /v1/swaps/stats/summary

Get aggregated swap statistics: totals, last 24h, and breakdown by status.

{
  "total": { "swaps": 150, "volume_usd": 12500.00 },
  "last_24h": { "swaps": 5, "volume_usd": 420.00 },
  "by_status": [
    { "status": "finished", "count": 120 },
    { "status": "pending", "count": 15 },
    { "status": "failed", "count": 10 },
    { "status": "expired", "count": 5 }
  ]
}

Webhook Test

POST /v1/merchant/webhook-test

Send a test webhook payload to your configured URL. Useful for verifying your endpoint before going live.

{
  "ok": true
}

Webhook Events

When a swap changes status, 404.cash sends a POST request to your configured webhook URL with the following payload:

{
  "event": "swap.status_changed",
  "swap": {
    "id": "sw_abc123",
    "status": "finished",
    "from_ticker": "btc",
    "to_ticker": "xmr",
    "amount_from": 0.01,
    "widget_id": "wk_abc123",
    "created_at": 1711900000
  }
}

Event types

EventDescription
swap.status_changedFired when a swap transitions to a new status (pending, confirming, exchanging, sending, finished, failed, expired, refunded)

Webhook Verification

All webhooks include an X-Webhook-Signature header containing an HMAC-SHA256 signature of the raw request body, signed with your webhook secret.

Webhook verification is mandatory. Requests without a valid signature must be rejected.
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express example
app.post('/webhook', (req, res) => {
  const sig = req.headers['x-webhook-signature'];
  const raw = JSON.stringify(req.body);

  if (!verifyWebhook(raw, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const { event, swap } = req.body;
  console.log(`Swap ${swap.id} → ${swap.status}`);
  res.status(200).send('OK');
});

Features & Rate Limits

Everything is free. There are no plans, subscriptions, prepaid quota, or platform fee — every feature is available to all merchants.

Everything, Free

$0
No platform fee · earn on every swap
  • Unlimited widgets
  • 4,600+ coins
  • Ghost (private) mode
  • Custom theme + CSS
  • Hide branding
  • Custom domain
  • Webhooks
  • Custodial rev-share & referral earnings

The API is rate limited to 300 requests/min per merchant. If you need a higher limit, reach out from the dashboard.

Error Codes

All errors return a JSON object with an error field:

{
  "error": "Invalid API key"
}
HTTP StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — missing or invalid API key
403Forbidden — you do not have access to this resource
404Resource not found
429Rate limited — too many requests
500Internal server error
503Service unavailable — upstream provider down

Swap Statuses

StatusDescription
waitingAwaiting user deposit
confirmingDeposit received, awaiting confirmations
exchangingSwap in progress at the exchange engine
sendingSending output to destination address
finishedSwap completed successfully
failedSwap failed — check provider for details
expiredNo deposit received within timeout
refundedDeposit returned to sender

404.cash — Swap as a Service — Dashboard