Player cards held by a wallet
const url = 'https://foxleague.ai/api/players/example';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://foxleague.ai/api/players/exampleAnswers the player cards a wallet holds with their game data, sorted by shirt number. A card listed on the marketplace sits with the marketplace contract and is left out. condition includes the recovery since it was last stored. Every caller gets each card’s yellow_cards and fouls_suffered, another team’s cards included: the app shows them on any team’s roster. The answer for a wallet can be up to 30 seconds old.
Asked by the wallet’s own session, the cards are read from the chain; when the chain cannot be read, the list comes from FoxLeague’s own records. Any other caller (no session, another player) gets the list from FoxLeague’s own records.
Who: anyone.
Refusals: none.
An address that is not a wallet address answers HTTP 400 with an empty body. If the list cannot be read on our side, the answer is HTTP 500 with an empty body.
Authorizations
Section titled “Authorizations ”- None
- session
Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”The wallet address (erd1...).
Responses
Section titled “ Responses ”Success or a refusal: read success (the refusals are in the description).
object
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.
The answer. Present when success is true.
One player card with its game data.
object
Current accuracy value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The accuracy value as last synced to chain.
Training XP toward the next accuracy point.
When the current owner got the card; null when unknown.
Career assists.
Yellow cards toward this card’s next ban. They count only while the bans govern (card_bans.live in GET /api/config), so every card starts at 0 at the switch. The yellow card that reaches card_bans.yellow_cards_per_ban (3 unless the game settings say otherwise) makes a ban (bans_pending) and the count starts again at 0. If that number is lowered, a card already at or above it gets its ban at its next yellow card.
Bans this card has not served yet. More than 0 means suspended: the card misses its team’s next tournament match of more than 2 teams, in its 18 or not. The ban is served once that match’s result is public. A sale or a transfer keeps it. A fusion never clears it: the Fusion tab refuses a suspended card and a fused card has the most bans one of its three cards still had to serve (0 when none had one); a ban a match still on air at the fusion gives one of them counts for that card when that match ends: the fused card’s bans rise only if that card then owes more than any of the three did.
Career catches.
Appearances in competitive matches. They count toward the match gate of the card’s rarity (rarity_match_gate in /api/config). Until the competition levels go live (competition_levels.live_from in /api/config): Silver and Gold tournament matches and 1v1 challenges against a real opponent; ranked, casual and Bronze matches never count. From then also the starter of a paid ranked game (never the team drawn in) and both sides of a paid Bronze (a private one only while competition_levels.private_bronze_earns is true), at most competition_levels.competitive_daily_cap per card per day. A free Bronze, a casual game and a developer match never count.
Condition from 0 to 100, the recovery up to condition_updated_at included.
The moment the recovery in condition was earned up to (RFC 3339). Recovery counts from here: the recovery after it is not in condition yet.
Current control value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The control value as last synced to chain.
Training XP toward the next control point.
Country index, 0 to 43.
When FoxLeague first recorded the card (RFC 3339). This is not the mint time.
Current defense value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The defense value as last synced to chain.
Training XP toward the next defense point.
The card’s total XP.
Total XP as last synced to chain.
Fouls this card suffered once a match’s result is public, called or not, in every match that counts toward competitive_matches for its team (the daily cap aside). A free Bronze, a casual game, a developer match and the team drawn into someone else’s ranked game get nothing.
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.
When the card was made by fusion (RFC 3339); null for a card not made by fusion.
Matches bought for this card with the match waiver. They count toward the match gate of its rarity (gate in rarity_match_gate of /api/config), never toward the matches it must really play (floor).
When the card can be fused again (RFC 3339): null for a card that never came out of a fusion; a time in the past means it can be fused now.
Career goals.
FoxLeague’s record number of the card. Use nft_nonce to name a card.
Until when this card is injured (RFC 3339, UTC); null or a past time when it is not. Each called foul it suffers in a match that counts rolls an injury once the result is public (1% at condition 100, 3% at condition 30); 1 injury keeps it out 3 days, 2 keep it out 9, 3 or more 27. Those numbers are game settings: card_bans in GET /api/config holds the ones in force and a change counts for matches that end after it. An injured card is out of every match until then: replaced by a bench card of its line, the bench one short; a casual or ranked game (or a 1v1 join) is refused when fewer than 11 cards are available. A sale or a transfer keeps it. A fusion never clears it: the Fusion tab refuses an injured card and a fused card is injured until the latest end among its three cards (null when none was injured); an injury a match still on air at the fusion gives one of them reaches it when that match ends.
The card’s level.
The level as last synced to chain.
true while the card is listed on the marketplace.
Every match the card has played.
When the card was minted (RFC 3339). It sets the card’s age. null when unknown.
The player’s name.
The card’s NFT nonce.
The wallet that holds the card. While the card is listed, the seller.
Career passes.
Address of the portrait image; null when none.
GK, DEF, MID or FWD.
Current power value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The power value as last synced to chain.
Training XP toward the next power point.
Common, Uncommon, Rare, Epic or Legendary.
Asking price in whole FOXSY while listed; null otherwise.
Shirt number.
Career shots on target.
Current speed value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The speed value as last synced to chain.
Training XP toward the next speed point.
Current stamina value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The stamina value as last synced to chain.
Training XP toward the next stamina point.
true when the card has changes not yet synced to chain.
Always true.
Career tackles.
Length in hours of the card’s transfer lock, counted from transferred_at; null means transfer_cooldown_hours from /api/config applies. For a rarity_gate lock it is the length now: the hours of every match bought for the card since it moved are already taken off.
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).
When the card last arrived by a direct transfer from another wallet (RFC 3339); its transfer lock counts from here. A card made by fusion from cards still under a transfer lock carries on the lock that ends last. null when neither.
Current vision value, capped by rarity (Common 30, Uncommon 55, Rare 75, Epic 90, Legendary 100).
The vision value as last synced to chain.
Training XP toward the next vision point.
Yellow cards this card received once a match’s result is public, in the tournaments of more than two teams whose matches count toward competitive_matches (the daily cap aside): never in a 1v1 challenge, a ranked game or a free Bronze. The count toward a ban is ban_yellow_cards.
Why the request was refused, in plain words. Present when success is false.
true when the request did what it asked. false is a refusal: read error.
Example
{ "data": [ { "accuracy": 22, "accuracy_synced": 22, "accuracy_xp": 0, "acquired_at": "2026-09-16T08:03:51.004912Z", "assists": 1, "catches": 118, "ban_yellow_cards": 0, "bans_pending": 0, "injured_until": null, "fouls_suffered": 0, "competitive_matches": 17, "condition": 100, "condition_updated_at": "2026-09-30T19:42:07.318204Z", "control": 24, "control_synced": 24, "control_xp": 40, "country": 23, "created_at": "2026-09-16T08:03:51.004912Z", "defense": 30, "defense_synced": 30, "defense_xp": 0, "experience": 3350, "experience_synced": 3350, "fused_at": null, "fused": false, "fusion_match_credit": 0, "fusion_ready_at": null, "goals": 0, "id": 5822, "level": 4, "level_synced": 4, "listed_for_sale": false, "matches_played": 39, "minted_at": "2026-09-15T14:27:12Z", "name": "Lars Holm", "nft_nonce": 1301, "owner_address": "erd15feryxhrdz9m6y09mr8wrerwzgj6f8ntxvhxyrdlm5aahn0t09nl4ujy86", "passes": 402, "portrait_uri": "https://ipfs.io/ipfs/bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354/1301.png", "position": "GK", "power": 25, "power_synced": 25, "power_xp": 120, "rarity": "Common", "sale_price": null, "shirt_number": 1, "shots_on_target": 0, "speed": 27, "speed_synced": 27, "speed_xp": 300, "stamina": 29, "stamina_synced": 29, "stamina_xp": 80, "stats_dirty": false, "synced_stats": true, "tackles": 3, "transfer_cooldown_hours": null, "transfer_lock_kind": null, "transferred_at": null, "vision": 28, "vision_synced": 28, "vision_xp": 560, "yellow_cards": 0 }, { "accuracy": 57, "accuracy_synced": 57, "accuracy_xp": 640, "acquired_at": "2026-09-16T08:03:51.004912Z", "assists": 14, "catches": 0, "ban_yellow_cards": 0, "bans_pending": 0, "injured_until": null, "fouls_suffered": 0, "competitive_matches": 21, "condition": 86, "condition_updated_at": "2026-09-30T19:42:07.318204Z", "control": 66, "control_synced": 65, "control_xp": 1530, "country": 0, "created_at": "2026-09-16T08:03:51.004912Z", "defense": 44, "defense_synced": 44, "defense_xp": 220, "experience": 7420, "experience_synced": 7210, "fused_at": null, "fused": false, "fusion_match_credit": 0, "fusion_ready_at": null, "goals": 9, "id": 5821, "level": 6, "level_synced": 6, "listed_for_sale": false, "matches_played": 47, "minted_at": "2026-09-15T14:27:12Z", "name": "Renan Silva", "nft_nonce": 1234, "owner_address": "erd15feryxhrdz9m6y09mr8wrerwzgj6f8ntxvhxyrdlm5aahn0t09nl4ujy86", "passes": 1288, "portrait_uri": "https://ipfs.io/ipfs/bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354/1234.png", "position": "MID", "power": 49, "power_synced": 49, "power_xp": 0, "rarity": "Rare", "sale_price": null, "shirt_number": 8, "shots_on_target": 33, "speed": 61, "speed_synced": 60, "speed_xp": 1180, "stamina": 58, "stamina_synced": 58, "stamina_xp": 310, "stats_dirty": true, "synced_stats": true, "tackles": 61, "transfer_cooldown_hours": null, "transfer_lock_kind": null, "transferred_at": null, "vision": 63, "vision_synced": 63, "vision_xp": 905, "yellow_cards": 0 } ], "success": true}address is not a wallet address (erd1...). The body is empty.
No valid session. The body is plain text: Missing Authorization header, Invalid Authorization format, Invalid session token or Session expired or invalid. Sign in again.
Example
Session expired or invalidThe cards could not be read on our side. The body is empty.