External access
Partner APIs
All external integrations go through https://partners.riddlewallet.com. Each connection (swap, bridge, cafe, token, nft) should have its own API key. Keys are monitored: every call stamps lastUsedAt, and GET /api/v1/monitor probes the upstream suite for that key’s scopes.
Authentication
Every /api/v1/* request (except optional collection-points) requires a key issued in Dashboard → API keys.
X-Api-Key: rpk_live_<secret> # or Authorization: Bearer rpk_live_<secret> # or (not recommended) ?api_key=rpk_live_<secret>
- rpk_live_… — mainnet create / report / prepare
- rpk_test_… — quotes, tokens, estimate, monitor only
- Public demo (quotes only): rpk_test_demo_riddle_partners_quote_smoke_key01
- Pending partners: test keys only until activation
- Suspended partners: 403 SUSPENDED
- Wrong product scope: 403 FORBIDDEN_SCOPE
- Rate limit: 429 RATE_LIMIT (tier RPM)
API keys per connection
Create a separate key for each product connection. Scope the key so a leaked swap key cannot create bridge orders.
| Connection | Scope | Suggested label |
|---|---|---|
| Swap DEX | swap | acme-swap-prod |
| Bridge | bridge | acme-bridge-prod |
| Cafe marketplace | cafe | acme-cafe-prod |
| DevTools token MM | token | acme-token-prod |
| NFT collections | nft | acme-nft-prod |
POST /api/dashboard/keys
{ "env": "live", "label": "acme-swap-prod", "scopes": ["swap"] }
GET /api/dashboard/keys # prefix, scopes, lastUsedAt
DELETE /api/dashboard/keys?id=Monitoring
Suite monitors hit these without your secret. You monitor your own keys with the same header.
# Public (no key) GET https://partners.riddlewallet.com/api/health GET https://partners.riddlewallet.com/healthz GET https://partners.riddlewallet.com/api/v1/collection-points # Per-key connection probe (requires X-Api-Key) GET https://partners.riddlewallet.com/api/v1/monitor # Example curl -s https://partners.riddlewallet.com/api/v1/monitor \ -H "X-Api-Key: rpk_live_YOUR_SWAP_KEY"
Monitor returns 200 if every scoped connection’s upstream is healthy, or 207 if any probe fails. Body includes key prefix, scopes, lastUsedAt, and per-connection ok / status / ms.
Riddle suite monitors also check https://partners.riddlewallet.com/api/health and a demo-key quote smoke on swap tokens.
Pay with any wallet
Embeds iframe the live suite apps, so the same connect matrix as Swap / Bridge / Cafe applies: Riddle Wallet (all chains including XLM), Xaman + Joey (XRPL), MetaMask / Reown AppKit (EVM + BNB), Phantom / AppKit (Solana). REST partners call prepare and sign the returned payloads — fee first, then the product leg.
GET https://partners.riddlewallet.com/api/v1/wallets # public catalog + bank treasuries POST /api/v1/swap/prepare # fee + swap steps, per-wallet sign payloads POST /api/v1/bridge/prepare # fee + deposit steps (2 txs) POST /api/v1/market/quote # cafe broker Payment for Xaman / Joey / Riddle # Each payment.steps[i].wallets[] includes: # xaman.txjson · joey xrpl_signAndSubmit · metamask eth_sendTransaction # phantom solana_transfer · riddle send URL
| Wallet | Chains | How it pays |
|---|---|---|
| Riddle Wallet | XRPL · EVM · BNB · SOL · XLM | Deep-link send/swap (XLM exclusive) |
| Xaman | XRPL | txjson Payment QR / deep link |
| Joey | XRPL | WC xrpl_signAndSubmit |
| MetaMask / AppKit | ETH · BNB + L2s | eth_sendTransaction stay-in-app |
| Phantom / AppKit | Solana | transfer + Jupiter swap tx |
Bank destinations: XRPL rheJJYv5GXwFMHTqpUYCS5HsFJAYNiydG2, EVM/BNB 0x4f88F60075ac9545C2B62A43cC9feae4fc729F76, SOL FHCRzjC2K26ZhfcFoiYNpVWrN1zxqV8fUf2HoSTZwsu7, XLM GD4Y5EKJZSN6HQOMRLXE5CL7E2ALWCEWZNP2PUIB2T3X4LJUAZV25FF4.
Sign session · POST / GET / complete
Host unsigned payloads from /prepare as a sign session. Open the returned popupUrl with window.open — a wallet popup, never an iframe. Wallet hosts (Riddle Wallet, Xaman, Joey, MetaMask, Phantom) refuse framing. Product widgets still iframe the suite apps; the sign hop is always a popup (mobile: same-tab redirect).
# Create (X-Api-Key). Returns id, embedToken, embedUrl, walletSignUrl
POST https://partners.riddlewallet.com/api/v1/sign/session
{
"chain": "xrpl",
"product": "swap",
"instruction": "Pay platform fee then swap",
"origin": "https://acme.example",
"payload": { /* unsigned step from /prepare — txjson / wallets[] */ }
}
# Poll — API key, or widget via ?et=
GET https://partners.riddlewallet.com/api/v1/sign/session/SESSION_ID
GET https://partners.riddlewallet.com/api/v1/sign/session/SESSION_ID?et=EMBED_TOKEN
# session.status: pending | signed | expired | cancelled
# Complete after the wallet signs (embed token — no API key)
POST https://partners.riddlewallet.com/api/v1/sign/session/SESSION_ID/complete
{
"et": "EMBED_TOKEN",
"txHash": "…"
}
# Browser — iframe the partners widget; wallet is a popup, not iframe
const w = window.open(walletSignUrl, 'riddle-wallet-sign',
'popup=yes,width=440,height=760,menubar=no,toolbar=no,status=no')
# never: <iframe src="https://wallet.riddlewallet.com/…">
# poll GET until status=signed, then swap/report or bridge/create with txHashSwap API · scope=swap
GET /api/v1/swap/tokens?chain=solana
GET /api/v1/swap/quote?chain=solana&fromToken=…&toToken=…&amount=1000000
# evm: chain=eth|bnb (LI.FI) xrpl: chain=xrpl
POST /api/v1/swap/prepare # test key → unsigned; live → + Jupiter if quoted
{
"chain": "xrpl",
"amountMinor": "1000000",
"partnerBps": 0,
"userAddress": "r…"
}
POST /api/v1/swap/report # live key — fee accrual
{
"chain": "xrpl",
"amountMinor": "1000000",
"feeTxHash": "…",
"sourceTxHash": "…"
}Bridge API · scope=bridge
Two on-chain legs on the suite Bridge: (1) platform fee, (2) deposit. Create stays gated on fee tx proof.
GET /api/v1/bridge/currencies
GET /api/v1/bridge/estimate?fromCurrency=xrp&fromNetwork=xrp&toCurrency=eth&toNetwork=eth&amount=10
POST /api/v1/bridge/prepare # fee + deposit sign payloads (any wallet)
POST /api/v1/bridge/create # live key — requires feeTxHash
{
"fromCurrency": "xrp",
"fromNetwork": "xrp",
"toCurrency": "eth",
"toNetwork": "eth",
"fromAmount": "10",
"destination": "0x…",
"feeTxHash": "…"
}
GET /api/v1/bridge/status?id=ORDER_IDMarketplace API · scope=cafe
GET /api/v1/market/config
POST /api/v1/market/quote
{
"mode": "buy_now",
"amountXrp": 10,
"partnerBps": 0
}Token MM API · scope=token
POST /api/v1/token/quote
{
"tokenId": "…",
"side": "buy",
"amount": 100
}NFT API · scope=nft
GET /api/v1/nft/collections
Collection points
GET /api/v1/collection-points # optional X-Api-Key — echoes partner slug + share
Internal (suite only — not partner keys)
Suite apps attribute fees with HMAC, not X-Api-Key.
POST /api/internal/fee-event
X-Riddle-Partners-Signature: hex_hmac_sha256(body, PARTNERS_INTERNAL_SECRET)
{
"partnerSlug": "acme",
"product": "swap",
"feeTxHash": "…",
"amountMinor": "1000000"
}Embeds (browser, no API key)
Full steps: /docs/setup. Allowlist your origin first.
<div id="riddle-swap"></div>
<script src="https://partners.riddlewallet.com/riddlepartners.js"></script>
<script>
const riddle = RiddlePartners.createClient({ partner: 'acme' })
riddle.mount('#riddle-swap', { product: 'swap', height: 560 })
</script>Also see Swap, Bridge, Marketplace, Setup.