riddlePARTNERS

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.

ConnectionScopeSuggested label
Swap DEXswapacme-swap-prod
Bridgebridgeacme-bridge-prod
Cafe marketplacecafeacme-cafe-prod
DevTools token MMtokenacme-token-prod
NFT collectionsnftacme-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
WalletChainsHow it pays
Riddle WalletXRPL · EVM · BNB · SOL · XLMDeep-link send/swap (XLM exclusive)
XamanXRPLtxjson Payment QR / deep link
JoeyXRPLWC xrpl_signAndSubmit
MetaMask / AppKitETH · BNB + L2seth_sendTransaction stay-in-app
Phantom / AppKitSolanatransfer + 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 txHash

Swap 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_ID

Marketplace 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.