Skip to content

Save your starting eleven and bench

POST
/api/teams/lineup
curl --request POST \
--url https://foxleague.ai/api/teams/lineup \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "formation": "example", "lineup": [ 1 ], "substitutes": [ 1 ], "wallet_address": "example" }'

Saves your 11 starters and 7 substitutes and answers the team. lineup lists the starters in shirt order, the slots of your formation as Tactics shows them: shirt 1 the goalkeeper, then its defenders, midfielders and forwards. Each starter must be a card of his slot’s line. Send formation to save a new formation together with this lineup: everything is checked against it and both are written in one save or neither is. Without it your saved formation stays. Send up to 7 substitutes: a shorter bench is completed from your other cards position for position, leaving out cards listed for sale or still in a transfer cooldown. The bench holds 1 goalkeeper and 6 outfield players split over defence, midfield and attack like the lines of your formation (4-3-3: 2, 2, 2; 4-4-2: 2, 3, 1; 5-3-2: 3, 2, 1). The substitutes you sent stay and count toward their line; each line takes your strongest cards; a line without enough cards gives its places to your strongest remaining cards. A substitute of yours that is listed for sale leaves the bench and its seat is completed the same way; the answer carries the bench that was saved. Every starter and every other card must be yours and not listed for sale.

Who: a signed-in player with a team.

Refusals:

  • Lineup must have exactly 11 players: lineup does not hold 11 nonces.
  • Substitutes cannot exceed 7 players: substitutes holds more than 7 nonces.
  • Invalid formation: formation is not a known formation.
  • This formation is coming soon. Pick another formation.: formation is known but cannot be picked yet.
  • User not found: the wallet has no account.
  • Team must have exactly 11 starters + 7 substitutes. You picked <n> sub(s) and have only <r> eligible reserve(s). Acquire <x> more NFT(s) to complete the bench.: you do not have enough cards for a full bench. <n> leaves out the substitutes you sent that are listed for sale; the text then ends with 1 substitute listed for sale left your bench: cancel the listing to keep him. (with two of them: 2 substitutes listed for sale left your bench: cancel the listings to keep them.).
  • Some players are not owned by you or are listed for sale: a card is not yours, is a starter listed for sale or appears twice.
  • <name> is a <line>. Slot requires <line>: a starter is not a card of his slot’s line (GK, DEF, MID or FW), for example Fox 7 is a FW. Slot requires DEF. The first such starter is named. Nothing is saved.
  • Cooldown active for recently-transferred players: <name> (<time left>), ...: a card received from another wallet is still in its transfer cooldown. The time left reads like 3d 4h or 5h 12m.

A wallet without a team gets HTTP 404 with an empty body. If the lineup cannot be saved on our side, the answer is HTTP 500 with an empty body.

Media type application/json

The starting eleven and bench to save.

object
formation

Optional. A formation to save together with this lineup: one of 4-4-2, 4-3-3, 5-3-2, 4-3-3w, 4-3-3b, 4-4-2o, 4-2-3-1 and 5-2-3. The starters and the bench are checked against it and both are written in one save or neither is. Leave it out to keep your saved formation.

string | null
lineup
required

NFT nonces of the 11 starters in shirt order: the slots of your formation, shirt 1 the goalkeeper, then its defenders, midfielders and forwards. Each must be a card of its slot’s line.

Array<integer>
substitutes

NFT nonces of up to 7 substitutes. A shorter bench is completed from your other cards, position for position: 1 goalkeeper plus the lines of the formation the lineup is saved in.

Array<integer>
wallet_address
required

Your wallet address. The body needs it, but the session decides which team changes.

string
Example generated
{
"formation": "example",
"lineup": [
1
],
"substitutes": [
1
],
"wallet_address": "example"
}

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.

object
badge

The team badge, usually an ipfs:// address (some older teams carry an inline image); null when none.

string | null
badge_ipfs_uri

The badge’s ipfs:// address; null when none.

string | null
best_xi_by_formation
required

The best XI of every formation the team can pick, best first (equal ones in the order of the formation list): its first entry is best_xi_ovr in best_xi_formation. Empty when no card it owns fits a slot.

Array<object>

The best XI of one formation.

object
complete
required

false when the cards cannot fill that formation: the OVR is then the average of the cards it holds.

boolean
formation
required

A formation a team can pick in Tactics, as a Team.formation id such as 4-3-3.

string
ovr
required

The best XI OVR in that formation, one decimal.

number format: double
best_xi_formation

The formation that best XI is built in, such as 4-3-3. null with best_xi_ovr.

string | null
best_xi_ovr

The team’s OVR, one decimal: its best XI OVR, the average OVR of the strongest XI it can field from the cards it owns now (for every formation in Tactics the best card of each position for its slots, each card in its own position, the highest average kept; cards listed for sale count). No lineup choice moves it. The same number every page and the OVR range use. null when no card it owns fits a slot.

number | null format: double
coach_name

The coach name; null when not set.

string | null
created_at
required

When the team was created (RFC 3339).

string format: date-time
formation
required

The saved formation.

string
id
required

Team id.

integer format: int32
lineup
required

NFT nonces of the 11 starters, as an array. Empty until a lineup is saved.

name
required

Team name.

string
substitutes
required

NFT nonces of the bench, as an array.

user_id
required

The owner’s user id.

integer format: int32
verified
required

true when the team carries the verified mark.

boolean
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": {
"badge": "ipfs://bafybeihkoviema7g3gxyt6la7vd5ho32ictqbilu3wnlo3rs7ewhnp7lly",
"badge_ipfs_uri": "ipfs://bafybeihkoviema7g3gxyt6la7vd5ho32ictqbilu3wnlo3rs7ewhnp7lly",
"best_xi_by_formation": [
{
"complete": true,
"formation": "4-3-3",
"ovr": 52.6
},
{
"complete": true,
"formation": "4-3-3w",
"ovr": 52.6
},
{
"complete": true,
"formation": "4-3-3b",
"ovr": 52.6
},
{
"complete": true,
"formation": "4-4-2",
"ovr": 52.1
},
{
"complete": true,
"formation": "4-4-2o",
"ovr": 52.1
},
{
"complete": true,
"formation": "4-2-3-1",
"ovr": 51.8
},
{
"complete": true,
"formation": "5-3-2",
"ovr": 51.3
},
{
"complete": true,
"formation": "5-2-3",
"ovr": 50.9
}
],
"best_xi_formation": "4-3-3",
"best_xi_ovr": 52.6,
"coach_name": "Ada Moraru",
"created_at": "2026-09-16T08:02:44.517093Z",
"formation": "4-3-3",
"id": 398,
"lineup": [
1301,
1234,
1240,
1255,
1262,
1270,
1288,
1290,
1302,
1311,
1325
],
"name": "Fox Rovers",
"substitutes": [
1330,
1342,
1356,
1361,
1377,
1389,
1394
],
"user_id": 412,
"verified": false
},
"success": true
}

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.

Media type text/plain
string
Example
Session expired or invalid

The wallet has no team yet. The body is empty.

The lineup could not be saved on our side. The body is empty.