Read-only JSON over GET, any origin (CORS *). Base URL https://night.poptraderbot.xyz. For a drop-in swap ticket see the embed widget.
| GET /api/quote | Same-chain quotes from every venue, ranked by what lands in the wallet, with executable calldata. |
| GET /api/bridge | Cross-chain routes (bridge + swap in one transaction) from LI.FI, Relay, deBridge and Across, ranked net of fees and gas. |
| GET /api/bridge/status | Delivery status of an executed cross-chain route. |
| GET /api/markets/stocks | Every tokenized company across issuers and chains: the Hyperliquid mark, each wrapper's per-share price and premium, the cheapest tradable wrapper. |
| GET /api/markets/tokens | Traded tokens on one chain or across every main chain, each row tagged with its chain. |
| GET /api/terminal | New pairs, trending and most traded tokens on a chain or across all of them, with safety flags on Solana. |
| GET /api/sol-orders | Solana limit and DCA orders through Jupiter's Trigger and Recurring programs. GET lists open orders; POST returns an unsigned transaction. |
| GET /api/tokens | Every token the ticket can pick on a chain, with prices. |
| GET /api/token | Metadata for an ERC-20 that is on no list (read on-chain, priced from DexScreener). |
| GET /api/marks | Hyperliquid reference marks for symbols (stocks via the xyz dex). |
| GET /api/health | Per source and chain: breaker state, recent failures and latency. Use it to explain a missing venue. |
Same-chain quotes from every venue, ranked by what lands in the wallet, with executable calldata.
curl "https://night.poptraderbot.xyz/api/quote?chainId=4663&tokenIn=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&tokenOut=0x322F0929c4625eD5bAd873c95208D54E1c003b2d&amountIn=100000000&taker=0xYourWallet&slippageBps=50" \ -H "x-client-id: my-app"
const r = await fetch("https://night.poptraderbot.xyz/api/quote?chainId=4663&tokenIn=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&tokenOut=0x322F0929c4625eD5bAd873c95208D54E1c003b2d&amountIn=100000000&taker=0xYourWallet&slippageBps=50", { headers: {"x-client-id":"my-app"} });
const data = await r.json();{
"request": { "chainId": 4663, "tokenIn": "0x…", "tokenOut": "0x…", "amountIn": "100000000", "slippageBps": 50 },
"best": { …same shape as quotes[0] },
"quotes": [
{
"source": "kyber", "label": "KyberSwap",
"amountOut": "233120000000000000", // gross, raw units of tokenOut
"amountOutMin": "231954400000000000",
"feeBps": 5, // router fee + partnerBps, 0 when direct
"netAmountOut": "233003440000000000", // what the wallet receives: display this
"netAmountOutMin": "231838422800000000",
"vsBest": 0, // fraction below the best quote (0 = best)
"gasUsd": 0.004, "priceImpact": 0.0008, "hops": [{ "venue": "metric", "tokenIn": "0x…", "tokenOut": "0x…" }],
"tx": { "to": "0x…", "data": "0x…", "value": "0", "spender": "0x…" }, // call the venue directly
"routerTx": { "to": "0x…", "data": "0x…", "value": "0", "spender": "0x…" } // call NightRouter (only with taker)
}
],
"split": null, // or { legs: [...], netAmountOut, routerTx?, executable }
"errors": [{ "source": "odos", "error": "timeout" }],
"via": "router", "router": "0x2cB1…C160", "at": 1760000000000
}To execute: approve `spender` for tokenIn (ERC-20 only), then send `{ to, data, value }`. Prefer `routerTx` when present: one approval covers every venue and positive slippage is returned to the taker.
Solana (chainId 1151111081099710): sources are `jupiter` and `henar` (Henar's native Raydium/Orca/Meteora router). With a taker each quote carries `solanaTx: { tx, lastValidBlockHeight }`, an unsigned v0 transaction in base64: deserialize, sign with the taker's wallet and send. Example: `chainId=1151111081099710&tokenIn=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&tokenOut=XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB&amountIn=100000000` buys $100 of TSLAx.
Quotes are cached for 4 s server-side and worth refreshing every 10–15 s; firm RFQ quotes carry `guaranteed: true` and `expiresAt`.
Cross-chain routes (bridge + swap in one transaction) from LI.FI, Relay, deBridge and Across, ranked net of fees and gas.
curl "https://night.poptraderbot.xyz/api/bridge?fromChain=8453&fromToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&amount=100000000&toChain=4663&toToken=0x322F0929c4625eD5bAd873c95208D54E1c003b2d&taker=0xYourWallet"
const r = await fetch("https://night.poptraderbot.xyz/api/bridge?fromChain=8453&fromToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&amount=100000000&toChain=4663&toToken=0x322F0929c4625eD5bAd873c95208D54E1c003b2d&taker=0xYourWallet");
const data = await r.json();{
…the best route's fields at the top level…
"provider": "relay", "providerLabel": "Relay", "ref": "0x…", // keep ref for status polling
"fromChain": 8453, "fromToken": "0x…", "fromAmount": "100000000",
"toChain": 4663, "toToken": "0x…", "toAmount": "232000000000000000", "toAmountMin": "230840000000000000",
"durationSec": 20, "totalFeeUsd": 0.31, "gasUsd": 0.02, "netUsd": 99.6,
"steps": [{ "tool": "relay", "fromToken": "USDC", "toToken": "TSLA" }],
"tx": { "to": "0x…", "data": "0x…", "value": "0", "chainId": 8453 },
"approval": { "spender": "0x…", "token": "0x…", "amount": "100000000" } | null,
"tags": ["best", "fastest"],
"routes": [ …every provider's route, ranked… ],
"errors": [{ "provider": "across", "error": "no route" }],
"providers": ["lifi", "relay", "debridge", "across", "mayan", "cctp"]
}404 with `routes: []` when no provider can serve the pair. Execute like a swap: `approval` first if present, then `tx` on `fromChain`.
Leaving Solana: routes carry `solanaTx: { tx, lastValidBlockHeight? }` instead of an EVM `tx`; sign and send it with the Solana wallet, then poll status with the signature as `txHash`.
Delivery status of an executed cross-chain route.
curl "https://night.poptraderbot.xyz/api/bridge/status?provider=relay&txHash=0x…&fromChain=8453&toChain=4663&ref=0x…"
const r = await fetch("https://night.poptraderbot.xyz/api/bridge/status?provider=relay&txHash=0x…&fromChain=8453&toChain=4663&ref=0x…");
const data = await r.json();{
"status": "PENDING" | "DONE" | "FAILED" | "NOT_FOUND" | "INVALID",
"substatusMessage": "Waiting for destination fill",
"sending": { "txHash": "0x…", "chainId": 8453 },
"receiving": { "txHash": "0x…", "chainId": 4663, "amount": "232140000000000000" } // once DONE
}Poll every 5 s until `DONE` or `FAILED`. `NOT_FOUND` right after sending is normal; keep polling for a minute before treating it as an error.
Every tokenized company across issuers and chains: the Hyperliquid mark, each wrapper's per-share price and premium, the cheapest tradable wrapper.
curl "https://night.poptraderbot.xyz/api/markets/stocks"
const r = await fetch("https://night.poptraderbot.xyz/api/markets/stocks");
const data = await r.json();{
"session": "open" | "closed", "opensAt": 1760000000000, "closesAt": null,
"counts": { "companies": 1386, "tradable": 83, "withMark": 56, "wrappers": 510 },
"medianPremiumBps": 18,
"rows": [{
"ticker": "TSLA", "name": "Tesla", "sector": "Industrials", "mark": 352.78, "markChange24h": -0.06,
"issuers": ["robinhood", "coinbase", "xstocks", "ondo", "backpack"], "chains": [4663, 8453, "solana"],
"best": { "chain": 1151111081099710, "issuer": "xstocks", "address": "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB", "sharePrice": 352.72, "premiumBps": -2 },
"wrappers": [{ "issuer": "robinhood", "chain": 4663, "symbol": "TSLA", "sharePrice": 352.9, "multiplier": 1.0012, "premiumBps": 3, "liquidityUsd": 2400000, "tradable": true }],
"depth": { "buy": { "premiumBps": 6, "source": "KyberSwap" }, "sell": { … } } // $1k fills on Robinhood, top 12
}]
}Prices are spot from each wrapper's deepest pool, divided by the issuer's multiplier. A wrapper more than 20% off the mark is never `best`. Cached 30 s.
Traded tokens on one chain or across every main chain, each row tagged with its chain.
curl "https://night.poptraderbot.xyz/api/markets/tokens?chain=all"
const r = await fetch("https://night.poptraderbot.xyz/api/markets/tokens?chain=all");
const data = await r.json();{
"chains": [{ "chainId": 4663, "ready": true, "count": 120 }, { "chainId": 1, "ready": false, "count": 0 }],
"rows": [{ "chainId": 1151111081099710, "address": "…", "symbol": "PUMP", "category": "crypto", "price": 0.0045, "change24h": 0.018, "volume24h": 63800000, "liquidityUsd": 36900000, "marketCap": 2100000000, "premium": null, "venue": "jupiter", "url": "…" }]
}A chain still loading comes back with `ready: false` and joins on a later poll (poll every 5 s until all are ready).
New pairs, trending and most traded tokens on a chain or across all of them, with safety flags on Solana.
curl "https://night.poptraderbot.xyz/api/terminal?chainId=1151111081099710"
const r = await fetch("https://night.poptraderbot.xyz/api/terminal?chainId=1151111081099710");
const data = await r.json();{
"chainId": 1151111081099710, "source": "Jupiter" | "GeckoTerminal" | "DexScreener",
"fresh": [{ "address": "…", "symbol": "ABC", "price": 0.00002, "mcap": 8100, "liquidity": 5300, "change1h": 0.11, "createdAt": 1760000000000,
"txns1h": { "buys": 15, "sells": 3 }, "organicScore": 12,
"audit": { "mintDisabled": true, "freezeDisabled": true, "topHoldersPct": 25 } }],
"trending": [ … ], "top": [ … ]
}`fresh` keeps pairs with $2k+ liquidity. `audit` and `organicScore` are Solana only. Cached 20 s.
Solana limit and DCA orders through Jupiter's Trigger and Recurring programs. GET lists open orders; POST returns an unsigned transaction.
curl "https://night.poptraderbot.xyz/api/sol-orders?user=YourSolanaPubkey"
const r = await fetch("https://night.poptraderbot.xyz/api/sol-orders?user=YourSolanaPubkey");
const data = await r.json();GET → { "orders": [{ "id": "…", "kind": "limit" | "dca", "inputMint": "…", "outputMint": "…", "inAmount": "100000000", "inUsed": "0", "outReceived": "0", "minOut": "283000", "expiresAt": 1760600000000 }] }
POST → { "tx": "<base64 v0 transaction>", "requestId": "…", "order": "…" }Funds sit in the user's own order account on Jupiter's program; Jupiter's keepers fill. Jupiter's minimums apply (DCA: $50 per order) and come back as a 400 with its message.
Every token the ticket can pick on a chain, with prices.
curl "https://night.poptraderbot.xyz/api/tokens?chainId=4663"
const r = await fetch("https://night.poptraderbot.xyz/api/tokens?chainId=4663");
const data = await r.json();{
"chainId": 4663,
"tokens": [{ "address": "0x…", "symbol": "TSLA", "name": "Tesla", "decimals": 18, "logoURI": "https://…", "priceUSD": 428.1, "kind": "stock" | "stable" | "native" | "other" }]
}Cached 60 s.
Metadata for an ERC-20 that is on no list (read on-chain, priced from DexScreener).
curl "https://night.poptraderbot.xyz/api/token?chainId=8453&address=0x…"
const r = await fetch("https://night.poptraderbot.xyz/api/token?chainId=8453&address=0x…");
const data = await r.json();{ "address": "0x…", "symbol": "ABC", "name": "…", "decimals": 18, "kind": "other", "logoURI": "…", "priceUSD": 0.0123, "liquidityUsd": 51000, "pair": { "dexId": "uniswap", "url": "…" }, "imported": true }404 when the address is not an ERC-20 on that chain.
Hyperliquid reference marks for symbols (stocks via the xyz dex).
curl "https://night.poptraderbot.xyz/api/marks?symbols=TSLA,WETH&kinds=stock,other"
const r = await fetch("https://night.poptraderbot.xyz/api/marks?symbols=TSLA,WETH&kinds=stock,other");
const data = await r.json();{ "marks": { "TSLA": { "hlName": "xyz:TSLA", "mark": 428.12, "prevDay": 425.9, "change24h": 0.0052 } }, "at": 1760000000000 }Per source and chain: breaker state, recent failures and latency. Use it to explain a missing venue.
curl "https://night.poptraderbot.xyz/api/health"
const r = await fetch("https://night.poptraderbot.xyz/api/health");
const data = await r.json();{
"at": 1760000000000, "window": 20, "cooldownMs": 60000,
"sources": [{ "source": "kyber", "chainId": 4663, "state": "ok" | "probing" | "cooling", "calls": 120, "recentFailures": 0, "medianMs": 410, "p90Ms": 900, "adaptiveTimeoutMs": 2700, "coolUntil": null, "reason": null, "rateLimitStrikes": 0, "trips": 0 }]
}Add partner=<address>&partnerBps=<n> to a quote. The router takes partnerBps of the output token on top of its own 5 bps and sends it to partner in the same transaction. The API and the contract both clamp it to 100 bps (1%). Every netAmountOut in the response is already net of both fees, so show those numbers as-is.
https://night.poptraderbot.xyz/api/quote?chainId=4663&tokenIn=0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168&tokenOut=0x322F0929c4625eD5bAd873c95208D54E1c003b2d&amountIn=100000000&taker=0xYourWallet&partner=0xYourWallet&partnerBps=20
Fees exist only where NightRouter is deployed (via: "router", Robinhood Chain today). Elsewhere, and for venues the router does not forward to, the quote executes directly against the venue with feeBps: 0 and the partner parameters are ignored. The partner share needs the v2 router; until it is live on a chain, ask before relying on payouts there.
The swap ticket as an iframe, themed to your page, with your partner fee baked in. Configure it and copy the snippet on the widget page.