Skip to main content
Most prediction-market APIs — struct.to among them — are transactional. They hand you resources: a market, an order, a position, a user. Each response is a faithful record of one thing, and the shape of the API follows the shape of the database behind it. That is exactly right if you are placing trades, reconciling fills, or keeping a local mirror in sync. Datadash is analytical. Nothing we return corresponds to a single stored record. Every response is the result of a query — filtered, joined, aggregated and ranked before it leaves the server. The distinction matters more than it sounds like it should, because it decides where the work happens.

The same question, both ways

Take a question you’d actually ask: which wallets made the most money in Sports last month, and what are they holding now? On a transactional API, that is a program:
  1. Page through trades for the period. There are millions.
  2. For each trade, resolve its market to find the category. That’s a second endpoint, and a cache you now have to maintain.
  3. Group by wallet. Sum cost basis and proceeds. Handle partial exits, and decide what you do about positions that were open at the start of the window.
  4. Sort what you computed. Take the top 100.
  5. For each of those 100 wallets, fetch current positions. That’s 100 more requests.
  6. Resolve each position’s market. More requests, or a bigger cache.
On Datadash it is one request:
Sent to /api/v1/profiles/user-tag. The ranking is the response.

What that buys you

Aggregation happens next to the data. Our storage is columnar, and the expensive rollups — per-wallet profiles, per-category breakdowns, position accounting — are precomputed by a pipeline rather than derived per request. Summing PnL across a million fills is a column scan, not a million objects serialized over HTTP so your process can add them up. Rows arrive resolved. Identifier columns come back already joined to the entity they name, so a row carries the market’s question, the event’s title and the category labels outright:
There is no second request and no join table on your side. This is the single largest difference in practice — most of the code people write against transactional market APIs is join maintenance. Ranking is a parameter, not a post-processing step. orderBy takes a prioritized list of sort keys and applies them before pagination, so “page 2 of the top traders” means what you’d expect. Sorting after you paginate — which is what you’re forced into when the server won’t rank — silently gives you the wrong answer. Filtering is typed and composable. Conditions carry a field, an operator appropriate to that field’s type, and a value; groups combine them with AND/OR. Numbers get comparisons, text gets matching, timestamps get windows, and wallet addresses get inCohort — membership in a group you defined, evaluated server-side. Cohorts are the clearest case of something that only works this way. “The 400 wallets matching these performance criteria” is not a resource a transactional API can hand you, because it is not a stored entity. It is a query result that other queries take as input.

Where transactional still wins

We are not claiming the analytical shape is better at everything. It isn’t: The honest framing is that these are complementary. Plenty of teams use a transactional API for execution and Datadash for the analysis that decides what to execute.

The cost model is different too

A transactional API charges you per resource fetched, and the leaderboard above costs thousands of requests. An analytical API charges you per question asked, and it costs one. That gap widens with every wallet you add to the analysis — which is the direction analytical work always goes. It also changes what is worth building. When a cohort leaderboard is a single request, you put it on a page and let users change the window. When it is a six-step pipeline with a cache to invalidate, you compute it nightly and ship a stale number.

Try the comparison

Pick something you currently assemble client-side and see what it takes here.

Filtering

The condition and group grammar behind every example above.

Generating a Client

Typed TypeScript and Python clients from the OpenAPI spec.