Skip to content

Cards on sale in the marketplace

GET
/api/marketplace/listings
curl --request GET \
--url https://foxleague.ai/api/marketplace/listings

Cards listed for sale: fixed-price listings and auctions, each with the card’s stats, its condition, its yellow cards and fouls suffered, its transfer lock and, for an auction, its reserve, top bid and end. Filters match exactly. Without sort_by the newest listing comes first. sort_by=ending_soon puts live auctions first (the one ending soonest on top), then fixed-price listings (newest first), then auctions that have ended and wait to be settled. sort_by=price_asc puts the lowest current price first and sort_by=price_desc the highest (the current price is an auction’s top bid, else its reserve, else the fixed price). sort_by=overall_desc puts the highest sum of the seven stats first. Every order is complete: listings that tie keep one order by card nonce.

The answer is one page. The X-Total-Count response header holds how many listings match the filters in all; ask for the next page with offset set to the number of rows already read until you hold that many.

Who: anyone.

position
string

Only cards of this position: GK, DEF, MID or FWD.

rarity
string

Only cards of this rarity: Common, Uncommon, Rare, Epic or Legendary.

min_price
integer format: int64

Only listings whose current price is at least this, in whole FOXSY. The current price is an auction’s top bid, else its reserve, else the fixed price.

max_price
integer format: int64

Only listings whose current price is at most this, in whole FOXSY.

sort_by
string

ending_soon for live auctions first (see the description), price_asc for the lowest current price first, price_desc for the highest current price first, overall_desc for the highest sum of the seven stats first. Leave it out for the newest listing first.

limit
integer format: int64

Rows per page, 1 to 200. Default 50.

offset
integer format: int64

Rows to skip. Default 0.

Success or a refusal: read success (the refusals are in the description).

Media type application/json
object
code

A machine-readable reason next to error, set only where the caller must act differently. tx_pending: the payment was not refused but could not be verified yet; keep the transaction hash and confirm again with the same hash, never pay twice.

string | null
data

The answer. Present when success is true.

Array<object>

A card on sale, at a fixed price or at auction.

object
accuracy
required

The card’s accuracy attribute.

integer format: int32
ban_yellow_cards
required

Yellow cards toward this card’s next ban, 0 to 2, the same count as ban_yellow_cards of the card (GET /api/players/nonce/{nonce}). They count only while the bans govern (card_bans.live in GET /api/config). A sale keeps them.

integer format: int32
bans_pending
required

Bans this card has not served yet, the same count as bans_pending of the card. More than 0 means suspended: the card misses its team’s next tournament match of more than 2 teams. A sale keeps it, so the buyer’s team serves it.

integer format: int32
condition
required

Condition from 0 to 100, as last recorded.

integer format: int32
control
required

The card’s control attribute.

integer format: int32
country
required

The card’s country index.

integer format: int32
created_at

When FoxLeague first recorded the card (RFC 3339). This is not the mint time. The age the app shows on the card counts from it when minted_at and fused_at are both null.

string | null format: date-time
defense
required

The card’s defense attribute.

integer format: int32
ends_at

Auction end (RFC 3339); a late bid can push it later. null for a fixed-price listing.

string | null format: date-time
experience
required

The card’s XP.

integer format: int32
fouls_suffered
required

Fouls this card suffered, the same count as fouls_suffered of the card (GET /api/players/nonce/{nonce}), counted once a match’s result is public. It stays with the card after a sale.

integer format: int32
fused
required

true when the card came out of a fusion: it was minted from the fusion pool. false for every other card, a starter squad card among them. The mark stays with the card for good, also after a sale. Display only: no rule, price or match reads it.

boolean
fused_at

When the card was made by fusion (RFC 3339); null for a card not made by fusion. The age the app shows on the card counts from it when minted_at is null.

string | null format: date-time
highest_bid

The top bid in whole FOXSY; null before the first bid and for a fixed-price listing.

integer | null format: int64
injured_until

Until when the listed card is injured (RFC 3339, UTC); null or a past time when it is not. An injured card can be listed and sold; the buyer gets the injury with the card. It is out of every match until then.

string | null format: date-time
is_auction
required

true for an auction, false for a fixed-price listing.

boolean
level
required

The card’s level.

integer format: int32
listed_at

When the card was listed (RFC 3339).

string | null format: date-time
min_price

The auction reserve in whole FOXSY; null for a fixed-price listing.

integer | null format: int64
minted_at

When the card was minted on chain (RFC 3339); null when unknown. The age the app shows on the card counts from it; when it is null that age counts from fused_at, then from created_at.

string | null format: date-time
name
required

The card’s name.

string
nft_nonce
required

The card’s NFT nonce.

integer format: int64
owner_address
required

The seller’s wallet.

string
portrait

The card’s portrait URI; null when it has none.

string | null
position
required

GK, DEF, MID or FWD.

string
power
required

The card’s power attribute.

integer format: int32
rarity
required

Common, Uncommon, Rare, Epic or Legendary.

string
sale_price
required

The listed price in whole FOXSY; 0 when unknown. For an auction read min_price and highest_bid.

integer format: int64
shirt_number
required

The card’s shirt number.

integer format: int32
speed
required

The card’s speed attribute.

integer format: int32
stamina
required

The card’s stamina attribute.

integer format: int32
transfer_cooldown_hours

The length of this card’s transfer lock in hours; null means the standard length.

integer | null format: int32
transfer_lock_kind
One of:

The kind of a card’s transfer lock: rarity_gate (the card was sent before it reached its gate; Reduce Cooldown does not apply, each match bought for the card shortens the lock down to a floor; a listed card already sits at its floor), standard (the usual lock; Reduce Cooldown applies) or per_card (a lock set before the rarity rules; Reduce Cooldown applies).

string
Allowed values: rarity_gate standard per_card
transferred_at

When the card last moved between wallets (RFC 3339). Its transfer lock counts from here and carries over to a buyer; null when no lock applies.

string | null format: date-time
vision
required

The card’s vision attribute.

integer format: int32
yellow_cards
required

Yellow cards this card received, the same count as yellow_cards of the card (GET /api/players/nonce/{nonce}): counted once a match’s result is public, only in tournaments of more than two teams. It stays with the card after a sale.

integer format: int32
error

Why the request was refused, in plain words. Present when success is false.

string | null
success
required

true when the request did what it asked. false is a refusal: read error.

boolean
Example
{
"data": [
{
"accuracy": 72,
"ban_yellow_cards": 1,
"bans_pending": 0,
"condition": 88,
"control": 70,
"country": 7,
"defense": 41,
"ends_at": "2026-10-02T07:30:00Z",
"experience": 1840,
"fouls_suffered": 6,
"highest_bid": 1750,
"is_auction": true,
"level": 7,
"listed_at": "2026-10-01T07:30:00Z",
"min_price": 1500,
"minted_at": "2026-09-21T12:00:00Z",
"fused": true,
"name": "Marco Vela",
"nft_nonce": 4127,
"owner_address": "erd124fl6zy54klay937yrnujckpak28lrdjg0eel92ue3gm36kcwf9tfwwqlt",
"portrait": "ipfs://bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku",
"position": "FWD",
"power": 69,
"rarity": "Rare",
"sale_price": 1500,
"shirt_number": 9,
"speed": 74,
"stamina": 71,
"transfer_cooldown_hours": null,
"transfer_lock_kind": null,
"transferred_at": null,
"vision": 66,
"yellow_cards": 2
},
{
"accuracy": 58,
"ban_yellow_cards": 0,
"bans_pending": 0,
"condition": 100,
"control": 57,
"country": 22,
"defense": 50,
"ends_at": null,
"experience": 410,
"fouls_suffered": 1,
"highest_bid": null,
"is_auction": false,
"level": 3,
"listed_at": "2026-09-30T16:12:44Z",
"min_price": null,
"minted_at": "2026-09-21T12:00:00Z",
"fused": false,
"name": "Pavel Dudek",
"nft_nonce": 3990,
"owner_address": "erd1pn9sh2kw4wv0ewvlkpp37svkukh9wxw7v4d7q7k98cv7tm49eae922gpfa",
"portrait": null,
"position": "MID",
"power": 52,
"rarity": "Common",
"sale_price": 350,
"shirt_number": 8,
"speed": 55,
"stamina": 59,
"transfer_cooldown_hours": null,
"transfer_lock_kind": "standard",
"transferred_at": "2026-09-25T10:00:00Z",
"vision": 60,
"yellow_cards": 0
}
],
"success": true
}

A server read failed. The body is empty.