Changelog
Changes to the partner API that integrators need to act on, newest first.
2026-11-09: Documentation brought in line with the API
These pages now describe the partner API as it runs today. Many of the changes below shipped over the last months without being documented, so if your integration was built from earlier versions of these pages, review every item. The Postman collection was regenerated and covers every endpoint.
Authentication
- A client has one live access token. Issuing a new token, with any grant, invalidates the previous one. Refresh tokens are single-use: a spent or superseded refresh token is refused with
400, code10006. See Create a Token. - Client certificates are presented in the TLS handshake. The
X-Client-Certheader is no longer accepted. See mTLS Client Certificates. - A call from outside the client's IP allow-list is refused with
401(not403).
Errors
- Errors are
{code, domain, message}, plusdetailson validation failures. The samecodeexists in several domains: identify an error bydomain+code. - Most "not found" errors answer
400with the area's own code, not404. Each endpoint page lists its codes. See Errors.
Wallet and network are always chosen by the caller
- Every operation that signs on-chain takes
wallet_id, andnetwork_idwhere it starts the operation: user buys (primary and secondary market), OTC and secondary-market sell, user burn, rent claim, user and node withdraw, setup creation, currency-token creation, KYC token and token recall. Cancel and delist sign with the wallet stored on the offer or listing. There is no fallback wallet. - Users no longer carry an
address. Addresses live on wallets, and a user can hold several wallets, including more than one per chain.
Routes that moved or were removed
| Before | Now |
|---|---|
/v2/admin/kyc/groups/** | /v2/admin/kycs/{kyc_token_id}/groups/** (platform owner only) |
/v2/admin/kyc/tokens | /v2/admin/kyc-tokens |
/v2/admin/kyc/nodes/{node_id}/addresses | GET /v2/admin/nodes/{node_id}/kyc/addresses |
POST /v2/admin/tokens/nodes/{node_id}/search | GET /v2/admin/tokens?node_id=… |
POST /v2/users/tokens/search | GET /v2/users/tokens?node_id=… |
GET /v2/admin/currency-tokens/active | GET /v2/admin/currency-tokens?is_active=true |
/v2/admin/fees/owner, /fees/platform-owner/defaults, /fees/nodes/{node_id}/defaults, /fees/nodes/{node_id}/platform-owner/defaults | GET /v2/admin/fees?entity=… |
/v2/admin/oracles/categories/{category_id} | GET /v2/admin/oracles?category_id=… |
POST /v2/admin/categories/{category_id}/children/search | GET /v2/admin/categories/{category_id}/children?page=…&per_page=… |
/v2/admin/otc-order-rules/nodes/{node_id}[/tokens/{token_id}] | GET /v2/admin/otc-order-rules?node_id=…&token_id=… |
| Node-scoped OTC listings | GET /v2/admin/otcs?node_id=…, GET /v2/admin/otcs/tokens/{token_id} |
| Node-level contract status and upgrade | Per setup: /v2/admin/nodes/{node_id}/setups/{setup_id}/contracts/… |
PUT /v2/users/{user_id}/wallet, wallet address + signature update | Removed. PATCH /v2/users/{user_id}/wallets/{wallet_id} only renames |
/v2/users/{user_id}/wallets/{wallet_id}/currency-tokens/{currency_token_id} | /v2/users/{user_id}/wallets/{wallet_id}/networks/{network_id}/assets/{asset_id} |
/v2/blockchain/… chain catalog | GET /v2/chains, GET /v2/networks |
POST /v2/webhooks | POST /v2/webhooks/custodial (the old path is a deprecated alias) |
Listings
- Every listing is a
GETwithpageandper_page(both required,per_pageat most 100) and answers{data, total, page, per_page}. A filter that matches nothing answers an empty page.
Asynchronous operations
- Token actions (listing, delist, passive, burn, rent, public transfer, open to OTC, open to secondary market), token and metric updates, currency-token deploy, mint and send, and OTC accept and cancel answer
{"transaction_id": "…"}to poll. Token create answers201with{token_id, transaction_id}. - User burn and rent claim answer an empty
200; poll the user's transactions. Node withdraw answersnull; poll the node's transactions.
Setups and contracts
- A deploy starts with
POST /v2/admin/nodes/{node_id}/setups(wallet_idandnetwork_idrequired). Every call creates a new setup.POST …/setups/{setup_id}/deploytakes no body and only retries or resumes a deploy.
Tokens
- Token create takes
node_id,setup_idandnetwork_id(the setup's network) in the body; the setup's wallet signs. - Token update and metric update write every field: an omitted number is stored as
0. Always send the complete set.
Currency tokens
- Create takes
node_id,network_idandwallet_id, deploys in the same call and answers201with the token in draft./deployonly retries a failed deploy.
Fees
- Fee percentages are strings with at most one decimal. Every write needs all nine values, takes its scope from the route, and answers
200with the saved row. Setup-scoped fee endpoints, effective fees and the affected-setups count are new. See the fee overview.
User market operations
- OTC and secondary-market sell take
currency_token_idandunit_priceinstead ofprice_idandprice_amount. - OTC cancel and secondary-market delist name the deal in the path (
…/deals/{deal_id}/cancel,…/deals/{deal_id}/delist) and take no body. - New purchase quote endpoints answer the price breakdown before buying.
Chain data
GET /v2/blockchain/gas-feenow needs a token withnode:summary:viewand anetwork_id. It answerssafe_gas_price,propose_gas_priceandfast_gas_priceinstead ofmax_feeandmax_priority_fee; the real-timegas_feemessage changed the same way.- Analytics responses use camelCase field names.
Newly documented endpoints
Node setups and wallets, wallet assets, ownership-change processes, platform-owner wallets and settings, analytics, token deposits, rents, burn payouts, investors, retokenize and tokenization images, KYC tokens, setup-scoped fees, oracle CRUD, oracle metrics, category writes, custody / spot-quote / AI provider settings, user listing and wallets, purchase quotes, chains, networks and gas sponsor wallets.
2026-10-21: Monetary values are decimal strings
Every monetary value in the partner API (/v2/admin/**, /v2/users/** and webhooks) is now a decimal string, such as "12.5". Field names and /v2 paths are unchanged. The rules, the error for a malformed value and examples are on Amounts and Percentages.
What changed
- Price objects
{id, amount, decimal, symbol, address}:amount(tokentoken_price,total_value,salable_value,rental_income, …). - Token
salable_percentage. - Fees: fee
valuepercentages (0 to 100, at most one decimal,"2.5"= 2.5 %); feeamountandpercentagein OTC, secondary-market and purchase breakdowns. - Prices:
min_sell_price,max_sell_price,min_price,max_price,unit_price,price_amount. - OTC order rules:
above_amount,below_amount,above_percent,below_percent. - Wallet summaries: balances and
usd/tryvaluations. - Analytics volumes and fee revenue.
- Currency tokens:
total_supply; mint, send and withdrawamount. Node withdrawamount. - Purchase quotes: unit price, subtotal, total, seller proceeds.
- Token-history
start_value,end_value,rate; spot prices; gas fee quotes.
Whole-token counts (quantity, max_supply, listed_supply, sold_supply, purchased_supply, minimum and maximum purchase quantity), decimal, page, per_page, type, status and timestamps stay JSON numbers.
Transition policy
- Responses return these fields as strings starting with this release, always in their shortest form (
"12.5", never"12.50"or"1e-7"). If your client reads them as numbers, update it now. - Requests should send strings. For now, a JSON number is still accepted. Support for numbers ends in a later release. This changelog will announce the date at least 30 days in advance.
- A malformed value, or a fee percentage with more than one decimal, is refused with HTTP 400 and code
10015(invalid request payload). Adetailsentry{field, message}names the rule. - Currency-token mint takes whole tokens. The SToken contract mints whole tokens, so a fractional
amountsuch as"12.5"is now refused with10015; before, it was accepted and the transaction completed without minting anything. - Secondary-market buy (
/v2/users/**) buys a listing whole:quantitymust equal the listing's quantity, and any other value is refused with HTTP 400, code11004. The contract always transfers the whole listing; a different quantity used to be accepted and then approved the wrong payment.