Skip to main content

Cards and decks API

The cards and decks API manages the authenticated player's owned copies and saved battle decks. The server owns card eligibility, deck validation, starter grants, and evolution results. Clients identify owned copies; they do not grant, consume, reserve, or transform cards locally.

See Collections and decks and Evolving cards for the player journeys. Trading uses the separate Trading API.

Access and routes​

All routes begin with /api/v1 and require bearer authentication and an active player account.

MethodRoutePurpose
GET/cards/collectionList the player's owned card copies.
GET/cards/starter-optionsCompare the available starter packages.
POST/cards/starterClaim one starter package.
GET/cards/evolutions/:sourceCardDefinitionId/previewCheck one evolution without reserving cards.
POST/cards/evolutionsConsume 3 copies and grant the evolved card.
GET/decksList saved decks and the active selection.
POST/decksCreate a saved deck.
PUT/decks/:deckIdReplace a saved deck's name and cards.
DELETE/decks/:deckIdDelete a saved deck.
PUT/decks/:deckId/selectionMake a valid saved deck active.

The OpenAPI reference owns exact request and response schemas. Successful JSON responses include requestId.

Collection and starter cards​

GET /cards/collection returns individual owned copies with their catalogue and acquisition fields. Send unique=true to receive only the newest owned copy of each card definition. This is a display filter; it does not merge or delete duplicates.

Send deckId=<UUID> to read only copies currently in a saved deck owned by the caller. Missing, deleted, and foreign decks return the same empty collection. Invalid UUIDs return 400. Combining deckId with unique=true selects the newest copy of each definition within that deck. Responses retain the same metadata; the filter does not reserve cards or validate battle readiness.

GET /cards/starter-options returns the currently approved Spark, Grit, and Wit packages. Each package contains 3 Common Creatures and 2 Common Power cards. Claim one by sending:

{
"affinity": "spark"
}

The first successful claim returns 201. Repeating the same affinity returns the saved grant with 200 and does not issue more cards. A different affinity after a claim returns 409 STARTER_ALREADY_CLAIMED. If a response is lost, repeat the same affinity rather than trying a different one.

Saved decks​

Create or replace a deck with a name and exactly 5 owned-copy identifiers:

{
"name": "Great Hall Five",
"ownedCardIds": [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002",
"00000000-0000-0000-0000-000000000003",
"00000000-0000-0000-0000-000000000004",
"00000000-0000-0000-0000-000000000005"
]
}

The server trims the name and validates ownership, availability, order, and the Basic deck rules: 3 Creatures, 2 Power cards, distinct owned copies, and at most 10 rarity points. A copy reserved by an unfinished trade is unavailable. The same owned copy may appear in different saved decks, but not twice in one deck.

Deck responses include deckId, name, isSelected, totalPoints, timestamps, and the 5 ordered cards. Selecting a deck revalidates its current cards before making it the player's single active selection. Deleting the active deck clears that selection without deleting any cards.

Deck mutations have no submissionId or expectedVersion. A PUT replaces the whole name and lineup, so reload before editing from another client. After an uncertain create response, list decks before creating again because creation does not have an idempotency key.

Evolution preview and command​

Preview a source definition before evolving it. The response identifies the fixed target, the 3-copy requirement, owned and eligible counts, each copy's lock reason, and canEvolve. A preview is current information, not a reservation; the command rechecks every condition.

Submit an evolution with one caller-generated UUID for that intended command:

{
"submissionId": "00000000-0000-0000-0000-000000000010",
"sourceCardDefinitionId": "00000000-0000-0000-0000-000000000020"
}

The server locks the owned copies, selects the 3 newest eligible copies, consumes them, and grants the fixed target in one transaction. Copies used by any saved deck or reserved by an unfinished trade are protected.

A new evolution returns 201; an identical replay returns 200 with replayed: true and the original result. Retry an uncertain response with the same submissionId and source definition. Never reuse that identifier for a different source.

Errors and recovery​

ResponseCaller action
400 STARTER_AFFINITY_NOT_ALLOWEDReload starter options and choose a supported affinity.
400 INVALID_DECK_CARDSRefresh the collection and replace unavailable or reserved copies.
400 DECK_SIZE_INVALIDSend exactly 5 owned-copy identifiers.
400 DECK_COPY_DUPLICATEDUse 5 distinct owned copies.
400 DECK_COMPOSITION_INVALIDUse exactly 3 Creatures and 2 Power cards.
400 DECK_POINT_CAP_EXCEEDEDReduce the lineup to at most 10 rarity points.
404 DECK_NOT_FOUNDRemove the unavailable deck from local state.
404 EVOLUTION_NOT_AVAILABLERefresh the catalogue; the source has no active evolution.
409 STARTER_ALREADY_CLAIMEDKeep the existing starter affinity.
409 STARTER_CATALOGUE_UNAVAILABLEDelay the first claim and reload the available packages.
409 EVOLUTION_COPIES_INSUFFICIENTRefresh the collection and obtain more copies.
409 EVOLUTION_COPIES_DECK_LOCKEDRemove enough source copies from every saved deck, then preview again.
409 EVOLUTION_COPIES_TRADE_RESERVEDEnd the relevant trade reservation, then preview again.
409 EVOLUTION_REPLAY_CONFLICTDo not change the intent attached to a used submission ID.

Collection and deck reads are private to the authenticated player. Missing and foreign deck identifiers share the same not-found response. See deck storage for transaction details and card reward storage for ownership provenance.

AI declaration​

Prepared with assistance from Codex[GPT-6], using card, evolution, and saved-deck route schemas and transaction behaviour.