Hushxima
Marketplace

Organisation

Markup, credentials, people, and the numbers on your dashboard.

Everything on this page is administration of your own organisation. All of it needs an organisation admin signed in as a user, since API keys do not qualify. The exceptions are GET /config and GET /stats, which any credential can read.

Configuration

GET /config returns six fields.

FieldMeaning
markup_tiersyour resale markup, one rate per wallet tier
markup_lockedwhether you may change it
rate_limit_rpmyour requests-per-minute allowance
is_internalwhether this is a platform-internal organisation
private_marketplacewhether you can run your own funding plans and sell from your own inventory
funding_fee_bpsthe platform fee you pay on each of those plans, in basis points

markup_tiers always carries the four tiers, ordered tier0 to tier3, each with its own markup_pct. The platform's own margin has always varied with the tier, and yours can too: a tier3 wallet is worth more to hold than a tier0 one, and can carry a different rate.

PUT /config changes the markup and nothing else. It takes either form.

// one rate for the whole catalog, applied to all four tiers
{ "markup_pct": "0.25" }

// tier by tier; the tiers you leave out keep their rate
{ "markup_tiers": [
    { "tier": "tier0", "markup_pct": "0.15" },
    { "tier": "tier3", "markup_pct": "0.40" }
  ] }

Passing both is a 400, and so is passing neither, because the two would disagree about what tier0 should be and the API will not pick a winner. The call is all-or-nothing: one rate it refuses leaves every tier exactly as it was, including the ones listed before it.

If markup_locked is true, meaning your pricing has been fixed for you, the call returns 403 with markup is locked by admin. The lock covers the whole set at once. Reading markup_locked before offering the control is the friendlier way to handle that.

The markup feeds straight into catalog pricing. It is one of the two components sitting on top of a wallet's base price, alongside the platform's own margin for that wallet's tier. Change a tier's rate and every user_price in the catalog for that tier moves with it.

GET
/config

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/config"
{  "funding_fee_bps": 0,  "is_internal": true,  "markup_locked": true,  "markup_tiers": [    {      "markup_pct": "string",      "tier": "string"    }  ],  "private_marketplace": true,  "rate_limit_rpm": 0}
PUT
/config

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.

Response Body

application/json

curl -X PUT "https://example.com/config" \  -H "Content-Type: application/json" \  -d '{}'
{  "funding_fee_bps": 0,  "is_internal": true,  "markup_locked": true,  "markup_tiers": [    {      "markup_pct": "string",      "tier": "string"    }  ],  "private_marketplace": true,  "rate_limit_rpm": 0}

API keys

Covered under Authentication: creating one, the fact that the secret is shown exactly once, and revoking it.

People

Users belong to one organisation and hold one of two roles, org_admin or org_member. Admin is what unlocks this page.

There is no sign-up form. You invite an address, they get an email, they register with the token in it. POST /users/invite defaults to org_member when no role is given.

PUT /users/{id}/status flips a user between active and disabled. A disabled user's tokens stop working on the next request, because the check is on the account rather than on the token, so there is no window to wait out.

Pending invitations live at GET /invitations until they are accepted, and DELETE /invitations/{id} withdraws one that should not have gone out.

GET
/users

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/users"
[  {    "created_at": "string",    "email": "string",    "id": "string",    "last_login_at": "string",    "name": "string",    "org_id": "string",    "role": "string",    "status": "string",    "timezone": "string"  }]
POST
/users/invite

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.

Response Body

application/json

curl -X POST "https://example.com/users/invite" \  -H "Content-Type: application/json" \  -d '{    "email": "string"  }'
{  "accepted_at": "string",  "created_at": "string",  "email": "string",  "expires_at": "string",  "id": "string",  "org_id": "string",  "role": "string",  "status": "string"}
PUT
/users/{id}/status

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 PUT "https://example.com/users/string/status" \  -H "Content-Type: application/json" \  -d '{    "status": "string"  }'
{  "ok": true}
GET
/invitations

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/invitations"
[  {    "accepted_at": "string",    "created_at": "string",    "email": "string",    "expires_at": "string",    "id": "string",    "org_id": "string",    "role": "string",    "status": "string"  }]
DELETE
/invitations/{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/invitations/string"
{  "ok": true}

Dashboard numbers

GET /stats is the summary: how many orders you have placed, how many wallets you hold, how many quotes are open right now, and your spend, margin and balance broken down per chain.

Two finer cuts sit next to it. GET /stats/sales sums your settled sales per day and per chain, with the days cut in your timezone (your profile's, tz to override, UTC for an API key), over the last days days. GET /stats/buyers sums them per buyer reference and chain instead, which is the "who buys the most" view. Both carry sales, wallets, user_price_total and margin_total, in base units per chain, as everywhere.

The per-chain breakdown is not an accident. Base units mean different things on different chains, so a single cross-chain total would be meaningless. Price each chain's native token with GET /prices and sum in USD if you want one number.

GET
/stats

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/stats"
{  "active_quotes": 0,  "balances": [    {      "amount": "string",      "chain": "string"    }  ],  "margin_by_chain": [    {      "amount": "string",      "chain": "string"    }  ],  "spent_by_chain": [    {      "amount": "string",      "chain": "string"    }  ],  "total_purchases": 0,  "wallets_bought": 0}
GET
/stats/sales

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Query Parameters

days?|

How many days back to include. Omit for all-time.

Formatint64
Defaultnull
tz?|

IANA zone the day buckets are cut in. Defaults to the caller's profile timezone; API-key callers have none and get UTC.

Defaultnull

Response Body

application/json

curl -X GET "https://example.com/stats/sales"
{  "buckets": [    {      "bucket": "string",      "chain": "string",      "cost_basis_total": "string",      "is_internal": true,      "margin_total": "string",      "org_id": "string",      "our_price_total": "string",      "profit_total": "string",      "sales": 0,      "user_price_total": "string",      "wallets": 0    }  ],  "timezone": "string"}
GET
/stats/buyers

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Query Parameters

days?|

How many days back to include. Omit for all-time.

Formatint64
Defaultnull
tz?|

IANA zone the day buckets are cut in. Defaults to the caller's profile timezone; API-key callers have none and get UTC.

Defaultnull

Response Body

application/json

curl -X GET "https://example.com/stats/buyers"
[  {    "buyer_ref": "string",    "chain": "string",    "last_sale_at": "string",    "margin_total": "string",    "sales": 0,    "user_price_total": "string",    "wallets": 0  }]

Last updated on

On this page