collectorcrypt

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CollectorCrypt API

CollectorCrypt API

Bridge physical trading cards and blockchain — buy, sell, and trade collectible card NFTs on Solana, open mystery gacha packs, redeem NFTs for real cards, and swap assets peer-to-peer.
Marketplace Base URL:
https://api.collectorcrypt.com
Marketplace Devnet URL:
https://dev-api.collectorcrypt.com
Gacha Base URL:
https://gacha.collectorcrypt.com
Gacha Devnet URL:
https://dev-gacha.collectorcrypt.com
连接实体交易卡牌与区块链——在Solana上买卖、交易收藏卡牌NFT,开启神秘扭蛋卡包,将NFT兑换为实体卡牌,并进行点对点资产互换。
市场基础URL:
https://api.collectorcrypt.com
市场测试网URL:
https://dev-api.collectorcrypt.com
扭蛋基础URL:
https://gacha.collectorcrypt.com
扭蛋测试网URL:
https://dev-gacha.collectorcrypt.com

Key Concepts

核心概念

Product Suite

产品套件

  • Marketplace — buy/sell/trade collectible card NFTs using USDC on Solana
  • Gacha Machine — mystery pack system; spend USDC for randomized Pokemon card NFTs with VRF-verified fairness
  • Vault — bridge NFTs ↔ physical cards; deposit real cards to mint NFTs, burn NFTs to ship physical cards
  • Swap — peer-to-peer on-chain asset swaps via escrow (NFTs, pNFTs, cNFTs, SPL tokens)
  • Launchpads — drop pages for minting new collectible releases
  • Bidder — eBay bid automation; deposit funds, service bids and tokenizes won cards
  • 交易市场 — 在Solana上使用USDC买卖/交易收藏卡牌NFT
  • 扭蛋机 — 神秘卡包系统;花费USDC获取随机宝可梦卡牌NFT,通过VRF保证公平性
  • 存管库 — 实现NFT与实体卡牌双向转换;存入实体卡牌铸造NFT,销毁NFT即可邮寄实体卡牌
  • 互换 — 通过托管合约实现链上点对点资产互换(支持NFT、pNFT、cNFT、SPL代币)
  • Launchpads — 新收藏系列铸造的发布页面
  • Bidder — eBay竞价自动化工具;存入资金、服务竞价并将中标卡牌代币化

Solana Programs

Solana程序

ProgramID
Marketplace
CcmRKTuZCGJBWQwMHvDYApBRvSZNHqGJXkznqpDTSQUr
Swap
CCSwaptcDXtfjyRMYBqavqBwiW162yXFAJrXN53UuENC
程序ID
交易市场
CcmRKTuZCGJBWQwMHvDYApBRvSZNHqGJXkznqpDTSQUr
互换
CCSwaptcDXtfjyRMYBqavqBwiW162yXFAJrXN53UuENC

NFT Types Supported

支持的NFT类型

  • Programmable NFTs (pNFTs) — Metaplex standard with enforced royalties; use
    tokenStandard: "Pnft"
  • Compressed NFTs (cNFTs) — Metaplex Bubblegum merkle-tree structure; use
    tokenStandard: "Cnft"
  • Metaplex Core (
    nftStandard: "core"
    )
    — single-account standard; many live listings are Core (browse responses return
    "nftStandard": "core"
    ). For Core listings, omit
    tokenStandard
    from buy/list/offer bodies — do NOT pass
    "Pnft"
    /
    "Cnft"
    . Only send
    tokenStandard
    when the asset is actually pNFT or cNFT.
  • 可编程NFT(pNFTs) — Metaplex标准,强制版税;使用
    tokenStandard: "Pnft"
  • 压缩NFT(cNFTs) — Metaplex Bubblegum默克尔树结构;使用
    tokenStandard: "Cnft"
  • Metaplex核心版(
    nftStandard: "core"
    — 单账户标准;当前许多在售列表为核心版(浏览接口返回
    "nftStandard": "core"
    )。对于核心版列表,在购买/挂单/出价请求体中省略
    tokenStandard
    ——请勿传入
    "Pnft"
    /
    "Cnft"
    。仅当资产确实是pNFT或cNFT时才传入
    tokenStandard

Currency

货币

All marketplace and gacha transactions use USDC (SPL Token) on Solana. Shipping fees accept USDC or USDT. Gas fees paid in SOL.
Marketplace prices are in whole USDC (e.g.,
"price": 25
means $25.00 USDC).
所有市场和扭蛋交易均使用Solana上的USDC(SPL代币)。运费支持USDC或USDT支付。Gas费以SOL支付。
市场价格为整数USDC(例如:
"price": 25
代表25.00 USDC)。

Transaction Pattern (Marketplace & Shipping)

交易流程(市场与物流)

Three-step flow:
  1. Build — POST to API endpoint, receive base64-encoded unsigned transaction(s)
  2. Sign — Sign with the Solana wallet (Phantom/Solflare, or the Starchild wallet helper — see below)
  3. Broadcast — POST signed transaction to
    /marketplace/broadcast
HTTP status — accept BOTH
200
and
201
as success.
Verified live:
/marketplace/buy
and
/marketplace/broadcast
return
201
, not
200
. Treat any 2xx as success; do not hard-check
== 200
.
Response body may be raw base64 text, NOT JSON.
/marketplace/buy
with
fundingSource: "wallet"
can return the unsigned transaction as a plain-text body. Parse defensively:
python
text = response.text
try:
    data = response.json()
    tx = data.get("transaction") or data.get("serializedTransaction")
except Exception:
    tx = text  # body was the raw base64 transaction
Starchild wallet signing returns snake_case
signed_transaction
.
When signing with the platform wallet:
python
from core.skill_tools import wallet
signed = wallet.wallet_sol_sign_transaction(unsigned_tx)
三步流程:
  1. 构建 — 向API端点发送POST请求,获取Base64编码的未签名交易
  2. 签名 — 使用Solana钱包(Phantom/Solflare,或Starchild钱包工具——见下文)签名
  3. 广播 — 将签名后的交易POST至
    /marketplace/broadcast
HTTP状态码——
200
201
均视为成功。
实测:
/marketplace/buy
/marketplace/broadcast
返回**
201
**而非
200
。将所有2xx状态码视为成功;不要硬校验
== 200
响应体可能是原始Base64文本,而非JSON。
fundingSource: "wallet"
时,
/marketplace/buy
可能直接返回未签名交易的纯文本内容。需做容错解析:
python
text = response.text
try:
    data = response.json()
    tx = data.get("transaction") or data.get("serializedTransaction")
except Exception:
    tx = text  # 响应体为原始Base64交易数据
Starchild钱包签名返回蛇形命名的
signed_transaction
使用平台钱包签名时:
python
from core.skill_tools import wallet
signed = wallet.wallet_sol_sign_transaction(unsigned_tx)

→ {"signed_transaction": "<base64>", "encoding": "base64"}

→ {"signed_transaction": "<base64>", "encoding": "base64"}

signed_tx = signed.get("signed_transaction") or signed.get("signedTransaction")
Look for `signed_transaction` first, then the camelCase variant. Feed `signed_tx` into `/marketplace/broadcast` as the `signedTransaction` field.
signed_tx = signed.get("signed_transaction") or signed.get("signedTransaction")
优先读取`signed_transaction`,再尝试驼峰命名的备选字段。将`signed_tx`作为`signedTransaction`字段传入`/marketplace/broadcast`。

Gacha Rarity Tiers

扭蛋稀有度等级

RarityProbability
Epic1%
Rare (High)4%
Uncommon (Mid)15%
Common (Low)80%
稀有度概率
Epic(史诗)1%
Rare(高稀有)4%
Uncommon(中稀有)15%
Common(普通)80%

VRF (Verifiable Random Function)

VRF(可验证随机函数)

Gacha rolls use a Verifiable Random Function for tamper-proof, provably-fair results. Selection is two-stage:
  1. Roll → tier: a uniform integer roll in the range 1–100,000,000, seeded by the player's own wallet signature on the open transaction, maps to a rarity tier via the machine's configured weights (see
    tierRanges
    in
    /api/machines
    ).
  2. Card → within tier: a provable selection picks the specific NFT inside that tier.
The seed (wallet signature) and result are committed to Solana in the award transaction's on-chain memo, preventing prediction or manipulation. Verify independently:
  • GET /api/vrf/verify?memo=YOUR_MEMO
    — returns the proof, public key, transaction signature, and whether the stored roll matches the recomputed roll.
  • /verify-selection/YOUR_MEMO
    — browser-side replay of the card selection against the on-chain memo.
The docs do not name a specific VRF algorithm; don't assert one.
扭蛋抽取使用可验证随机函数,确保结果防篡改、可证明公平。选择分为两个阶段
  1. 抽取→等级: 生成一个范围在1–100,000,000的均匀整数,以玩家在开启交易时的钱包签名作为种子,通过机器配置的权重映射到对应稀有度等级(详见
    /api/machines
    中的
    tierRanges
    )。
  2. 卡牌→等级内: 通过可证明的选择逻辑从对应等级中挑选具体NFT。
种子(钱包签名)和结果会被记录在Solana奖励交易的链上备注中,防止预测或操纵。可独立验证:
  • GET /api/vrf/verify?memo=YOUR_MEMO
    — 返回证明、公钥、交易签名,以及存储的抽取结果是否与重新计算的结果匹配。
  • /verify-selection/YOUR_MEMO
    — 基于链上备注在浏览器端重放卡牌选择过程。
文档未指定具体VRF算法,请勿断言某一算法。

How to Call

调用方式

Gacha API — No API Key (the key does not exist)

扭蛋API——无API密钥(不存在密钥系统)

There is no API key. Do not set
CC_API_KEY
, do not send an
x-api-key
header, and do not try to obtain a key — the CollectorCrypt team has confirmed no key system exists.
Every gacha endpoint, reads and writes alike, is called with no authentication.
bash
undefined
不存在API密钥。请勿设置
CC_API_KEY
,不要发送
x-api-key
请求头,也无需尝试获取密钥——CollectorCrypt团队已确认无密钥系统。
所有扭蛋端点,无论读写,均无需认证即可调用。
bash
undefined

Reads AND writes — no auth header of any kind

读写请求均无需任何认证头

curl -s "https://gacha.collectorcrypt.com/api/machines" curl -s -X POST "https://gacha.collectorcrypt.com/api/generatePack"
-H "Content-Type: application/json"
-d '{"playerAddress":"WALLET_PUBKEY"}'

> **Ignore the docs' authentication section.** The public docs say *"Each request must include a valid `x-api-key` header"* and reference a partner "slug." That does not reflect reality — confirmed both by the team (no key system exists) and by live testing (`/api/generatePack` returns `200` with no header). There is nothing to request and no header to add.

Without a key, generated transactions carry a `cc-<uuid>` memo. Security comes from the **wallet signature**, not from any API credential — nothing executes until the user signs the transaction this API hands back.

Reference implementation: **Gacha Starter Demo** — https://github.com/daxherrera/gacha-starter (full pack → sign → submit → open flow). Try every call live on devnet at `https://dev-gacha.collectorcrypt.com` (fund a devnet wallet via the USDC faucet: https://spl-token-faucet.com/?token-name=USDC-Dev).
curl -s "https://gacha.collectorcrypt.com/api/machines" curl -s -X POST "https://gacha.collectorcrypt.com/api/generatePack"
-H "Content-Type: application/json"
-d '{"playerAddress":"WALLET_PUBKEY"}'

> **忽略文档中的认证章节。** 公开文档提到*“每个请求必须包含有效的`x-api-key`请求头”*并引用合作伙伴“slug”。但这与实际情况不符——团队已确认无密钥系统,且实测`/api/generatePack`无需请求头即可返回`200`。无需申请密钥,也无需添加任何请求头。

无密钥情况下,生成的交易带有`cc-<uuid>`格式的备注。安全性依赖于**钱包签名**,而非API凭证——只有用户签名API返回的交易后,操作才会执行。

参考实现:**扭蛋入门Demo** — https://github.com/daxherrera/gacha-starter(完整的卡包→签名→提交→开启流程)。可在测试网`https://dev-gacha.collectorcrypt.com`上实测所有调用(通过USDC水龙头为测试网钱包充值:https://spl-token-faucet.com/?token-name=USDC-Dev)。

Marketplace API — No Auth for Reads

交易市场API——读请求无需认证

Public GET endpoints (browse listings) need no authentication. Write endpoints return unsigned transactions for wallet signing — no API key involved.
bash
undefined
公开GET端点(浏览列表)无需认证。写端点返回未签名交易供钱包签名——无需API密钥。
bash
undefined

Browse listings — no auth, 5s cache for unauthenticated requests

浏览列表——无需认证,未认证请求有5秒缓存

Create listing — returns base64 unsigned transaction

创建挂单——返回Base64编码的未签名交易

curl -s -X POST "https://api.collectorcrypt.com/marketplace/list"
-H "Content-Type: application/json"
-d '{ "wallet": "YOUR_SOLANA_ADDRESS", "cardId": "CC_CARD_DB_ID", "nftAddress": "NFT_MINT_ADDRESS", "currency": "USDC", "price": 50 }'
undefined
curl -s -X POST "https://api.collectorcrypt.com/marketplace/list"
-H "Content-Type: application/json"
-d '{ "wallet": "YOUR_SOLANA_ADDRESS", "cardId": "CC_CARD_DB_ID", "nftAddress": "NFT_MINT_ADDRESS", "currency": "USDC", "price": 50 }'
undefined

Shipping API — Two Auth Tracks

物流API——两种认证方式

Track A — Privy Identity Token:
Authorization: Bearer <privy-identity-token>
Track B — Sign-In With Solana (SIWS):
  1. POST /auth/wallet/nonce
    — get nonce + message to sign
  2. Sign message with wallet (ed25519, base58)
  3. POST /auth/wallet/verify
    — exchange signature for access/refresh tokens
bash
undefined
方式A——Privy身份令牌:
Authorization: Bearer <privy-identity-token>
方式B——Solana登录(SIWS):
  1. POST /auth/wallet/nonce
    — 获取随机数+待签名消息
  2. 使用钱包签名消息(ed25519,base58编码)
  3. POST /auth/wallet/verify
    — 用签名换取访问/刷新令牌
bash
undefined

Step 1: Get nonce

步骤1:获取随机数

curl -s -X POST "https://api.collectorcrypt.com/auth/wallet/nonce"
-H "Content-Type: application/json"
-d '{"wallet": "YOUR_PUBKEY", "partnerAppId": "your-slug", "domain": "your-app.com", "uri": "https://your-app.com"}'
curl -s -X POST "https://api.collectorcrypt.com/auth/wallet/nonce"
-H "Content-Type: application/json"
-d '{"wallet": "YOUR_PUBKEY", "partnerAppId": "your-slug", "domain": "your-app.com", "uri": "https://your-app.com"}'

Step 3: Verify and get tokens

步骤3:验证并获取令牌

curl -s -X POST "https://api.collectorcrypt.com/auth/wallet/verify"
-H "Content-Type: application/json"
-d '{"message": "<message-from-nonce>", "signature": "<base58-ed25519-signature>"}'
curl -s -X POST "https://api.collectorcrypt.com/auth/wallet/verify"
-H "Content-Type: application/json"
-d '{"message": "<message-from-nonce>", "signature": "<base58-ed25519-signature>"}'

Returns: {"accessToken": "cca_...", "refreshToken": "ccr_...", "expiresAt": ...}

返回:{"accessToken": "cca_...", "refreshToken": "ccr_...", "expiresAt": ...}


**Token management:**
- Access token lifetime: 15 minutes
- Refresh: `POST /auth/wallet/refresh` with `{"refreshToken": "..."}`
- Logout: `POST /auth/wallet/logout`
- Track B limitation: crypto payment only (no card payments), Solana signatures only

**令牌管理:**
- 访问令牌有效期:15分钟
- 刷新令牌:`POST /auth/wallet/refresh`,传入`{"refreshToken": "..."}`
- 登出:`POST /auth/wallet/logout`
- 方式B限制:仅支持加密货币支付(不支持银行卡支付),仅支持Solana签名

Intent Routing

意图路由

Marketplace

交易市场

Base:
https://api.collectorcrypt.com
All POST endpoints return base64-encoded unsigned Solana transaction(s). Sign with wallet, then broadcast via
/marketplace/broadcast
.
基础URL:
https://api.collectorcrypt.com
所有POST端点返回Base64编码的未签名Solana交易。使用钱包签名后,通过
/marketplace/broadcast
广播。

List an NFT —
POST /marketplace/list

挂单NFT —
POST /marketplace/list

FieldTypeRequiredDescription
wallet
stringyesSeller's Solana address
cardId
stringyesCollectorCrypt card DB ID
nftAddress
stringyesNFT mint address
currency
stringyes
"USDC"
price
numberyesListing price in USDC
tokenStandard
enumno
"Pnft"
or
"Cnft"
userHasSol
booleannoIf
false
, backend pays fees
Errors:
400
(on-chain error),
409
(already listed)
字段类型必填描述
wallet
string卖家的Solana地址
cardId
stringCollectorCrypt卡牌数据库ID
nftAddress
stringNFT铸造地址
currency
string
"USDC"
price
number挂单价格(USDC)
tokenStandard
enum
"Pnft"
"Cnft"
userHasSol
boolean若为
false
,由后端支付手续费
错误码:
400
(链上错误)、
409
(已挂单)

Cancel a Listing —
POST /marketplace/cancel-listing

取消挂单 —
POST /marketplace/cancel-listing

FieldTypeRequiredDescription
wallet
stringyesCaller's wallet
tokenMint
stringyesNFT mint address
seller
stringnoDefaults to
wallet
Errors:
400
(on-chain error),
404
(no listing found)
字段类型必填描述
wallet
string调用者钱包地址
tokenMint
stringNFT铸造地址
seller
string默认值为
wallet
错误码:
400
(链上错误)、
404
(未找到挂单)

Update a Listing Price —
POST /marketplace/update-listing

更新挂单价格 —
POST /marketplace/update-listing

FieldTypeRequiredDescription
wallet
stringyesSeller's wallet
tokenMint
stringyesNFT mint address
newPrice
numberyesUpdated price in USDC
coin
stringyes
"USDC"
Errors:
400
(price unchanged or on-chain error),
404
(no listing found)
字段类型必填描述
wallet
string卖家钱包地址
tokenMint
stringNFT铸造地址
newPrice
number更新后的价格(USDC)
coin
string
"USDC"
错误码:
400
(价格未变更或链上错误)、
404
(未找到挂单)

Buy an NFT —
POST /marketplace/buy

购买NFT —
POST /marketplace/buy

FieldTypeRequiredDescription
wallet
stringyesBuyer's wallet
nftAddress
stringyesNFT mint address
price
numberyesListed price in USDC
currency
stringyes
"USDC"
tokenStandard
enumno
"Pnft"
or
"Cnft"
omit for Metaplex Core listings (
nftStandard: "core"
)
sellerWallet
stringnoResolved from DB if omitted
fundingSource
enumno
"wallet"
(default) or
"escrow"
Success status is
200
OR
201
(live buys return
201
). Response body may be raw base64 text rather than JSON — parse defensively (see Transaction Pattern above).
  • fundingSource: "wallet"
    → single base64 unsigned transaction (JSON
    {"transaction": "..."}
    or plain base64 text)
  • fundingSource: "escrow"
    {"transactions": ["BASE64_WITHDRAW_TX", "BASE64_BUY_TX"], "fundingSource": "escrow"}
Escrow requires minimum
price × 1.02
USDC balance.
Errors:
400
(on-chain error, insufficient escrow),
404
(card/listing not found),
409
(owner changed)
字段类型必填描述
wallet
string买家钱包地址
nftAddress
stringNFT铸造地址
price
number挂单价格(USDC)
currency
string
"USDC"
tokenStandard
enum
"Pnft"
"Cnft"
Metaplex核心版列表(
nftStandard: "core"
)请省略此字段
sellerWallet
string若省略则从数据库解析
fundingSource
enum
"wallet"
(默认)或
"escrow"
成功状态码为
200
201
(实测购买返回
201
)。响应体可能是原始Base64文本而非JSON——需做容错解析(见上文交易流程)。
  • fundingSource: "wallet"
    → 单个Base64未签名交易(JSON格式
    {"transaction": "..."}
    纯Base64文本)
  • fundingSource: "escrow"
    {"transactions": ["BASE64_WITHDRAW_TX", "BASE64_BUY_TX"], "fundingSource": "escrow"}
托管账户需至少有
price × 1.02
数量的USDC余额。
错误码:
400
(链上错误、托管余额不足)、
404
(未找到卡牌/挂单)、
409
(所有者变更)

End-to-End Buy Recipe (tested live)

完整购买流程(已实测)

python
import requests
from core.skill_tools import wallet

BASE = "https://api.collectorcrypt.com"
buyer = "YOUR_WALLET_PUBKEY"
python
import requests
from core.skill_tools import wallet

BASE = "https://api.collectorcrypt.com"
buyer = "YOUR_WALLET_PUBKEY"

1. Find a listed item, cheapest first

1. 找到在售商品,按价格从低到高排序

listings = requests.get(f"{BASE}/marketplace", params={"page": 1, "step": 1, "marketplaceStatus": "Buy now", "orderBy": "listedPriceAsc"} ).json()["filterNFtCard"] item = listings[0] mint = item["nftAddress"] price = float(item["listing"]["price"]) seller = item["owner"]["wallet"] std = item.get("nftStandard") # "core" | "Pnft" | "Cnft"
listings = requests.get(f"{BASE}/marketplace", params={"page": 1, "step": 1, "marketplaceStatus": "Buy now", "orderBy": "listedPriceAsc"} ).json()["filterNFtCard"] item = listings[0] mint = item["nftAddress"] price = float(item["listing"]["price"]) seller = item["owner"]["wallet"] std = item.get("nftStandard") # "core" | "Pnft" | "Cnft"

2. Build buy tx. Omit tokenStandard for Core listings.

2. 构建购买交易。核心版列表省略tokenStandard。

body = {"wallet": buyer, "nftAddress": mint, "price": price, "currency": "USDC", "sellerWallet": seller} if std in ("Pnft", "Cnft"): body["tokenStandard"] = std r = requests.post(f"{BASE}/marketplace/buy", json=body) assert r.status_code in (200, 201) # buy returns 201 try: unsigned = r.json().get("transaction") or r.json().get("serializedTransaction") except Exception: unsigned = r.text # may be raw base64
body = {"wallet": buyer, "nftAddress": mint, "price": price, "currency": "USDC", "sellerWallet": seller} if std in ("Pnft", "Cnft"): body["tokenStandard"] = std r = requests.post(f"{BASE}/marketplace/buy", json=body) assert r.status_code in (200, 201) # 购买返回201 try: unsigned = r.json().get("transaction") or r.json().get("serializedTransaction") except Exception: unsigned = r.text # 可能为原始Base64文本

3. Sign with Starchild wallet (snake_case key)

3. 使用Starchild钱包签名(蛇形命名字段)

signed = wallet.wallet_sol_sign_transaction(unsigned) signed_tx = signed.get("signed_transaction") or signed.get("signedTransaction")
signed = wallet.wallet_sol_sign_transaction(unsigned) signed_tx = signed.get("signed_transaction") or signed.get("signedTransaction")

4. Broadcast

4. 广播交易

b = requests.post(f"{BASE}/marketplace/broadcast", json={"wallet": buyer, "signedTransaction": signed_tx, "nftAddress": mint}) assert b.status_code in (200, 201) and b.json().get("success") # broadcast returns 201 sig = b.json()["signature"]
b = requests.post(f"{BASE}/marketplace/broadcast", json={"wallet": buyer, "signedTransaction": signed_tx, "nftAddress": mint}) assert b.status_code in (200, 201) and b.json().get("success") # 广播返回201 sig = b.json()["signature"]

5. Verify on Solana RPC — the SOURCE OF TRUTH (see below)

5. 通过Solana RPC验证——权威验证方式(见下文)

status = requests.post("https://api.mainnet-beta.solana.com", json={ "jsonrpc": "2.0", "id": 1, "method": "getSignatureStatuses", "params": [[sig], {"searchTransactionHistory": True}]} ).json()["result"]["value"][0] assert status and status["err"] is None and status["confirmationStatus"] == "finalized"

**Verify via Solana RPC signature status, not a marketplace refetch.** Marketplace metadata refresh lags after a buy, and there is no `nftAddress` lookup filter (`search=<mint>` is fuzzy and may not reflect the new owner immediately). The authoritative post-broadcast check is `getSignatureStatuses` on the broadcast `signature`:
```json
{"confirmationStatus": "finalized", "err": null, "status": {"Ok": null}}
err == null
(and
confirmationStatus
of
confirmed
/
finalized
) means the buy settled on-chain. Only fall back to a marketplace refetch for display, never as the success gate.
Regression fixture — a real buy that succeeded (use to smoke-test the flow):
FieldValue
Item2017 #024 POKE BALL PSA 9 — Pokémon Japanese Sun & Moon, Ash vs. Team Rocket Deck Kit
Price19 USDC
NFT mint
4AWreh7pqVb4jhANAXFz2fwSPKqWr5ZAFMgaAFWZS9nk
Seller
FfveJgtFmGPCSazkjicf21WLk9rdUaMsownVVA8LRhwf
Broadcast signature
5SwxeuWGjWbiAFq8YVN3Qsw1PXnKXBakKA2ykgccc78gg6JkGnyi48StezcijXmgWHyGWvojq8TYmTXJoC9XnbjH
Solana status
finalized
,
err: null
status = requests.post("https://api.mainnet-beta.solana.com", json={ "jsonrpc": "2.0", "id": 1, "method": "getSignatureStatuses", "params": [[sig], {"searchTransactionHistory": True}]} ).json()["result"]["value"][0] assert status and status["err"] is None and status["confirmationStatus"] == "finalized"

**通过Solana RPC签名状态验证,而非重新查询市场数据。** 购买后市场元数据刷新存在延迟,且无`nftAddress`精确查询过滤器(`search=<mint>`为模糊查询,可能无法立即反映新所有者)。广播后的权威验证方式是调用`getSignatureStatuses`查询广播的`signature`:
```json
{"confirmationStatus": "finalized", "err": null, "status": {"Ok": null}}
err == null
(且
confirmationStatus
confirmed
/
finalized
)表示购买已在链上完成。仅在展示时才回退到市场数据查询,切勿将其作为成功判断依据。
回归测试示例——已成功的真实购买(用于流程冒烟测试):
字段
商品2017 #024 POKE BALL PSA 9 — 宝可梦日文日月系列,小智vs火箭队卡组套装
价格19 USDC
NFT铸造地址
4AWreh7pqVb4jhANAXFz2fwSPKqWr5ZAFMgaAFWZS9nk
卖家
FfveJgtFmGPCSazkjicf21WLk9rdUaMsownVVA8LRhwf
广播签名
5SwxeuWGjWbiAFq8YVN3Qsw1PXnKXBakKA2ykgccc78gg6JkGnyi48StezcijXmgWHyGWvojq8TYmTXJoC9XnbjH
Solana状态
finalized
,
err: null

Make an Offer —
POST /marketplace/make-offer

发起出价 —
POST /marketplace/make-offer

FieldTypeRequiredDescription
wallet
stringyesBuyer's wallet
cardId
stringyesCollectorCrypt card DB ID
nftAddress
stringyesNFT mint address
price
numberyesOffer price in USDC
currency
stringyes
"USDC"
tokenStandard
enumno
"Pnft"
or
"Cnft"
userHasSol
booleannoBackend fee payer if
false
ownerWallet
stringnoCurrent NFT owner
collectionHash
stringnocNFT collection hash
Errors:
400
(can't determine owner or on-chain error)
字段类型必填描述
wallet
string买家钱包地址
cardId
stringCollectorCrypt卡牌数据库ID
nftAddress
stringNFT铸造地址
price
number出价金额(USDC)
currency
string
"USDC"
tokenStandard
enum
"Pnft"
"Cnft"
userHasSol
boolean若为
false
,由后端支付手续费
ownerWallet
string当前NFT所有者
collectionHash
stringcNFT集合哈希
错误码:
400
(无法确定所有者或链上错误)

Cancel an Offer —
POST /marketplace/cancel-offer

取消出价 —
POST /marketplace/cancel-offer

FieldTypeRequiredDescription
wallet
stringyesBuyer's wallet
nftAddress
stringyesNFT mint address
keepInEscrow
booleannoIf
true
, USDC stays in escrow; default
false
Backend auto-sets
keepInEscrow: true
if wallet has insufficient SOL for rent.
Errors:
404
(no active offer found)
字段类型必填描述
wallet
string买家钱包地址
nftAddress
stringNFT铸造地址
keepInEscrow
boolean若为
true
,USDC保留在托管账户;默认
false
若钱包余额不足以支付租金,后端会自动设置
keepInEscrow: true
错误码:
404
(未找到有效出价)

Update an Offer —
POST /marketplace/update-offer

更新出价 —
POST /marketplace/update-offer

FieldTypeRequiredDescription
wallet
stringyesBuyer's wallet (signer)
nftAddress
stringyesNFT mint address
currency
stringyes
"USDC"
buyer
stringyesBuyer's wallet (typically =
wallet
)
price
numberyesNew offer price in USDC
Important: Escrow must already contain the full new amount — this instruction does NOT transfer additional USDC.
Errors:
400
(price unchanged, no escrow, insufficient balance, on-chain error),
404
(offer not found)
字段类型必填描述
wallet
string买家钱包地址(签名者)
nftAddress
stringNFT铸造地址
currency
string
"USDC"
buyer
string买家钱包地址(通常与
wallet
一致)
price
number更新后的出价金额(USDC)
注意: 托管账户必须已存入足额的新出价金额——此接口不会额外转入USDC。
错误码:
400
(价格未变更、无托管账户、余额不足、链上错误)、
404
(未找到出价)

Accept an Offer —
POST /marketplace/accept-offer

接受出价 —
POST /marketplace/accept-offer

FieldTypeRequiredDescription
wallet
stringyesSeller's wallet (NFT owner)
nftAddress
stringyesNFT mint address
buyer
stringyesBuyer's wallet
currency
stringyes
"USDC"
price
numberyesOffer price in USDC
tokenStandard
enumno
"Pnft"
or
"Cnft"
userHasSol
booleannoBackend fee payer if
false
cNFT edge case: If the cNFT is currently listed, returns:
json
{
  "requiresCancelListing": true,
  "cancelListingTx": "BASE64_CANCEL_LISTING_TX",
  "message": "This cNFT is currently listed. Please sign..."
}
Sign the cancel-listing tx first, then re-call accept-offer.
Errors:
400
(price drift, on-chain error),
404
(offer not found)
字段类型必填描述
wallet
string卖家钱包地址(NFT所有者)
nftAddress
stringNFT铸造地址
buyer
string买家钱包地址
currency
string
"USDC"
price
number出价金额(USDC)
tokenStandard
enum
"Pnft"
"Cnft"
userHasSol
boolean若为
false
,由后端支付手续费
cNFT特殊情况: 若cNFT当前处于挂单状态,返回:
json
{
  "requiresCancelListing": true,
  "cancelListingTx": "BASE64_CANCEL_LISTING_TX",
  "message": "此cNFT当前处于挂单状态,请先签名取消挂单交易..."
}
先签名取消挂单交易,再重新调用接受出价接口。
错误码:
400
(价格变动、链上错误)、
404
(未找到出价)

Browse Listings —
GET /marketplace

浏览挂单 —
GET /marketplace

Public, no auth required. 5-second cache for unauthenticated requests.
Pagination:
ParamTypeDefaultDescription
page
integer11-indexed page
step
integer100Page size (max 100)
Filters (all optional):
ParamTypeDescription
search
stringSubstring match against itemName, nftAddress, gemrateCardName, gradingID. This is the only way to look up by mint — there is NO
nftAddress
query param (
GET /marketplace?nftAddress=<mint>
returns
400
). Use
search=<mint>
instead.
ownerAddress
stringFilter by owner wallet
hideOwned
booleanHide caller's own cards (requires auth)
favoritesOnly
booleanOnly favorited cards (requires auth)
followingOnly
booleanOnly from followed users (requires auth)
followingOf
stringCards owned by users that this wallet follows
marketplaceStatus
CSV
Buy now
,
Has offers
marketplaceSource
CSV
CC
,
ME
marketplaceTags
CSVGlobal tag names (e.g.,
Hot
,
Featured
)
listPriceMin
/
listPriceMax
numberUSDC price range
insuredValueMin
/
insuredValueMax
numberInsured value range
yearMin
/
yearMax
integerCard year range
categories
CSV
Pokemon
,
Baseball
,
Basketball
,
Football
,
Magic The Gathering
,
Yu-Gi-Oh!
,
Lorcana
,
One Piece
,
Non-Sport
, etc.
cardType
CSV
Card
,
Comic
,
ComicRaw
,
Game
,
Merch
,
Raw
,
Sealed
blockchain
CSV
Solana
, others
authenticated
booleanOnly authenticated cards
autographed
booleanOnly autographed cards
burnt
booleanInclude burned cards (default excludes)
grade
stringSubstring match
genericGradeMin
/
genericGradeMax
numberNumeric grade range
gradingCompany
CSV
PSA
,
Beckett
,
CGC
,
SGC
,
TAG
,
CSG
,
KSA
,
PSA/DNA
,
UDA
,
Steiner
,
BBCE
,
Rare Edition
,
Not graded
set
/
format
/
language
/
productCode
stringSubstring match for sealed/comic metadata
pokemon
stringWord-boundary match against gemrateCardName
ccBuyback
booleanOnly cards with active CC buyback
gemrateSet
/
gemrateGrade
/
gemrateCardName
/
gemrateSpecId
/
gemrateParallel
stringGemrate-specific filters
Sort —
orderBy
values:
dateAsc
,
dateDesc
,
nameAsc
,
nameDesc
,
priceAsc
,
priceDesc
(insured value),
yearAsc
,
yearDesc
,
listedDateAsc
,
listedDateDesc
,
listedPriceAsc
,
listedPriceDesc
Default:
listedDateDesc
Response:
json
{
  "filterNFtCard": [
    {
      "id": "card_db_id",
      "itemName": "...",
      "nftAddress": "NFT_MINT_ADDRESS",
      "nftStandard": "Pnft",
      "blockchain": "Solana",
      "category": "Pokemon",
      "type": "Card",
      "year": 1999,
      "grade": "10",
      "gradeNum": 10,
      "gradingCompany": "PSA",
      "gradingID": "...",
      "insuredValue": "...",
      "listing": {
        "price": "25",
        "currency": "USDC",
        "marketplace": "CC",
        "sellerId": "...",
        "createdAt": "ISO_DATE"
      },
      "offers": [{"id": "offer_id"}],
      "owner": {
        "id": "user_id",
        "name": "...",
        "wallet": "OWNER_WALLET_ADDRESS"
      },
      "images": {
        "front": "URL",
        "frontM": "URL",
        "frontS": "URL",
        "back": "URL",
        "backM": "URL",
        "backS": "URL"
      }
    }
  ],
  "findTotal": 1234,
  "total": 50000,
  "totalPages": 25,
  "cardsQtyByCategory": {"Pokemon": 800, "Baseball": 200}
}
  • listing
    is
    null
    when unlisted
  • offers
    is array of active offer IDs
  • findTotal
    = total matching filter;
    total
    = total marketplace cards overall
  • cardsQtyByCategory
    = per-category count (excludes
    categories
    filter)
公开接口,无需认证。未认证请求有5秒缓存。
分页参数:
参数类型默认值描述
page
integer1从1开始的页码
step
integer100每页数量(最大100)
过滤参数(均为可选):
参数类型描述
search
string匹配itemName、nftAddress、gemrateCardName、gradingID的子串。这是唯一通过铸造地址查询的方式——无
nftAddress
查询参数(
GET /marketplace?nftAddress=<mint>
返回
400
)。请使用
search=<mint>
替代。
ownerAddress
string按所有者钱包地址过滤
hideOwned
boolean隐藏调用者自己的卡牌(需认证)
favoritesOnly
boolean仅显示收藏的卡牌(需认证)
followingOnly
boolean仅显示关注用户的卡牌(需认证)
followingOf
string此钱包关注用户所拥有的卡牌
marketplaceStatus
CSV
Buy now
Has offers
marketplaceSource
CSV
CC
ME
marketplaceTags
CSV全局标签名称(例如:
Hot
Featured
listPriceMin
/
listPriceMax
numberUSDC价格范围
insuredValueMin
/
insuredValueMax
number保险价值范围
yearMin
/
yearMax
integer卡牌年份范围
categories
CSV
Pokemon
Baseball
Basketball
Football
Magic The Gathering
Yu-Gi-Oh!
Lorcana
One Piece
Non-Sport
cardType
CSV
Card
Comic
ComicRaw
Game
Merch
Raw
Sealed
blockchain
CSV
Solana
authenticated
boolean仅显示已认证卡牌
autographed
boolean仅显示签名卡牌
burnt
boolean包含已销毁卡牌(默认排除)
grade
string匹配等级子串
genericGradeMin
/
genericGradeMax
number数值等级范围
gradingCompany
CSV
PSA
Beckett
CGC
SGC
TAG
CSG
KSA
PSA/DNA
UDA
Steiner
BBCE
Rare Edition
Not graded
set
/
format
/
language
/
productCode
string匹配密封/漫画元数据的子串
pokemon
string匹配gemrateCardName的词边界
ccBuyback
boolean仅显示有CC回购活动的卡牌
gemrateSet
/
gemrateGrade
/
gemrateCardName
/
gemrateSpecId
/
gemrateParallel
stringGemrate专属过滤参数
排序参数——
orderBy
可选值:
dateAsc
dateDesc
nameAsc
nameDesc
priceAsc
priceDesc
(保险价值)、
yearAsc
yearDesc
listedDateAsc
listedDateDesc
listedPriceAsc
listedPriceDesc
默认值:
listedDateDesc
响应格式:
json
{
  "filterNFtCard": [
    {
      "id": "card_db_id",
      "itemName": "...",
      "nftAddress": "NFT_MINT_ADDRESS",
      "nftStandard": "Pnft",
      "blockchain": "Solana",
      "category": "Pokemon",
      "type": "Card",
      "year": 1999,
      "grade": "10",
      "gradeNum": 10,
      "gradingCompany": "PSA",
      "gradingID": "...",
      "insuredValue": "...",
      "listing": {
        "price": "25",
        "currency": "USDC",
        "marketplace": "CC",
        "sellerId": "...",
        "createdAt": "ISO_DATE"
      },
      "offers": [{"id": "offer_id"}],
      "owner": {
        "id": "user_id",
        "name": "...",
        "wallet": "OWNER_WALLET_ADDRESS"
      },
      "images": {
        "front": "URL",
        "frontM": "URL",
        "frontS": "URL",
        "back": "URL",
        "backM": "URL",
        "backS": "URL"
      }
    }
  ],
  "findTotal": 1234,
  "total": 50000,
  "totalPages": 25,
  "cardsQtyByCategory": {"Pokemon": 800, "Baseball": 200}
}
  • 未挂单时
    listing
    null
  • offers
    为有效出价ID数组
  • findTotal
    = 匹配过滤条件的总数;
    total
    = 市场所有卡牌总数
  • cardsQtyByCategory
    = 各分类卡牌数量(排除
    categories
    过滤条件)

Broadcast a Transaction —
POST /marketplace/broadcast

广播交易 —
POST /marketplace/broadcast

FieldTypeRequiredDescription
wallet
stringyesSigner wallet address
signedTransaction
stringyesBase64-encoded signed transaction
nftAddress
stringnoTriggers metadata refresh after 5s
Success status is
200
OR
201
(live broadcasts return
201
). Response:
json
{
  "success": true,
  "signature": "SOLANA_TRANSACTION_SIGNATURE",
  "message": "Transaction broadcast successfully"
}
Don't treat the
201
as a failure — check
success === true
/ presence of
signature
, not the status code.
Insufficient funds recovery: If broadcast returns
400
with
"code": "INSUFFICIENT_FUNDS_RETRYABLE"
, rebuild the original transaction with
userHasSol: false
so the backend pays fees, then re-sign and re-broadcast.
Validation: Transaction is validated against an allow-list of program IDs before submission.
Errors:
400
(invalid transaction, insufficient funds retryable, submission failure),
403
(program ID not on allow-list)
字段类型必填描述
wallet
string签名者钱包地址
signedTransaction
stringBase64编码的签名交易
nftAddress
string触发5秒后的元数据刷新
成功状态码为
200
201
(实测广播返回
201
)。响应格式:
json
{
  "success": true,
  "signature": "SOLANA_TRANSACTION_SIGNATURE",
  "message": "交易广播成功"
}
请勿将
201
视为失败——检查
success === true
/ 是否存在
signature
/ 是否有交易体,而非状态码。
余额不足恢复: 若广播返回
400
且包含
"code": "INSUFFICIENT_FUNDS_RETRYABLE"
,请重新构建原始交易并设置
userHasSol: false
,由后端支付手续费,然后重新签名并广播。
验证: 交易在提交前会针对允许的程序ID列表进行验证。
错误码:
400
(无效交易、可重试的余额不足、提交失败)、
403
(程序ID不在允许列表中)

Gacha Machine

扭蛋机

Base:
https://gacha.collectorcrypt.com
MethodEndpointPrimary ParamsDescription
GET
/api/status
Machine operational status (open/closed)
GET
/api/stock
NFT inventory counts by rarity per machine
GET
/api/machines
Full config for all machines: pricing,
odds
,
tierRanges
(roll→tier bounds), live
stock
,
instantBuyback
%, and
ev
(rarity-weighted expected insured value)
GET
/api/getNfts
code
,
rarity
,
page
,
limit
Available NFTs with filtering
POST
/api/generatePack
Body:
playerAddress
,
packType
,
turbo
,
altPlayerAddress
Create purchase transaction for one pack
POST
/api/generateYoloPacks
Body:
count
(1-100),
packType
,
playerAddress
,
turbo
,
altPlayerAddress
Batch purchase multiple packs
POST
/api/openPack
Body:
memo
Open purchased pack, receive NFT
POST
/api/buyback
Body:
playerAddress
,
nftAddress
,
altRecipient
Sell NFT back for USDC (within 72 hours)
GET
/api/buyback/check
memo
Check buyback completion status
GET
/api/buyback/available
wallet
,
nft
Pre-check NFT buyback eligibility + refund
amount
(before building a tx)
GET
/api/pack/status
memo
Full pack lifecycle: purchase, NFT send (incl.
prize_tier
,
insured_value
,
vrf_proof
), and buyback history
POST
/api/submitTransaction
Body:
signedTransaction
(base64)
Submit signed transaction to Solana
POST
/api/generateGift
Body:
sender
,
receiver
,
packType
,
count
Gift packs to another wallet
GET
/api/getGifted
wallet
Gift history (sent/received)
GET
/api/purchasedPacks
wallet
Pack counts by type (purchased vs gifted, used vs unused)
POST
/api/generatePurchasedPack
Body:
publicKey
,
packType
,
ledger
Create sign challenge for opening gifted/purchased packs
POST
/api/usePurchasedPack
Body:
nonce
,
packType
,
publicKey
,
signature
/
transactionSignature
,
ledger
Consume purchased pack after signing, returns memo
GET
/api/getAllWinners
timestamp
,
slug
,
epic
,
packType
,
count
Recent winners with optional filtering
GET
/api/vrf/verify
memo
Verify VRF proof for a roll
基础URL:
https://gacha.collectorcrypt.com
方法端点主要参数描述
GET
/api/status
机器运行状态(开启/关闭)
GET
/api/stock
各稀有度NFT的库存数量
GET
/api/machines
所有机器的完整配置:定价、
odds
tierRanges
(抽取→等级区间)、实时
stock
instantBuyback
百分比、
ev
(稀有度加权的预期保险价值)
GET
/api/getNfts
code
,
rarity
,
page
,
limit
可筛选的可用NFT列表
POST
/api/generatePack
请求体:
playerAddress
,
packType
,
turbo
,
altPlayerAddress
创建单包购买交易
POST
/api/generateYoloPacks
请求体:
count
(1-100),
packType
,
playerAddress
,
turbo
,
altPlayerAddress
批量购买多包
POST
/api/openPack
请求体:
memo
开启已购买的卡包,获取NFT
POST
/api/buyback
请求体:
playerAddress
,
nftAddress
,
altRecipient
将NFT卖回换取USDC(72小时内有效)
GET
/api/buyback/check
memo
检查回购完成状态
GET
/api/buyback/available
wallet
,
nft
预检查NFT回购资格+退款金额(构建回购交易前)
GET
/api/pack/status
memo
卡包全生命周期:购买、NFT发放(包含
prize_tier
insured_value
vrf_proof
)、回购历史
POST
/api/submitTransaction
请求体:
signedTransaction
(Base64)
将签名交易提交至Solana
POST
/api/generateGift
请求体:
sender
,
receiver
,
packType
,
count
向其他钱包赠送卡包
GET
/api/getGifted
wallet
赠送历史(发送/接收)
GET
/api/purchasedPacks
wallet
卡包数量统计(购买/赠送、已使用/未使用)
POST
/api/generatePurchasedPack
请求体:
publicKey
,
packType
,
ledger
为开启赠送/购买的卡包创建签名挑战
POST
/api/usePurchasedPack
请求体:
nonce
,
packType
,
publicKey
,
signature
/
transactionSignature
,
ledger
签名后使用已购买的卡包,返回备注
GET
/api/getAllWinners
timestamp
,
slug
,
epic
,
packType
,
count
近期中奖记录(可筛选)
GET
/api/vrf/verify
memo
验证抽取的VRF证明

Gacha Response Shapes

扭蛋响应格式

generatePack response:
json
{"memo": "slug-uuid", "transaction": "base64_encoded_transaction"}
The
memo
is
cc-<uuid>
(there is no API key, so no partner slug prefix applies). Body is
{playerAddress, packType?, turbo?, altPlayerAddress?}
packType
defaults to
pokemon_50
(use
pokemon_250
for legendary).
openPack response (normal win):
json
{
  "success": true,
  "transactionSignature": "...",
  "nft_address": "...",
  "nftWon": {
    "content": {
      "metadata": {"name": "...", "description": "...", "attributes": []}
    }
  },
  "points": 0,
  "roll": 12345678,
  "rarity": "Epic|Rare|Uncommon|Common"
}
roll
is an integer in the range 1–100,000,000 (NOT a fraction).
nftWon
is nested under
content.metadata
— there is no top-level
name
/
image
.
openPack response (turbo-mode buyback, Common roll): adds
"code": "TURBO_MODE_BUYBACK"
and
"buybackAmount": 42500000
(USDC base units) — the Common NFT is auto-sold instead of delivered.
openPack response (payment not yet confirmed):
json
{"success": true, "code": "WAITING_FOR_WEBHOOK", "memo": "slug-uuid-string"}
Do NOT assume an NFT was delivered on this response — poll
GET /api/pack/status?memo=...
(or retry
openPack
) until the win resolves.
openPack is idempotent: calling it again on an already-opened pack returns the original result (same
transactionSignature
,
nftWon
,
points
,
rarity
) — safe to retry.
Prize tier mapping (
pack/status
and
getAllWinners
return numeric
prize_tier
;
openPack
returns human-readable
rarity
):
1
= Epic,
2
= Rare,
3
= Uncommon,
4
= Common.
buyback response:
json
{
  "serializedTransaction": "base64",
  "refundAmount": 42500000,
  "memo": "..."
}
generatePack响应:
json
{"memo": "slug-uuid", "transaction": "base64_encoded_transaction"}
memo
格式为
cc-<uuid>
(无API密钥,因此无合作伙伴slug前缀)。请求体为
{playerAddress, packType?, turbo?, altPlayerAddress?}
packType
默认值为
pokemon_50
(传奇卡包使用
pokemon_250
)。
openPack响应(普通中奖):
json
{
  "success": true,
  "transactionSignature": "...",
  "nft_address": "...",
  "nftWon": {
    "content": {
      "metadata": {"name": "...", "description": "...", "attributes": []}
    }
  },
  "points": 0,
  "roll": 12345678,
  "rarity": "Epic|Rare|Uncommon|Common"
}
roll
为1–100,000,000范围内的整数(不是分数)。
nftWon
嵌套在
content.metadata
下——无顶层
name
/
image
字段。
openPack响应( turbo模式回购,普通稀有度): 新增
"code": "TURBO_MODE_BUYBACK"
"buybackAmount": 42500000
(USDC最小单位)——普通NFT会自动卖出而非发放给用户。
openPack响应(支付未确认):
json
{"success": true, "code": "WAITING_FOR_WEBHOOK", "memo": "slug-uuid-string"}
收到此响应时请勿默认已发放NFT——轮询
GET /api/pack/status?memo=...
(或重试
openPack
)直到中奖结果确定。
openPack接口是幂等的: 对已开启的卡包再次调用会返回原始结果(相同的
transactionSignature
nftWon
points
rarity
)——可安全重试。
奖励等级映射
pack/status
getAllWinners
返回数字
prize_tier
openPack
返回可读的
rarity
):
1
= Epic(史诗),
2
= Rare(稀有),
3
= Uncommon(中稀有),
4
= Common(普通)。
buyback响应:
json
{
  "serializedTransaction": "base64",
  "refundAmount": 42500000,
  "memo": "..."
}

Shipping / Vault Redemption

物流/存管兑换

Base:
https://api.collectorcrypt.com
MethodEndpointPrimary ParamsDescription
POST
/redeem/estimate
Body:
nftAddresses
,
shippingAddressId
Fee estimate without creating shipment; returns
price
,
insurancePrice
,
feesPrice
,
shippingPrice
,
total
,
numberOfCards
,
breakdown
POST
/redeem/prepare
Body:
nftAddresses
,
shippingAddressId
,
coin
(
USDC
|
USDT
),
deliveryCompany
,
comment
,
insurance
Create pending shipment, returns unsigned transactions
POST
/blockchain/:outboundShipmentId/burn
Body:
transactions
(base64 signed),
evmTransactions
Broadcast signed burn transactions; returns
id
,
status
,
transactionUrls
GET
/outbound-shipment
List user shipments
GET
/outbound-shipment/:id
id
Get specific shipment status
基础URL:
https://api.collectorcrypt.com
方法端点主要参数描述
POST
/redeem/estimate
请求体:
nftAddresses
,
shippingAddressId
估算费用(不创建运单);返回
price
,
insurancePrice
,
feesPrice
,
shippingPrice
,
total
,
numberOfCards
,
breakdown
POST
/redeem/prepare
请求体:
nftAddresses
,
shippingAddressId
,
coin
(
USDC
|
USDT
),
deliveryCompany
,
comment
,
insurance
创建待处理运单,返回未签名交易
POST
/blockchain/:outboundShipmentId/burn
请求体:
transactions
(Base64签名交易),
evmTransactions
广播签名的销毁交易;返回
id
,
status
,
transactionUrls
GET
/outbound-shipment
列出用户运单
GET
/outbound-shipment/:id
id
获取指定运单状态

Shipping Address Management

收货地址管理

MethodEndpointDescription
GET
/shipping-address
List saved addresses
GET
/shipping-address/:id
Get specific address
POST
/shipping-address/create
Create new address
PATCH
/shipping-address/update/:id
Update address
DELETE
/shipping-address/:id
Delete address
方法端点描述
GET
/shipping-address
列出已保存的地址
GET
/shipping-address/:id
获取指定地址
POST
/shipping-address/create
创建新地址
PATCH
/shipping-address/update/:id
更新地址
DELETE
/shipping-address/:id
删除地址

Shipping Rates

运费标准

RegionBaseEach AdditionalSignaturePack Surcharge
USA$5.99$3.00+$3.00 (value >= $500)$0.18/pack
Canada$20.99$3.00Included$0.25/pack
Europe$29.99$3.00Included$0.25/pack
Australia/NZ$34.99$3.00Included$0.25/pack
Rest of World$34.99$3.00Included$0.25/pack
Insurance auto-applies at 0.5% of declared value when package exceeds $5,000.
地区基础运费额外每张签名费包装附加费
美国$5.99$3.00+$3.00(价值≥$500)$0.18/包
加拿大$20.99$3.00包含在内$0.25/包
欧洲$29.99$3.00包含在内$0.25/包
澳大利亚/新西兰$34.99$3.00包含在内$0.25/包
其他地区$34.99$3.00包含在内$0.25/包
当包裹价值超过$5,000时,自动按申报价值的0.5%收取保险费。

Redeem/Prepare Response Shape

Redeem/Prepare响应格式

json
{
  "outboundShipmentId": "shipment_...",
  "transactions": ["<base64-unsigned-tx>"],
  "evmTransactions": [],
  "totalCost": 14.99,
  "submitUrl": "/blockchain/shipment_.../burn",
  "breakdown": {
    "region": "USA",
    "declaredValue": 700,
    "numberOfCards": 10,
    "lines": [
      {"code": "shipping_base", "label": "Base shipping (USA, first card)", "amount": 5.99, "unitPrice": 5.99}
    ]
  }
}
json
{
  "outboundShipmentId": "shipment_...",
  "transactions": ["<base64-unsigned-tx>"],
  "evmTransactions": [],
  "totalCost": 14.99,
  "submitUrl": "/blockchain/shipment_.../burn",
  "breakdown": {
    "region": "USA",
    "declaredValue": 700,
    "numberOfCards": 10,
    "lines": [
      {"code": "shipping_base", "label": "基础运费(美国,首张卡牌)", "amount": 5.99, "unitPrice": 5.99}
    ]
  }
}

Auth (SIWS — Sign-In With Solana)

认证(SIWS — Solana登录)

Base:
https://api.collectorcrypt.com
MethodEndpointPrimary ParamsDescription
POST
/auth/wallet/nonce
Body:
wallet
,
partnerAppId
,
domain
,
uri
Get nonce + EIP-4361 signing message
POST
/auth/wallet/verify
Body:
message
,
signature
(base58 ed25519)
Exchange signature for access + refresh tokens
POST
/auth/wallet/refresh
Body:
refreshToken
Refresh expired access token
POST
/auth/wallet/logout
Body:
refreshToken
(+ access token in
Authorization
header)
Invalidate tokens
基础URL:
https://api.collectorcrypt.com
方法端点主要参数描述
POST
/auth/wallet/nonce
请求体:
wallet
,
partnerAppId
,
domain
,
uri
获取随机数+EIP-4361签名消息
POST
/auth/wallet/verify
请求体:
message
,
signature
(base58 ed25519)
用签名换取访问+刷新令牌
POST
/auth/wallet/refresh
请求体:
refreshToken
刷新过期的访问令牌
POST
/auth/wallet/logout
请求体:
refreshToken
(+
Authorization
请求头中的访问令牌)
使令牌失效

Swap Program (On-Chain)

互换程序(链上)

Program ID:
CCSwaptcDXtfjyRMYBqavqBwiW162yXFAJrXN53UuENC
The swap program is an Anchor-based Solana smart contract. Trades follow this lifecycle:
Open → Approved → Executed → Settled → (Closed)
         ↑            ↑
    cancel_trade  cancel_trade
Instructions:
InstructionDescription
create_trade
Initialize trade between two wallets
approve_trade
Signal readiness (both parties must approve)
execute_trade
Commit to execution (both parties must execute)
cancel_trade
Abort open or approved trades
execute_nft_batch
Transfer standard NFTs into/out of escrow
execute_pnft_batch
Transfer programmable NFTs
execute_cnft_batch
Transfer compressed NFTs
execute_token_batch
Transfer SPL tokens
mark_trade_settled
Backend confirmation of completion
close_trade
Final cleanup and rent refund
程序ID:
CCSwaptcDXtfjyRMYBqavqBwiW162yXFAJrXN53UuENC
互换程序是基于Anchor的Solana智能合约。交易遵循以下生命周期:
开启 → 已批准 → 已执行 → 已结算 → (已关闭)
         ↑            ↑
    取消交易  取消交易
指令:
指令描述
create_trade
初始化两个钱包间的交易
approve_trade
表示准备就绪(双方均需批准)
execute_trade
提交执行(双方均需执行)
cancel_trade
中止开启或已批准的交易
execute_nft_batch
转移标准NFT进出托管合约
execute_pnft_batch
转移可编程NFT
execute_cnft_batch
转移压缩NFT
execute_token_batch
转移SPL代币
mark_trade_settled
后端确认交易完成
close_trade
最终清理并退还租金

Marketplace On-Chain Details

交易市场链上细节

Account Structure

账户结构

AccountPurpose
MarketSingleton PDA — config (admin keys, fees, treasury, paused status)
ListingSale info indexed by asset ID + seller, with delegation authority
OfferBuyer offer details with independent escrow backing
UserEscrowPer-user USDC deposit tracking for offer collateral
账户用途
Market单例PDA — 配置(管理员密钥、手续费、国库、暂停状态)
Listing按资产ID+卖家索引的售卖信息,包含委托权限
Offer买家出价详情,包含独立托管抵押
UserEscrow每个用户的USDC存款跟踪,用于出价抵押

Fee Structure

手续费结构

Platform fee: 200 basis points (2%). Configurable 0–200 bps.
fee = floor(price * platform_fee_bps / 10000)
Uses u128 intermediate precision to prevent overflow.
平台手续费:200个基点(2%)。可配置范围0–200个基点。
fee = floor(price * platform_fee_bps / 10000)
使用u128中间精度防止溢出。

Security Properties

安全特性

  • Non-custodial listings — NFTs remain in seller wallets using delegation, not escrow transfers
  • Frontrun prevention
    expected_price
    parameters validate on-chain prices match expectations
  • Self-trade blocking — enforced
    seller != buyer
    validation
  • PDA determinism — fixed seed schemes prevent unauthorized account substitution
  • Broadcast allow-list — transactions validated against approved program IDs before submission
  • 非托管挂单 — NFT通过委托权限保留在卖家钱包中,无需转移至托管合约
  • 防抢先交易
    expected_price
    参数验证链上价格与预期一致
  • 防止自交易 — 强制校验
    seller != buyer
  • PDA确定性 — 固定种子方案防止未授权账户替换
  • 广播允许列表 — 交易提交前验证是否属于批准的程序ID

Error Handling

错误处理

Success is any 2xx — accept
200
AND
201
.
Several marketplace write endpoints (
/marketplace/buy
,
/marketplace/broadcast
) return
201
on success. Never gate on
status == 200
; check for a 2xx status plus
success: true
/ a
signature
/ a transaction body.
All APIs return errors in a standard shape:
json
{"statusCode": 400, "message": "human-readable error", "error": "Bad Request"}
StatusMeaning
400
Invalid input, on-chain failure, price mismatch, insufficient escrow, signing failure
401
Invalid or expired token
403
Access denied, program ID outside broadcast allow-list
404
Card, NFT, listing, offer, or address not found
409
Conflict (already listed, owner changed, wallet linked to Privy account)
429
Rate limit exceeded
500
Machine empty, too many packs open, or processing error
所有2xx状态码均为成功——接受
200
201
多个市场写端点(
/marketplace/buy
/marketplace/broadcast
)成功时返回
201
。切勿仅校验
status == 200
;检查2xx状态码+
success: true
/
signature
/ 交易体。
所有API返回标准格式错误:
json
{"statusCode": 400, "message": "可读错误信息", "error": "Bad Request"}
状态码含义
400
无效输入、链上失败、价格不匹配、托管余额不足、签名失败
401
令牌无效或过期
403
访问被拒绝、程序ID不在广播允许列表中
404
未找到卡牌、NFT、挂单、出价或地址
409
冲突(已挂单、所有者变更、钱包已关联Privy账户)
429
请求频率超限
500
机器库存为空、开启卡包过多或处理错误

Safety Notes

注意事项

  • Marketplace prices are in whole USDC.
    "price": 25
    means $25.00 USDC.
  • Buy/broadcast succeed with HTTP
    201
    — accept any 2xx, parse the body which may be raw base64 (not JSON), and verify the result on Solana RPC (
    getSignatureStatuses
    ), not via a marketplace refetch. See the End-to-End Buy Recipe.
  • Metaplex Core (
    nftStandard: "core"
    ) is common
    — omit
    tokenStandard
    for those; only send
    "Pnft"
    /
    "Cnft"
    when the asset really is one.
  • Starchild wallet signing returns
    signed_transaction
    (snake_case) — read that (or the camelCase fallback) before broadcasting.
  • Gacha
    refundAmount
    is in USDC lamports.
    42,500,000 = $42.50 USDC (1 USDC = 1,000,000 lamports).
  • Gacha buyback window is 72 hours. After that, the NFT cannot be sold back to the machine.
  • Buyback refund is a per-machine percentage of insured/market value (not the purchase price). The rate is exposed as
    instantBuyback
    in
    GET /api/machines
    (e.g.
    85
    = 85%); don't assume a fixed global rate. Use
    GET /api/buyback/available?wallet=…&nft=…
    to get the exact refund
    amount
    before building a buyback tx (USDC base units, already adjusted for the machine's buyback % and capped at 40,000 USDC).
  • Non-custodial listings — NFTs stay in seller wallets via delegation. If a seller transfers an NFT without canceling the listing, the listing becomes invalid. Backend auto-cancellation is not guaranteed.
  • Escrow must be pre-funded for offer updates
    update-offer
    does NOT transfer additional USDC; the escrow must already contain the full new amount.
  • cNFT accept-offer may require two transactions — if the cNFT is currently listed, the API returns a cancel-listing tx that must be signed first.
  • Shipping creates real physical shipments. Always confirm address and NFT selection with the user before calling
    /redeem/prepare
    .
  • Signed transactions are irreversible. Verify NFT address, price, and wallet before broadcasting.
  • VRF rolls are final. Once a pack is opened, the result cannot be changed or re-rolled.
  • Track B (SIWS) is crypto-only. No card payment support. Wallets already linked to Privy accounts will get
    409 Conflict
    .
  • userHasSol: false
    — use this flag when the user's wallet lacks SOL for transaction fees; the backend will pay gas. Also use it to recover from
    INSUFFICIENT_FUNDS_RETRYABLE
    broadcast errors.
  • 市场价格为整数USDC。
    "price": 25
    代表25.00 USDC。
  • 购买/广播成功时返回HTTP
    201
    — 接受所有2xx状态码,解析可能为原始Base64的响应体,并通过Solana RPC(
    getSignatureStatuses
    )验证结果,而非重新查询市场数据。详见完整购买流程。
  • Metaplex核心版(
    nftStandard: "core"
    )较为常见
    — 此类资产请省略
    tokenStandard
    ;仅当资产确实为pNFT或cNFT时才传入
    "Pnft"
    /
    "Cnft"
  • Starchild钱包签名返回
    signed_transaction
    (蛇形命名)——广播前优先读取此字段(或驼峰命名的备选字段)。
  • 扭蛋
    refundAmount
    为USDC最小单位。
    42,500,000 = 42.50 USDC(1 USDC = 1,000,000最小单位)。
  • 扭蛋回购窗口期为72小时。 超过此时间后,NFT无法卖回给机器。
  • 回购退款为机器设定的保险/市场价值百分比(不是购买价格)。回购率在
    GET /api/machines
    中以
    instantBuyback
    字段暴露(例如
    85
    代表85%);请勿假设固定全局回购率。构建回购交易前,使用
    GET /api/buyback/available?wallet=…&nft=…
    获取精确退款金额(USDC最小单位,已根据机器回购率调整,上限为40,000 USDC)。
  • 非托管挂单 — NFT通过委托权限保留在卖家钱包中。若卖家未取消挂单就转移NFT,挂单会失效。后端不保证自动取消挂单。
  • 更新出价需预先充值托管账户
    update-offer
    不会额外转入USDC;托管账户必须已存入足额的新出价金额。
  • 接受cNFT出价可能需要两步交易 — 若cNFT当前处于挂单状态,API会返回取消挂单交易,需先签名此交易。
  • 物流会创建真实实体运单。 调用
    /redeem/prepare
    前,请务必与用户确认地址和NFT选择。
  • 签名交易不可撤销。 广播前请验证NFT地址、价格和钱包信息。
  • VRF抽取结果不可更改。 卡包开启后,结果无法修改或重新抽取。
  • 方式B(SIWS)仅支持加密货币支付。 不支持银行卡支付。已关联Privy账户的钱包会返回
    409 Conflict
  • userHasSol: false
    — 当用户钱包余额不足支付交易手续费时使用此标志;后端会支付Gas费。也可用于从
    INSUFFICIENT_FUNDS_RETRYABLE
    广播错误中恢复。

Known Limitations

已知限制

  • Marketplace uses delegation, not escrow — if a seller transfers their NFT elsewhere without canceling, the listing breaks silently. Always check listing validity before buying.
  • Field names differ across endpoints — listing uses
    nftAddress
    , cancel-listing uses
    tokenMint
    , update-listing uses
    tokenMint
    +
    newPrice
    +
    coin
    . Always check the exact field names per endpoint above.
  • Gacha
    packType
    codes
    are machine-specific (e.g.,
    pokemon_50
    ,
    pokemon_250
    ). Use
    GET /api/machines
    to discover available pack types and current pricing.
  • No keyword search for gacha NFTs — use
    GET /api/getNfts
    with
    code
    and
    rarity
    filters, or browse via
    GET /api/machines
    .
  • Swap is on-chain only — no REST API wrapper; interact via Solana transactions against the Anchor program IDL.
  • Access tokens expire in 15 minutes (Track B / SIWS) — implement refresh token rotation for long sessions.
  • eBay Bidder has no public API documentation — it's a consumer-facing tool at
    https://bid.collectorcrypt.com
    .
  • Launchpads are admin-managed drop pages — no public API for creating or configuring them.
  • Browse listings cache — unauthenticated GET requests are cached for 5 seconds.
  • 市场使用委托而非托管 — 若卖家未取消挂单就将NFT转移至其他地址,挂单会静默失效。购买前请始终检查挂单有效性。
  • 各端点字段名称不一致 — 挂单使用
    nftAddress
    ,取消挂单使用
    tokenMint
    ,更新挂单使用
    tokenMint
    +
    newPrice
    +
    coin
    。请始终参考上文各端点的精确字段名称。
  • 扭蛋
    packType
    代码为机器专属
    (例如
    pokemon_50
    pokemon_250
    )。使用
    GET /api/machines
    查询可用卡包类型和当前定价。
  • 扭蛋NFT无关键词搜索 — 使用
    GET /api/getNfts
    配合
    code
    rarity
    过滤,或通过
    GET /api/machines
    浏览。
  • 互换仅支持链上操作 — 无REST API封装;需通过Solana交易与Anchor程序IDL交互。
  • 访问令牌有效期为15分钟(方式B/SIWS)——长会话需实现刷新令牌轮换。
  • eBay Bidder无公开API文档 — 这是面向消费者的工具,地址为
    https://bid.collectorcrypt.com
  • Launchpads为管理员管理的发布页面 — 无创建或配置的公开API。
  • 浏览挂单缓存 — 未认证GET请求有5秒缓存。