skillZs
LIVE SKILL TAGS
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
REAL INSTALL DATA
← back to all skills
starchild-ai-agent/official-skills134 installs

collectorcrypt

CollectorCrypt: physical trading card NFTs on Solana — marketplace, gacha packs, vault redemption, P2P swaps. Use when buying/selling/trading collectible card NFTs, opening mystery packs, redeeming NFTs for physical cards, or swapping assets on Solana (e.g. list Pokemon card for 50 USDC, open gacha pack, ship card to address, swap NFTs peer-to-peer).

How do I install this agent skill?

npx skills add https://github.com/starchild-ai-agent/official-skills --skill collectorcrypt
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill provides a technical interface for interacting with the CollectorCrypt marketplace and gacha system on the Solana blockchain. It includes detailed instructions for trading, gacha mechanics, and physical card redemptions while ensuring secure transaction handling via standard wallet signing tools.

  • Socketwarn

    1 alert: gptSecurity

  • Snykfail

    Risk: HIGH · 2 issues

What does this agent skill do?

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

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 Programs

ProgramID
MarketplaceCcmRKTuZCGJBWQwMHvDYApBRvSZNHqGJXkznqpDTSQUr
SwapCCSwaptcDXtfjyRMYBqavqBwiW162yXFAJrXN53UuENC

NFT Types Supported

  • 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.

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).

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:

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:

from core.skill_tools import wallet
signed = wallet.wallet_sol_sign_transaction(unsigned_tx)
# → {"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.

Gacha Rarity Tiers

RarityProbability
Epic1%
Rare (High)4%
Uncommon (Mid)15%
Common (Low)80%

VRF (Verifiable Random Function)

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.

How to Call

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

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.

# 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 Demohttps://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).

Marketplace API — No Auth for Reads

Public GET endpoints (browse listings) need no authentication. Write endpoints return unsigned transactions for wallet signing — no API key involved.

# Browse listings — no auth, 5s cache for unauthenticated requests
curl -s "https://api.collectorcrypt.com/marketplace?page=1&step=20&categories=Pokemon"

# Create listing — returns base64 unsigned transaction
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
  }'

Shipping API — Two Auth Tracks

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
# Step 1: Get nonce
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
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": ...}

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

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.

List an NFT — POST /marketplace/list

FieldTypeRequiredDescription
walletstringyesSeller's Solana address
cardIdstringyesCollectorCrypt card DB ID
nftAddressstringyesNFT mint address
currencystringyes"USDC"
pricenumberyesListing price in USDC
tokenStandardenumno"Pnft" or "Cnft"
userHasSolbooleannoIf false, backend pays fees

Errors: 400 (on-chain error), 409 (already listed)

Cancel a Listing — POST /marketplace/cancel-listing

FieldTypeRequiredDescription
walletstringyesCaller's wallet
tokenMintstringyesNFT mint address
sellerstringnoDefaults to wallet

Errors: 400 (on-chain error), 404 (no listing found)

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

FieldTypeRequiredDescription
walletstringyesSeller's wallet
tokenMintstringyesNFT mint address
newPricenumberyesUpdated price in USDC
coinstringyes"USDC"

Errors: 400 (price unchanged or on-chain error), 404 (no listing found)

Buy an NFT — POST /marketplace/buy

FieldTypeRequiredDescription
walletstringyesBuyer's wallet
nftAddressstringyesNFT mint address
pricenumberyesListed price in USDC
currencystringyes"USDC"
tokenStandardenumno"Pnft" or "Cnft"omit for Metaplex Core listings (nftStandard: "core")
sellerWalletstringnoResolved from DB if omitted
fundingSourceenumno"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)

End-to-End Buy Recipe (tested live)

import requests
from core.skill_tools import wallet

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

# 1. Find a listed item, cheapest first
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.
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

# 3. Sign with Starchild wallet (snake_case key)
signed = wallet.wallet_sol_sign_transaction(unsigned)
signed_tx = signed.get("signed_transaction") or signed.get("signedTransaction")

# 4. Broadcast
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"]

# 5. Verify on Solana RPC — the SOURCE OF TRUTH (see below)
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:

{"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 mint4AWreh7pqVb4jhANAXFz2fwSPKqWr5ZAFMgaAFWZS9nk
SellerFfveJgtFmGPCSazkjicf21WLk9rdUaMsownVVA8LRhwf
Broadcast signature5SwxeuWGjWbiAFq8YVN3Qsw1PXnKXBakKA2ykgccc78gg6JkGnyi48StezcijXmgWHyGWvojq8TYmTXJoC9XnbjH
Solana statusfinalized, err: null

Make an Offer — POST /marketplace/make-offer

FieldTypeRequiredDescription
walletstringyesBuyer's wallet
cardIdstringyesCollectorCrypt card DB ID
nftAddressstringyesNFT mint address
pricenumberyesOffer price in USDC
currencystringyes"USDC"
tokenStandardenumno"Pnft" or "Cnft"
userHasSolbooleannoBackend fee payer if false
ownerWalletstringnoCurrent NFT owner
collectionHashstringnocNFT collection hash

Errors: 400 (can't determine owner or on-chain error)

Cancel an Offer — POST /marketplace/cancel-offer

FieldTypeRequiredDescription
walletstringyesBuyer's wallet
nftAddressstringyesNFT mint address
keepInEscrowbooleannoIf 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)

Update an Offer — POST /marketplace/update-offer

FieldTypeRequiredDescription
walletstringyesBuyer's wallet (signer)
nftAddressstringyesNFT mint address
currencystringyes"USDC"
buyerstringyesBuyer's wallet (typically = wallet)
pricenumberyesNew 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)

Accept an Offer — POST /marketplace/accept-offer

FieldTypeRequiredDescription
walletstringyesSeller's wallet (NFT owner)
nftAddressstringyesNFT mint address
buyerstringyesBuyer's wallet
currencystringyes"USDC"
pricenumberyesOffer price in USDC
tokenStandardenumno"Pnft" or "Cnft"
userHasSolbooleannoBackend fee payer if false

cNFT edge case: If the cNFT is currently listed, returns:

{
  "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)

Browse Listings — GET /marketplace

Public, no auth required. 5-second cache for unauthenticated requests.

Pagination:

ParamTypeDefaultDescription
pageinteger11-indexed page
stepinteger100Page size (max 100)

Filters (all optional):

ParamTypeDescription
searchstringSubstring 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.
ownerAddressstringFilter by owner wallet
hideOwnedbooleanHide caller's own cards (requires auth)
favoritesOnlybooleanOnly favorited cards (requires auth)
followingOnlybooleanOnly from followed users (requires auth)
followingOfstringCards owned by users that this wallet follows
marketplaceStatusCSVBuy now, Has offers
marketplaceSourceCSVCC, ME
marketplaceTagsCSVGlobal tag names (e.g., Hot, Featured)
listPriceMin / listPriceMaxnumberUSDC price range
insuredValueMin / insuredValueMaxnumberInsured value range
yearMin / yearMaxintegerCard year range
categoriesCSVPokemon, Baseball, Basketball, Football, Magic The Gathering, Yu-Gi-Oh!, Lorcana, One Piece, Non-Sport, etc.
cardTypeCSVCard, Comic, ComicRaw, Game, Merch, Raw, Sealed
blockchainCSVSolana, others
authenticatedbooleanOnly authenticated cards
autographedbooleanOnly autographed cards
burntbooleanInclude burned cards (default excludes)
gradestringSubstring match
genericGradeMin / genericGradeMaxnumberNumeric grade range
gradingCompanyCSVPSA, Beckett, CGC, SGC, TAG, CSG, KSA, PSA/DNA, UDA, Steiner, BBCE, Rare Edition, Not graded
set / format / language / productCodestringSubstring match for sealed/comic metadata
pokemonstringWord-boundary match against gemrateCardName
ccBuybackbooleanOnly cards with active CC buyback
gemrateSet / gemrateGrade / gemrateCardName / gemrateSpecId / gemrateParallelstringGemrate-specific filters

Sort — orderBy values: dateAsc, dateDesc, nameAsc, nameDesc, priceAsc, priceDesc (insured value), yearAsc, yearDesc, listedDateAsc, listedDateDesc, listedPriceAsc, listedPriceDesc Default: listedDateDesc

Response:

{
  "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)

Broadcast a Transaction — POST /marketplace/broadcast

FieldTypeRequiredDescription
walletstringyesSigner wallet address
signedTransactionstringyesBase64-encoded signed transaction
nftAddressstringnoTriggers metadata refresh after 5s

Success status is 200 OR 201 (live broadcasts return 201). Response:

{
  "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)

Gacha Machine

Base: https://gacha.collectorcrypt.com

MethodEndpointPrimary ParamsDescription
GET/api/statusMachine operational status (open/closed)
GET/api/stockNFT inventory counts by rarity per machine
GET/api/machinesFull config for all machines: pricing, odds, tierRanges (roll→tier bounds), live stock, instantBuyback %, and ev (rarity-weighted expected insured value)
GET/api/getNftscode, rarity, page, limitAvailable NFTs with filtering
POST/api/generatePackBody: playerAddress, packType, turbo, altPlayerAddressCreate purchase transaction for one pack
POST/api/generateYoloPacksBody: count (1-100), packType, playerAddress, turbo, altPlayerAddressBatch purchase multiple packs
POST/api/openPackBody: memoOpen purchased pack, receive NFT
POST/api/buybackBody: playerAddress, nftAddress, altRecipientSell NFT back for USDC (within 72 hours)
GET/api/buyback/checkmemoCheck buyback completion status
GET/api/buyback/availablewallet, nftPre-check NFT buyback eligibility + refund amount (before building a tx)
GET/api/pack/statusmemoFull pack lifecycle: purchase, NFT send (incl. prize_tier, insured_value, vrf_proof), and buyback history
POST/api/submitTransactionBody: signedTransaction (base64)Submit signed transaction to Solana
POST/api/generateGiftBody: sender, receiver, packType, countGift packs to another wallet
GET/api/getGiftedwalletGift history (sent/received)
GET/api/purchasedPackswalletPack counts by type (purchased vs gifted, used vs unused)
POST/api/generatePurchasedPackBody: publicKey, packType, ledgerCreate sign challenge for opening gifted/purchased packs
POST/api/usePurchasedPackBody: nonce, packType, publicKey, signature/transactionSignature, ledgerConsume purchased pack after signing, returns memo
GET/api/getAllWinnerstimestamp, slug, epic, packType, countRecent winners with optional filtering
GET/api/vrf/verifymemoVerify VRF proof for a roll

Gacha Response Shapes

generatePack response:

{"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):

{
  "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):

{"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:

{
  "serializedTransaction": "base64",
  "refundAmount": 42500000,
  "memo": "..."
}

Shipping / Vault Redemption

Base: https://api.collectorcrypt.com

MethodEndpointPrimary ParamsDescription
POST/redeem/estimateBody: nftAddresses, shippingAddressIdFee estimate without creating shipment; returns price, insurancePrice, feesPrice, shippingPrice, total, numberOfCards, breakdown
POST/redeem/prepareBody: nftAddresses, shippingAddressId, coin (USDC|USDT), deliveryCompany, comment, insuranceCreate pending shipment, returns unsigned transactions
POST/blockchain/:outboundShipmentId/burnBody: transactions (base64 signed), evmTransactionsBroadcast signed burn transactions; returns id, status, transactionUrls
GET/outbound-shipmentList user shipments
GET/outbound-shipment/:ididGet specific shipment status

Shipping Address Management

MethodEndpointDescription
GET/shipping-addressList saved addresses
GET/shipping-address/:idGet specific address
POST/shipping-address/createCreate new address
PATCH/shipping-address/update/:idUpdate address
DELETE/shipping-address/:idDelete address

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.

Redeem/Prepare Response Shape

{
  "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}
    ]
  }
}

Auth (SIWS — Sign-In With Solana)

Base: https://api.collectorcrypt.com

MethodEndpointPrimary ParamsDescription
POST/auth/wallet/nonceBody: wallet, partnerAppId, domain, uriGet nonce + EIP-4361 signing message
POST/auth/wallet/verifyBody: message, signature (base58 ed25519)Exchange signature for access + refresh tokens
POST/auth/wallet/refreshBody: refreshTokenRefresh expired access token
POST/auth/wallet/logoutBody: refreshToken (+ access token in Authorization header)Invalidate tokens

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_tradeInitialize trade between two wallets
approve_tradeSignal readiness (both parties must approve)
execute_tradeCommit to execution (both parties must execute)
cancel_tradeAbort open or approved trades
execute_nft_batchTransfer standard NFTs into/out of escrow
execute_pnft_batchTransfer programmable NFTs
execute_cnft_batchTransfer compressed NFTs
execute_token_batchTransfer SPL tokens
mark_trade_settledBackend confirmation of completion
close_tradeFinal cleanup and rent refund

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

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.

Security Properties

  • Non-custodial listings — NFTs remain in seller wallets using delegation, not escrow transfers
  • Frontrun preventionexpected_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

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:

{"statusCode": 400, "message": "human-readable error", "error": "Bad Request"}
StatusMeaning
400Invalid input, on-chain failure, price mismatch, insufficient escrow, signing failure
401Invalid or expired token
403Access denied, program ID outside broadcast allow-list
404Card, NFT, listing, offer, or address not found
409Conflict (already listed, owner changed, wallet linked to Privy account)
429Rate limit exceeded
500Machine empty, too many packs open, or processing error

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 updatesupdate-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.

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.

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/starchild-ai-agent/official-skills/collectorcrypt">View collectorcrypt on skillZs</a>