Hushxima
Marketplace

Catalog

Browsing the inventory that is for sale, and where each wallet's price comes from.

The catalog is the set of wallets currently listed for sale. Wallets leave it the moment a quote reserves them and never come back, so treat a page of results as a snapshot rather than a stable list.

What a wallet looks like

Each entry carries the history that makes it worth buying:

  • balance, what the wallet holds right now, in base units.
  • funded_at, first_tx_at, last_tx_at, its timeline. Age is derived from funded_at.
  • tx_count, how many transactions it has made.
  • funding_source and funding_exchange, where the money originally came from. The first names the provider, the second the actual exchange when the wallet was funded from one.
  • tier, persona_name, timezone_name, the quality band and the behavioural profile the wallet was aged under.
  • token_holdings, non-native tokens sitting in the wallet, if any.

Two prices, and they are not the same

cost_basis is what the wallet costs the platform. user_price is what you will be charged, and it is the one that matters: platform margin for the wallet's tier, plus your own organisation's resale markup, on top of the base.

On a catalog response user_price is computed live, with exactly the pricing a quote would apply, so the number you display is the number the order charges. On a sold wallet the same field means something slightly different: the price actually paid, frozen at settlement.

Both are in base units. Convert to USD with GET /prices if you are showing them to a human.

Filtering

GET /catalog takes the filters you would expect, covering chain, balance range, price range, age range and transaction count, plus a few that are specific to this inventory:

  • sources, tier, persona and timezone are comma-separated multi-selects: tier=tier1,tier2.
  • min_funding_gap_seconds thins the results so that no two returned wallets were funded within that many seconds of each other. A batch of wallets all funded in the same minute is a pattern, and this is how you avoid buying one.
  • gap_with takes a comma-separated list of Unix timestamps and keeps only wallets whose funded_at is at least min_funding_gap_seconds away from every one of them. Useful when you already hold wallets and want the next lot not to line up with them. It requires min_funding_gap_seconds to be set.

sort defaults to random, which is not really random. It interleaves funding sources and funding windows round-robin, so a page, and any lot you pick out of it, spreads across funders and time instead of clustering. order is ignored in that mode. If you want plain chronological order, ask for sort=age explicitly.

GET
/catalog

Authorization

bearerAuth
AuthorizationBearer <token>

JWT from /auth/login (users) or an org API key (mk_...) for integrations.

In: header

Query Parameters

chain?string|null
count?integer

Max rows for this page (per-request cap; page past it via cursor).

Formatint64
Default50
cursor?|

Opaque keyset cursor from a prior response's next_cursor. When set, returns the page strictly after it.

Defaultnull
gap_with?|

Comma-separated reference timestamps (Unix epoch seconds). A wallet is kept only if its funded_at is at least min_funding_gap_seconds away from each of them, so its funding gap never collides with these times. Composes with the mutual spacing above.

max_age_days?|
Formatint64
max_balance?string|null
max_price?string|null
max_tx_count?|
Formatint32
min_age_days?|
Formatint64
min_balance?|

Balance bounds, in base units (lamports on Solana, wei on EVM) — the same scale as WalletDto.balance. Convert native → base client-side.

min_funding_gap_seconds?|

Minimum funding gap, in seconds. When set (>0) it enforces mutual spacing: the returned wallets are thinned along funded_at so no two are funded within this many seconds of each other (like a quote's min_gap_seconds). The same threshold also applies to gap_with when that is provided. Required when gap_with is set.

Formatint64
min_price?|

Price bounds on our price (cost_basis), also in base units (same scale as balance). For USD filtering convert client-side via /prices.

min_tx_count?|

Transaction-count bounds (inclusive) on tx_count.

Formatint32
order?|

asc (default) | desc.

persona?|

Comma-separated persona names (multi-select), e.g. memecoin_degen,hodler.

sort?|

random (default) | age | balance | price | tx_count. random interleaves funding source and funding time round-robin, so a page (or a lot picked from it) spreads across funders and funding windows instead of clustering on one; order is ignored in that mode. age is the un-diversified chronological order for callers that want it explicitly.

source?string|null
sources?|

Comma-separated funding sources (multi-select), e.g. binance,kraken.

tier?|

Comma-separated quality tiers (multi-select), e.g. tier1,tier2.

timezone?|

Comma-separated timezone-profile names (multi-select).

Response Body

application/json

curl -X GET "https://example.com/catalog"
{  "items": [    {      "aging_status": "string",      "balance": "string",      "buyer_ref": "string",      "chain": "string",      "cost_basis": "string",      "created_at": "string",      "first_tx_at": "string",      "funded_at": "string",      "funding_exchange": "string",      "funding_source": "string",      "id": "string",      "imported": true,      "last_tx_at": "string",      "network": "string",      "owner_org_id": "string",      "persona_name": "string",      "pubkey": "string",      "sale_id": "string",      "sold_at": "string",      "source_kind": "string",      "status": "string",      "target_age_days": 0,      "tier": "string",      "timezone_name": "string",      "token_holdings": [        {          "balance": "string",          "decimals": 0,          "mint": "string",          "symbol": "string",          "ui_multiplier": "string",          "usd_value": 0        }      ],      "tx_count": 0,      "user_price": "string"    }  ],  "next_cursor": "string"}

Counting and faceting before you fetch

GET /catalog/count answers the same filters with a single number. It is cheap enough to call on every keystroke of a filter form.

GET /catalog/facets returns the bounds and histograms of the current selection: maximum balance, price, transaction count and age, four histograms to draw sliders against, and the distinct tiers, personas and timezones available. It is what you build a filter panel out of.

GET /catalog/sources lists the distinct funding sources present, optionally narrowed to one chain.

GET
/catalog/count

Authorization

bearerAuth
AuthorizationBearer <token>

JWT from /auth/login (users) or an org API key (mk_...) for integrations.

In: header

Query Parameters

chain?string|null
count?integer

Max rows for this page (per-request cap; page past it via cursor).

Formatint64
Default50
cursor?|

Opaque keyset cursor from a prior response's next_cursor. When set, returns the page strictly after it.

Defaultnull
gap_with?|

Comma-separated reference timestamps (Unix epoch seconds). A wallet is kept only if its funded_at is at least min_funding_gap_seconds away from each of them, so its funding gap never collides with these times. Composes with the mutual spacing above.

max_age_days?|
Formatint64
max_balance?string|null
max_price?string|null
max_tx_count?|
Formatint32
min_age_days?|
Formatint64
min_balance?|

Balance bounds, in base units (lamports on Solana, wei on EVM) — the same scale as WalletDto.balance. Convert native → base client-side.

min_funding_gap_seconds?|

Minimum funding gap, in seconds. When set (>0) it enforces mutual spacing: the returned wallets are thinned along funded_at so no two are funded within this many seconds of each other (like a quote's min_gap_seconds). The same threshold also applies to gap_with when that is provided. Required when gap_with is set.

Formatint64
min_price?|

Price bounds on our price (cost_basis), also in base units (same scale as balance). For USD filtering convert client-side via /prices.

min_tx_count?|

Transaction-count bounds (inclusive) on tx_count.

Formatint32
order?|

asc (default) | desc.

persona?|

Comma-separated persona names (multi-select), e.g. memecoin_degen,hodler.

sort?|

random (default) | age | balance | price | tx_count. random interleaves funding source and funding time round-robin, so a page (or a lot picked from it) spreads across funders and funding windows instead of clustering on one; order is ignored in that mode. age is the un-diversified chronological order for callers that want it explicitly.

source?string|null
sources?|

Comma-separated funding sources (multi-select), e.g. binance,kraken.

tier?|

Comma-separated quality tiers (multi-select), e.g. tier1,tier2.

timezone?|

Comma-separated timezone-profile names (multi-select).

Response Body

application/json

curl -X GET "https://example.com/catalog/count"
{  "count": 0}
GET
/catalog/facets

Authorization

bearerAuth
AuthorizationBearer <token>

JWT from /auth/login (users) or an org API key (mk_...) for integrations.

In: header

Query Parameters

chain?string|null
count?integer

Max rows for this page (per-request cap; page past it via cursor).

Formatint64
Default50
cursor?|

Opaque keyset cursor from a prior response's next_cursor. When set, returns the page strictly after it.

Defaultnull
gap_with?|

Comma-separated reference timestamps (Unix epoch seconds). A wallet is kept only if its funded_at is at least min_funding_gap_seconds away from each of them, so its funding gap never collides with these times. Composes with the mutual spacing above.

max_age_days?|
Formatint64
max_balance?string|null
max_price?string|null
max_tx_count?|
Formatint32
min_age_days?|
Formatint64
min_balance?|

Balance bounds, in base units (lamports on Solana, wei on EVM) — the same scale as WalletDto.balance. Convert native → base client-side.

min_funding_gap_seconds?|

Minimum funding gap, in seconds. When set (>0) it enforces mutual spacing: the returned wallets are thinned along funded_at so no two are funded within this many seconds of each other (like a quote's min_gap_seconds). The same threshold also applies to gap_with when that is provided. Required when gap_with is set.

Formatint64
min_price?|

Price bounds on our price (cost_basis), also in base units (same scale as balance). For USD filtering convert client-side via /prices.

min_tx_count?|

Transaction-count bounds (inclusive) on tx_count.

Formatint32
order?|

asc (default) | desc.

persona?|

Comma-separated persona names (multi-select), e.g. memecoin_degen,hodler.

sort?|

random (default) | age | balance | price | tx_count. random interleaves funding source and funding time round-robin, so a page (or a lot picked from it) spreads across funders and funding windows instead of clustering on one; order is ignored in that mode. age is the un-diversified chronological order for callers that want it explicitly.

source?string|null
sources?|

Comma-separated funding sources (multi-select), e.g. binance,kraken.

tier?|

Comma-separated quality tiers (multi-select), e.g. tier1,tier2.

timezone?|

Comma-separated timezone-profile names (multi-select).

Response Body

application/json

curl -X GET "https://example.com/catalog/facets"
{  "age_hist": [    0  ],  "balance_hist": [    0  ],  "count": 0,  "max_age_days": 0.1,  "max_balance": "string",  "max_price": "string",  "max_tx": 0,  "personas": [    "string"  ],  "price_hist": [    0  ],  "tiers": [    "string"  ],  "timezones": [    "string"  ],  "tx_hist": [    0  ]}
GET
/catalog/sources

Authorization

bearerAuth
AuthorizationBearer <token>

JWT from /auth/login (users) or an org API key (mk_...) for integrations.

In: header

Query Parameters

chain?string|null

Response Body

application/json

curl -X GET "https://example.com/catalog/sources"
{  "sources": [    "string"  ]}

From a page to an order

There are two ways to turn a selection into a quote.

Let the server pick. Pass the same filters to POST /quote with a count, and it selects that many matching wallets at reserve time. Nothing you saw needs to still be there.

Pick them yourself. Send the wallet_ids you showed the buyer, and the lot is exactly what they chose. If any single one has been reserved by someone else in the meantime, though, the whole call fails with 409 and reserves nothing.

The second is the right choice when a human has been looking at a list. The first is the right choice for anything automated.

Last updated on

On this page