Response envelope
The envelope is not uniform across the surface — it depends on the endpoint family. Enveloped (legacy/api/v1/* + raw stats/swaps):
/api/v1/pairs, /api/v1/candles, /api/v1/candles/latest, /api/v1/stats, /api/v1/top-movers, /api/v1/protocols (and the raw /stats/*, /swaps/* families).
Top-level (no wrapper): newer endpoints return the payload directly — no success/data keys:
/screener,/search,/trending,/tokens/{mint}/intel,/tokens/{mint}/risk
/screener returns { results, total_matches, limit, offset, warnings } at the top level.
Errors are always enveloped, even for the top-level endpoints, and error is an object:
error.code (the codes). error.message is for humans and is not a stable format; a 5xx message is generic and never carries the internal cause.
/screener: a malformedmint,mints[]orcreatorfilter is a 400INVALID_PARAM(messageinvalid parameter: invalid_filter:mint|creator|mints). An unsupported filter (e.g.risk_score) instead stays 200 and adds a note to thewarnings[]array./search: a malformedcreator(ordeployer) ormintsis a 400INVALID_PARAM(invalid_filter:creatororinvalid_filter:mints).minton/searchis matched as text, likequery, and is never rejected. An unsupported filter stays 200 with awarnings[]note, as on/screener./tokens/{mint}/inteland/tokens/{mint}/risk: a malformedmintis a 400INVALID_PARAM, an unknown mint a 404NOT_FOUND, and a failed lookup a 503UNAVAILABLE(retry). A failed lookup is never reported as a 404;/tokens/{mint}/riskanswers 504GATEWAY_TIMEOUTif its lookup times out./tokens/{mint}/holders,/holders/top,/snipers,/insiders,/smart-moneyand/whales: a malformedmintis a 400INVALID_PARAMon every tier.- Not on this shape yet:
/swaps/*and/stats/*send a flat{ "error": "invalid_parameter", "message": "..." }(their 401 and 429 carry theerrorobject but nosuccess), and/tokens/{mint}/concentrationsends{ "error": "..." }. They are being moved to the envelope; until then, iferroris a string, treat it as the message.
Base paths
Endpoints live under different base paths, and one is served by a separate service:
All paths share the same host,
https://api.dexploit.dev, and the same Authorization / API-key auth.
Rate limits
Dexploit’s pricing model is capped requests-per-second, unlimited monthly usage. Pick a tier that matches your sustained throughput; there is no monthly volume to budget against.
The cap is strict per second. Requests are counted in fixed one-second windows (
rps_window_secs: 1 in /credits), and the first request over the cap within a second gets a 429. There is no burst allowance above it: a Free-tier client gets 20 requests in any one second, not more by staying quiet the rest of the minute.
Inspecting your usage
CallGET /credits at any time to see your current tier, RPS cap, requests used in the current window, and feature flags:
monthly_used is informational. There is no monthly cap on Dexploit — the field shows your cumulative request count for the current calendar month so you can size up your typical load.
Rate limiting
When you exceed your tier’s RPS cap you get HTTP 429 withcode: "RATE_LIMIT_EXCEEDED". Back off and retry. Windows are one second long, so a short backoff is enough; GET /credits shows the current window’s usage.
Tier-locked features
Some endpoints are paid-tier-only. Free tier callers get HTTP 200 withtier_locked: true rather than a 429:
/tokens/{mint}/smart-money, /tokens/{mint}/whales.
Streaming caps
Each API key has one allowance of concurrent streams, set by its tier. Every open stream on every transport counts against it: a gRPCdexploit.v1.SwapStream stream, a gRPC dexploit.v1.PriceStream stream, and a /ws or /ws/swaps WebSocket.
The allowance is counted per streaming server today, so while your streams are spread across servers you may be allowed more than your tier’s cap. Do not rely on that: the cap will be enforced across all servers.
Opening a stream past the cap is refused once the cap is reached on the server that receives it: gRPC returns
RESOURCE_EXHAUSTED (stream cap exceeded; tier=… cap=…), and a WebSocket is closed with code 1013. A slot is freed as soon as its stream closes.
The wallet_tags filter is Pro+ only — on lower tiers the filter is silently dropped and the response carries x-dexploit-tier-locked-filter: wallet_tags metadata. See gRPC: SwapStream for the full reference.

