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.
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.
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:
| Parameter | Type | Description |
|---|---|---|
data-widget-key | string | Your widget key (required) |
data-theme | string | dark or light |
data-accent | hex | Accent color, e.g. #00ff41 |
data-locale | string | Language: en, zh-TW, ru, es, ar, pt, ja, ko, fr, de |
data-from | string | Default "from" ticker, e.g. btc |
data-to | string | Default "to" ticker, e.g. xmr |
data-ghost | boolean | Enable Ghost Mode (XMR privacy routing) |
data-provider-link | boolean | Show provider link on trade page |
Earnings
Merchants earn from every swap that runs through their widget. There are two modes:
| Mode | How it works | Payout |
|---|---|---|
| Custodial rev-share | 404.cash settles the swap custodially and credits the merchant a share of swap revenue to an internal BTC balance. | Withdraw as XMR |
| Referral fallback | A plain non-custodial swap attributed to the platform's referral; the merchant earns a referral credit. | Referral credit |
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
Create a new swap widget. Returns the widget key for embedding.
{
"widget_key": "wk_abc123def456"
}
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
}
]
}
Update a widget's theme, allowed tickers, label, accent color, locale, and other settings.
{
"ok": true
}
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 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
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
| Event | Description |
|---|---|
swap.status_changed | Fired 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.
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
- 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 Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — missing or invalid API key |
403 | Forbidden — you do not have access to this resource |
404 | Resource not found |
429 | Rate limited — too many requests |
500 | Internal server error |
503 | Service unavailable — upstream provider down |
Swap Statuses
| Status | Description |
|---|---|
waiting | Awaiting user deposit |
confirming | Deposit received, awaiting confirmations |
exchanging | Swap in progress at the exchange engine |
sending | Sending output to destination address |
finished | Swap completed successfully |
failed | Swap failed — check provider for details |
expired | No deposit received within timeout |
refunded | Deposit returned to sender |