Hushxima
Marketplace

Private marketplace

Fund your own inventory from a deposit, let the platform farm and list it for you alone, and deliver it to your customers at no charge.

The marketplace sells wallets the platform produced. With the private marketplace your organisation produces its own: you draft a funding plan, send the money to a deposit address, and the platform does what it does for its own stock, funds the wallets through exchanges and proxies, farms them under the personas you chose, and lists them when they are ready. They are listed for you only, and you hand them to your customers without paying for them a second time.

The feature is switched on per organisation. GET /config tells you whether yours has it (private_marketplace) and what the platform charges on each plan (funding_fee_bps). Without it every route on this page answers 403.

A plan, from draft to inventory

A plan goes through five states, and you drive the first two transitions.

StatusMeaning
draftbeing configured; the only state a plan can be edited or deleted in
awaiting_fundsarmed: it has a deposit address and a required amount
launchingmoney seen, funding jobs being created
executingwallets being funded and farmed
done / failedevery funding job has stopped
cancelleddropped from draft or awaiting_funds

Drafting

POST /inventory/plans creates a draft. The configuration is the operator's own planner: a solve_mode of budget (fix the money, derive the wallet count) or spec (fix the counts, derive the cost), a USD budget_usd in budget mode, the share of wallets routed through exchanges rather than proxies as cex_pct, and one or more segments.

A segment is one chain's worth of wallets: how many or what share of the budget, the funding each wallet draws between amount_min and amount_max (base units of the segment's chain), the gap between funding groups, and the farming it gets afterwards, as mixes of tiers, personas and timezone profiles. GET /inventory/taxonomy lists the persona and timezone profile ids a mix can name.

POST /inventory/plans/simulate forecasts an unsaved configuration, and GET /inventory/plans/{id}/simulate a saved one: how many wallets, what they cost in USD, how long funding takes, and the checks the planner ran. Use it while editing; nothing is committed.

POST
/inventory/plans

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

An org's own plan: the planner config without a source wallet (the org pays through the deposit minted when the plan is armed).

Response Body

application/json

curl -X POST "https://example.com/inventory/plans" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "armed_at": "string",  "budget_source": "string",  "budget_usd": 0,  "cex_pct": 0,  "completed_at": "string",  "created_at": "string",  "created_by": "string",  "deposit_address": "string",  "deposit_balance": "string",  "deposit_chain": "string",  "fee_amount": "string",  "fee_bps": 0,  "fee_swept_at": "string",  "id": "string",  "job_ids": [    "string"  ],  "launch_balance": "string",  "name": "string",  "notes": "string",  "org_id": "string",  "required_amount": "string",  "segments": [    {      "amount_max": "string",      "amount_min": "string",      "chain": "string",      "farm_duration_days": null,      "gap_max_mins": 0,      "gap_min_mins": 0,      "group_size": 1,      "list_at_age_hours": null,      "list_at_tx_count": null,      "list_combinator": null,      "min_tx": 0,      "persona_mix": {},      "providers": [],      "share_pct": 0,      "target_age_days": null,      "target_count": 0,      "tier_mix": {},      "timezone_mix": {},      "tx_per_day_max": null,      "tx_per_day_min": null    }  ],  "solve_mode": "string",  "source_wallet_id": "string",  "status": "string",  "updated_at": "string",  "validated_at": "string"}
POST
/inventory/plans/simulate

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

An org's own plan: the planner config without a source wallet (the org pays through the deposit minted when the plan is armed).

Response Body

application/json

curl -X POST "https://example.com/inventory/plans/simulate" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "active_wallets": 0,  "avg_tx": 0.1,  "budget_usd": 0.1,  "cex_wallets": 0,  "classic_wallets": 0,  "curve": [    {      "expected": 0,      "hi": 0,      "lo": 0,      "t_mins": 0.1    }  ],  "finish_mins_expected": 0.1,  "finish_mins_max": 0.1,  "finish_mins_min": 0.1,  "over_budget": true,  "remaining_usd": 0.1,  "segments": [    {      "active_wallets": 0,      "amount_max_native": 0.1,      "amount_min_native": 0.1,      "avg_tx": 0.1,      "below_cex_min": true,      "cex_min_native": 0,      "cex_min_usd": 0,      "chain": "string",      "cost_usd": 0.1,      "duration_mins_expected": 0.1,      "duration_mins_max": 0.1,      "duration_mins_min": 0.1,      "groups": 0,      "mature_at_days": 0,      "price_usd": 0.1,      "wallets": 0    }  ],  "total_cost_usd": 0.1,  "total_wallets": 0,  "wallets_per_day": 0.1,  "warnings": [    "string"  ]}
GET
/inventory/taxonomy

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Response Body

application/json

curl -X GET "https://example.com/inventory/taxonomy"
{  "personas": [    {      "id": "string",      "name": "string"    }  ],  "timezones": [    {      "id": "string",      "name": "string"    }  ]}
PUT
/inventory/plans/{id}

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

An org's own plan: the planner config without a source wallet (the org pays through the deposit minted when the plan is armed).

Response Body

application/json

curl -X PUT "https://example.com/inventory/plans/string" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "armed_at": "string",  "budget_source": "string",  "budget_usd": 0,  "cex_pct": 0,  "completed_at": "string",  "created_at": "string",  "created_by": "string",  "deposit_address": "string",  "deposit_balance": "string",  "deposit_chain": "string",  "fee_amount": "string",  "fee_bps": 0,  "fee_swept_at": "string",  "id": "string",  "job_ids": [    "string"  ],  "launch_balance": "string",  "name": "string",  "notes": "string",  "org_id": "string",  "required_amount": "string",  "segments": [    {      "amount_max": "string",      "amount_min": "string",      "chain": "string",      "farm_duration_days": null,      "gap_max_mins": 0,      "gap_min_mins": 0,      "group_size": 1,      "list_at_age_hours": null,      "list_at_tx_count": null,      "list_combinator": null,      "min_tx": 0,      "persona_mix": {},      "providers": [],      "share_pct": 0,      "target_age_days": null,      "target_count": 0,      "tier_mix": {},      "timezone_mix": {},      "tx_per_day_max": null,      "tx_per_day_min": null    }  ],  "solve_mode": "string",  "source_wallet_id": "string",  "status": "string",  "updated_at": "string",  "validated_at": "string"}

Arming: getting a deposit address

POST /inventory/plans/{id}/arm freezes the draft and mints its deposit. You choose the chain you will deposit on; segments on another chain are funded cross-asset through the exchanges. The response carries deposit_address, deposit_chain and required_amount, and the plan is now awaiting_funds.

required_amount is sized so the plan can fund every wallet even if each draws its maximum: the worst case, grossed up for the exchanges' pre-flight margin, plus the platform fee and the deposit's own transaction costs. What the plan does not spend stays on the deposit and comes back to you at the end.

The fee rate is frozen on the plan at this point (fee_bps), so a plan you are already sending money to is never repriced.

POST
/inventory/plans/{id}/arm

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

curl -X POST "https://example.com/inventory/plans/string/arm" \  -H "Content-Type: application/json" \  -d '{    "deposit_chain": "string"  }'
{  "armed_at": "string",  "budget_source": "string",  "budget_usd": 0,  "cex_pct": 0,  "completed_at": "string",  "created_at": "string",  "created_by": "string",  "deposit_address": "string",  "deposit_balance": "string",  "deposit_chain": "string",  "fee_amount": "string",  "fee_bps": 0,  "fee_swept_at": "string",  "id": "string",  "job_ids": [    "string"  ],  "launch_balance": "string",  "name": "string",  "notes": "string",  "org_id": "string",  "required_amount": "string",  "segments": [    {      "amount_max": "string",      "amount_min": "string",      "chain": "string",      "farm_duration_days": null,      "gap_max_mins": 0,      "gap_min_mins": 0,      "group_size": 1,      "list_at_age_hours": null,      "list_at_tx_count": null,      "list_combinator": null,      "min_tx": 0,      "persona_mix": {},      "providers": [],      "share_pct": 0,      "target_age_days": null,      "target_count": 0,      "tier_mix": {},      "timezone_mix": {},      "tx_per_day_max": null,      "tx_per_day_min": null    }  ],  "solve_mode": "string",  "source_wallet_id": "string",  "status": "string",  "updated_at": "string",  "validated_at": "string"}

Launching

Send the money. The platform watches the deposit and launches the plan on its own once the balance covers required_amount; nothing more to call.

POST /inventory/plans/{id}/launch launches it earlier, with whatever has arrived. The budget is then what the deposit holds, net of the fee and of the deposit's transaction costs, so fewer wallets are funded than the plan asked for. A deposit too small to fund a single wallet is refused and the plan stays awaiting_funds.

Launching is what takes the platform fee: fee_amount, at fee_bps of the deposit, is swept to the platform once the funding jobs exist, and never before. launch_balance records what the launch was sized on.

POST
/inventory/plans/{id}/launch

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Response Body

application/json

curl -X POST "https://example.com/inventory/plans/string/launch"
{  "cex_wallets": 0,  "classic_wallets": 0,  "job_ids": [    "string"  ],  "plan_id": "string"}

Watching it run

GET /inventory/plans/{id} is the plan itself, with the deposit's balance as last read on chain (deposit_balance) and the ids of the funding jobs it launched. GET /inventory/plans lists them all.

The wallets appear in GET /inventory/wallets as soon as they are created, and move through the same statuses as platform stock: created while waiting for funding, funded while farming, listed once they reach your private catalog, reserved and sold as you deliver them. GET /inventory/summary gives the counts by status with the plan list in one call.

GET
/inventory/plans

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Response Body

application/json

curl -X GET "https://example.com/inventory/plans"
[  {    "armed_at": "string",    "budget_source": "string",    "budget_usd": 0,    "cex_pct": 0,    "completed_at": "string",    "created_at": "string",    "created_by": "string",    "deposit_address": "string",    "deposit_balance": "string",    "deposit_chain": "string",    "fee_amount": "string",    "fee_bps": 0,    "fee_swept_at": "string",    "id": "string",    "job_ids": [      "string"    ],    "launch_balance": "string",    "name": "string",    "notes": "string",    "org_id": "string",    "required_amount": "string",    "segments": [      {        "amount_max": "string",        "amount_min": "string",        "chain": "string",        "farm_duration_days": null,        "gap_max_mins": 0,        "gap_min_mins": 0,        "group_size": 1,        "list_at_age_hours": null,        "list_at_tx_count": null,        "list_combinator": null,        "min_tx": 0,        "persona_mix": {},        "providers": [],        "share_pct": 0,        "target_age_days": null,        "target_count": 0,        "tier_mix": {},        "timezone_mix": {},        "tx_per_day_max": null,        "tx_per_day_min": null      }    ],    "solve_mode": "string",    "source_wallet_id": "string",    "status": "string",    "updated_at": "string",    "validated_at": "string"  }]
GET
/inventory/plans/{id}

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Response Body

application/json

curl -X GET "https://example.com/inventory/plans/string"
{  "armed_at": "string",  "budget_source": "string",  "budget_usd": 0,  "cex_pct": 0,  "completed_at": "string",  "created_at": "string",  "created_by": "string",  "deposit_address": "string",  "deposit_balance": "string",  "deposit_chain": "string",  "fee_amount": "string",  "fee_bps": 0,  "fee_swept_at": "string",  "id": "string",  "job_ids": [    "string"  ],  "launch_balance": "string",  "name": "string",  "notes": "string",  "org_id": "string",  "required_amount": "string",  "segments": [    {      "amount_max": "string",      "amount_min": "string",      "chain": "string",      "farm_duration_days": null,      "gap_max_mins": 0,      "gap_min_mins": 0,      "group_size": 1,      "list_at_age_hours": null,      "list_at_tx_count": null,      "list_combinator": null,      "min_tx": 0,      "persona_mix": {},      "providers": [],      "share_pct": 0,      "target_age_days": null,      "target_count": 0,      "tier_mix": {},      "timezone_mix": {},      "tx_per_day_max": null,      "tx_per_day_min": null    }  ],  "solve_mode": "string",  "source_wallet_id": "string",  "status": "string",  "updated_at": "string",  "validated_at": "string"}
GET
/inventory/wallets

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Query Parameters

chain?string|null
cursor?|
Defaultnull
limit?integer
Formatint64
Default50
status?string|null

Response Body

application/json

curl -X GET "https://example.com/inventory/wallets"
{  "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,      "inventory_org_id": "string",      "key_purged_at": "string",      "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",          "post_sale": true,          "sellable_balance": "string",          "sellable_usd_value": 0,          "symbol": "string",          "ui_multiplier": "string",          "usd_value": 0        }      ],      "tx_count": 0,      "user_price": "string"    }  ],  "next_cursor": "string"}
GET
/inventory/summary

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Response Body

application/json

curl -X GET "https://example.com/inventory/summary"
{  "counts": [    {      "count": 0,      "status": "string"    }  ],  "plans": [    {      "armed_at": "string",      "budget_source": "string",      "budget_usd": 0,      "cex_pct": 0,      "completed_at": "string",      "created_at": "string",      "created_by": "string",      "deposit_address": "string",      "deposit_balance": "string",      "deposit_chain": "string",      "fee_amount": "string",      "fee_bps": 0,      "fee_swept_at": "string",      "id": "string",      "job_ids": [        "string"      ],      "launch_balance": "string",      "name": "string",      "notes": "string",      "org_id": "string",      "required_amount": "string",      "segments": [        {          "amount_max": "string",          "amount_min": "string",          "chain": "string",          "farm_duration_days": null,          "gap_max_mins": 0,          "gap_min_mins": 0,          "group_size": 1,          "list_at_age_hours": null,          "list_at_tx_count": null,          "list_combinator": null,          "min_tx": 0,          "persona_mix": {},          "providers": [],          "share_pct": 0,          "target_age_days": null,          "target_count": 0,          "tier_mix": {},          "timezone_mix": {},          "tx_per_day_max": null,          "tx_per_day_min": null        }      ],      "solve_mode": "string",      "source_wallet_id": "string",      "status": "string",      "updated_at": "string",      "validated_at": "string"    }  ]}

Backing out, and getting the rest back

POST /inventory/plans/{id}/cancel drops a draft or an armed plan. Once launched there is nothing to cancel: the money is on its way to the wallets.

POST /inventory/plans/{id}/withdraw-leftover sends whatever is still on the deposit to one of your registered withdrawal addresses on that chain. It is available once the plan is done, failed or cancelled, and refused while any transfer from the deposit is still in flight. The destination has to be an address you registered, enabled, on the deposit's chain: the money is yours, and it only ever goes somewhere you named in advance.

POST
/inventory/plans/{id}/cancel

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Response Body

application/json

curl -X POST "https://example.com/inventory/plans/string/cancel"
{  "armed_at": "string",  "budget_source": "string",  "budget_usd": 0,  "cex_pct": 0,  "completed_at": "string",  "created_at": "string",  "created_by": "string",  "deposit_address": "string",  "deposit_balance": "string",  "deposit_chain": "string",  "fee_amount": "string",  "fee_bps": 0,  "fee_swept_at": "string",  "id": "string",  "job_ids": [    "string"  ],  "launch_balance": "string",  "name": "string",  "notes": "string",  "org_id": "string",  "required_amount": "string",  "segments": [    {      "amount_max": "string",      "amount_min": "string",      "chain": "string",      "farm_duration_days": null,      "gap_max_mins": 0,      "gap_min_mins": 0,      "group_size": 1,      "list_at_age_hours": null,      "list_at_tx_count": null,      "list_combinator": null,      "min_tx": 0,      "persona_mix": {},      "providers": [],      "share_pct": 0,      "target_age_days": null,      "target_count": 0,      "tier_mix": {},      "timezone_mix": {},      "tx_per_day_max": null,      "tx_per_day_min": null    }  ],  "solve_mode": "string",  "source_wallet_id": "string",  "status": "string",  "updated_at": "string",  "validated_at": "string"}
POST
/inventory/plans/{id}/withdraw-leftover

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

curl -X POST "https://example.com/inventory/plans/string/withdraw-leftover" \  -H "Content-Type: application/json" \  -d '{    "address_id": "string"  }'
{  "attempts": 0,  "chain": "string",  "created_at": "string",  "id": "string",  "kind": "string",  "last_error": "string",  "next_run_at": "string",  "payload": null,  "status": "string",  "tx_hash": "string",  "updated_at": "string",  "wallet_id": "string"}
DELETE
/inventory/plans/{id}

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

id*String

Response Body

application/json

curl -X DELETE "https://example.com/inventory/plans/string"
{  "ok": true}

Selling what you produced

Your listed wallets show up in the catalog under scope=private, and a quote with "scope": "private" delivers them. There is no price: a private quote with no top-up settles the moment it is created, and the keys are available through the usual routes. With a top-up, the customer pays for the top-up alone.

Deliveries are not sales. They credit no margin to your balance and count in none of the sales statistics, since no money changed hands. They do show in your purchases and on the wallets as sold_at and buyer_ref, so the customer history reads the same whether a wallet came from the marketplace or from your own stock.

Who may do what

Creating, editing, arming, launching, cancelling a plan and withdrawing the leftover need an organisation admin signed in as a user; an API key reads plans and inventory, and delivers wallets, but does not move money. See Authentication.

Last updated on

On this page