Onboarding — Game Value, player board
Ten steps, each with a way to tell that it worked. Follow them in order and your ratings are scored. Skip one and everything still returns
201— and nothing is ever scored.
This is the page to read end to end before you write any code. The delivery contract is the reference you will keep open afterwards; the overview explains what is being measured and why.
Every call below is made against https://api.footballanalyticsarena.com, and paths are shown
relative to it. The API's own reference, where each endpoint can be tried from the browser, is at
api.footballanalyticsarena.com/docs.
This is not one submission
Player Value is a standing weekly obligation, at the scale of a squad sheet. After every round you send one rating per player per appearance — about 1,400 of them — before a deadline that belongs to the round rather than to the match, and your score is rebuilt from the whole season each week.
If you already deliver to the team board, the rules are the same ones to the minute: the same key, the same deadlines, the same freeze, the same ten deliveries a round. Three things are different, and all three follow from the number:
- The unit is an appearance, so the list pages. You follow it with a cursor rather than reading it whole (step 4).
- The gate is the eleven, not everything. Certification asks for every starter; a cameo you decline does not block you (step 5).
- A rating is scored through the eleven it played in. A segment is priced on the mean prior rating of the players on the pitch, so a rating counts once a player has an earlier rated appearance behind him — not the week you send it (step 9).
Step 1 — Register
One identity for the whole Arena, whatever you enter.
POST /api/participants
{
"vendor_name": "Acme Analytics",
"leaderboard_name": "Acme ratings",
"short_description": "Match ratings from event data",
"contact_email": "team@acme.example.com"
}
The response carries an API key beginning fa_. It is shown once and never again — store it
where your delivery job can read it. The contact address is where deadline reminders are sent; it
is never published.
Done when you hold a key starting
fa_. If you are already registered for another benchmark, skip this: the key is Arena-wide.
Step 2 — Enter the benchmark
POST /api/participants/entries Authorization: Bearer <your key>
{ "task_slug": "game_value_player" }
A 201 comes back with "participation_mode": "submission" — the Arena never calls you, so there
is no endpoint to expose and no service to keep running.
Done when you have that 201.
Entering is not certifying. A real delivery now is refused with
403 Certify first. Step 5 is what enrolment actually means.
Step 3 — Map the Arena's players to your own
Everything you deliver is keyed on the Arena's identifiers. Map them to your own once, before you send anything, and keep the mapping.
GET /api/tasks/game-value-team/teams the clubs: team_id -> name, country, competition
GET /api/tasks/game-value-player/players the players: player_id -> name, club, birth year, position
The team registry is the team board's, because both boards share one calendar and one set of club
ids. The player directory gives each player_id (FAP0003133) the name, club, year of birth,
nationality and position you need to match it against your own database. Both are public: no key.
?team_id= or ?competition= reads one club or one league at a time.
- Integrate on the ids, never the names. Names are published so you can build the mapping; a
delivery carries
player_idalone. A name match made at delivery time is a guess, and a guess puts a rating on the wrong footballer silently. - Match on more than a name. Club, birth year and position resolve the cases a name cannot — two players of one name in one league, the player a source spells three ways.
- New players arrive every window. Re-read the directory weekly and map what is new; a player you have not mapped is an appearance you cannot rate.
Done when every club you cover resolves to a
team_id, and the players of those clubs resolve toplayer_ids in your own database without consulting a name at delivery time.
Step 4 — Follow the appearance list
GET /api/tasks/game-value-player/appearances?limit=1000 Authorization: Bearer <your key>
One row per player per appearance: match_id, player_id, team_id, minutes_played,
is_starter, competition, round, kickoff, deadline, updated_at. It is what you rate, and
the only thing you can rate — a rating for anyone not on it is refused.
Page it with the cursor, not with a timestamp. The response carries count, more and
next_since. While more is true, send next_since back as ?since= to get the next page. At the
end of the list, keep the next_since you were given and send it on your next run: you will read
only what changed.
Why this matters. A match's appearances are all written at the same instant. A page that ends in the middle of a match ends on a time that the unread rows of that match also carry, so resuming on the time alone skips them — silently, and for good.
next_sincenames the exact row you stopped on. It is the easiest thing on this board to get wrong.
Two things the list decides for you:
- An unused substitute is not on it. He made no appearance; there is nothing to rate.
- A three-minute substitute is. He played. Declining to rate him is a product boundary the board reports as coverage, not an error.
Done when your job reads the whole list in pages, stores
next_since, and a second run straight after the first returns nothing new.
Step 5 — Certify
Certification is a dry run against one completed round, checked exactly as a real delivery would be and storing nothing.
POST /api/tasks/game-value-player/ratings?dry_run=true Authorization: Bearer <your key>
{
"task": "game_value_player",
"contract_version": "2026-09-game-value-player-v0",
"model_version": "my-ratings-2.1",
"ratings": [
{"match_id": "fam_2627_premierleague_0042", "player_id": "FAP0000731", "rating": 7.4},
{"match_id": "fam_2627_premierleague_0042", "player_id": "FAP0004120", "rating": 5.9}
]
}
To pass, the dry run must carry every starter of one completed round, and nothing may be rejected. Send the whole round — cameos included, where you rate them — but only the starters are required: the eleven on the pitch at kick-off is what a signal is built from.
lateis not a failure. A completed round's deadline has passed, so its entries come back markedlate. The only outcome that prevents certification isrejected.
Certifying is also how you declare what you are entering. The competitions your dry run covered are the ones you are scored on, and within one you rate every appearance you can — you do not choose which. To cover all five leagues, send one completed round per competition in the same dry run. Certifying again later adds a competition; it never moves your enrolment date.
Done when the receipt says
"certified": true. That moment is your enrolment: you are scored from it, not from when you registered.
Dry runs count toward no limit, so run as many as you need until nothing is rejected.
Step 6 — Deliver, every round
The same call without dry_run: one number per player per appearance, on your own scale.
POST /api/tasks/game-value-player/ratings Authorization: Bearer <your key>
- Nothing is normalised. Out of ten, out of a hundred, z-scores: the score depends only on the order your ratings put players in.
- One rating per appearance, not per segment. The Arena decides who was on the pitch for each segment, from the event stream.
- A missing rating is missing, never zero. Leave out what you do not rate. A zero for a player you did not judge is a wrong number, and on a mean over eleven a very wrong one.
- Goalkeepers are not optional. An unrated keeper counts against your rated share like anyone else.
The response is your receipt: an outcome per entry — accepted, replaced, unchanged, late, or
rejected with a reason — the Arena's receipt time, and a payload_sha256 of the body as received.
Ten stored deliveries per round, dry runs exempt. A round is about 1,400 ratings, so batch them: a job that re-posts the same round every night spends the ten inside a fortnight.
Done when the receipt's outcomes are the ones you expected and its
payload_sha256matches the checksum of what you sent. Keep the receipt.
Step 7 — Know your deadline
The deadline belongs to the round, not to the match, and every appearance carries it.
- A round's ratings are due at 23:59 Europe/Paris, a full day after the round's last match — Tuesday, for a weekend round. The same rule as the team board.
- A postponed match is a round of its own, with its own deadline.
- Ratings are replaceable until the deadline and freeze at it. Afterwards a first rating still
lands, as
late; a different rating for someone already rated is refused asfrozen. - A rating counts only toward matches kicking off after its deadline. A rating that can arrive once a result is known must not be allowed to inform it.
Run your job daily, not weekly. A midweek round is due the day after it is played, and a weekly job misses one deadline in every midweek week.
Done when your job runs daily and clears each deadline by hours, not minutes.
Step 8 — Check what is still missing
GET /api/tasks/game-value-player/status Authorization: Bearer <your key>
due lists every open round with something missing: its competition, round and deadline, how
many ratings are expected and how many were delivered, how many are missing, which matches
they are missing from (matches_incomplete), and the deliveries_left for that round.
missed_this_season counts ratings that were not there when a deadline passed.
What is missing is counted, not listed — a list of 1,400 outstanding appearances would be longer
than the delivery that answers it. matches_incomplete tells you where to look.
The Arena also emails a reminder at deadline − 12 h and − 3 h when something is missing. A job that checks its own work never hears from us.
Done when
dueis empty for the open round, or holds only the cameos you choose not to rate.
Step 9 — Be scored
The scoring run is every Saturday at 06:30 Europe/Paris, once every deadline in the week has passed. It rebuilds your score from the whole season and appends one immutable snapshot a week.
A segment is scored for you only when at least nine of the eleven on the pitch, on both sides, have a prior rating from you — a rating for an earlier appearance, due before this match kicked off. That is why your first round scores nothing: it is the history your second round is priced on. Most starters play most weeks, so the second round after you certify is usually scorable, and the Saturday after its deadline brings your first snapshot.
The second ranking comes later. The selection column compares what a player was rated over five club matches with the minutes he played over the next five, so it reads only once every club has played about ten rounds since you certified.
Done when a snapshot exists for you. Until it does, you are enrolled and delivering correctly — there is simply nothing to compute yet.
Step 10 — Be published
Being scored and being named are separate. A person confirms who you are before your row appears on the public board.
Publication is resolved when the board is read, so confirming late reveals your whole trajectory at once. Being published slowly costs you nothing.
Done when your row is on the player board, and your players appear under Players, match by match.
Your first month
What actually happens, week by week, if you certify today.
| When | What happens | What you should see |
|---|---|---|
| Day 0 | Register, enter, map, certify | "certified": true, and enrolment dated now |
| The first round after that | Your job delivers every appearance you rate | A receipt with entries accepted |
| That Tuesday 23:59 | The round's ratings freeze | status shows nothing due |
| The first Saturday | Scoring runs | No snapshot yet — no player has a prior rating from you |
| The second round | Deliver again; its segments are priced on the first round's ratings | status empty |
| The Saturday after its deadline | Scoring runs | Your first snapshot: a skill score with an interval, and not scored yet on the selection column |
| After about ten rounds | Enough club matches either side of a pivot | The selection column reads for the first time |
Common refusals, and what each means
A whole delivery can be refused:
| Code | Means | Fix |
|---|---|---|
401 | No valid key | Send Authorization: Bearer <your key> |
403 | Not entered, or not certified | Step 2, then step 5 |
400 | Wrong task | It must be game_value_player |
409 | contract_version is not the one in force | The refusal names the version that is; see versioning |
422 | The body is not shaped like the contract | Check required fields and types |
Or individual entries can be rejected while the rest of the delivery lands:
| Reason | Means | Fix |
|---|---|---|
unknown match_id | No such fixture this season | Take ids from the appearance list; do not construct them |
player did not appear in this match | Not on the appearance list for that match — often an unused substitute | Rate only what the list offers; check your player mapping |
match not played | Rated before it was played | Deliver after the match |
before enrolment | The match kicked off before you certified | Not accepted: it could be rated knowing the result |
rating is not a number | Not numeric, or not finite | Send a number, not a string, null or NaN |
duplicate player in this delivery | The same (match_id, player_id) twice in one body | Send each appearance once |
frozen | A different rating after the deadline | The first rating stands; corrections had to arrive before the deadline |
delivery limit reached for this round | The round's ten deliveries are spent | Batch your ratings; check status before resending |
Joining mid-season
You may join at any point. Certify, and you are scored from that moment.
Ratings for matches that kicked off before you certified are refused as before enrolment. It is
the rule everyone is under: a rating for a match played weeks ago could be made knowing every result
since, and would not be a forecast. Since the history your first scores need is built from the day
you certify, the sooner you certify, the sooner you are scored.
If your ratings predate the season, ask about a scoring exception. A rating published match by match since August, fixed before any result it is scored against, is the case it exists for. An admin can let ratings count for rounds due at or before a stated horizon, with the reason printed on every snapshot it touches and beside your name on the board. Nothing is backdated: your receipts keep the time the ratings really arrived.
Before your first real delivery
- Your key is stored where the job reads it, and is not in source control
- Every club you cover maps to a
team_id, and its players toplayer_ids - Your job re-reads the player directory weekly and maps new players
- Your job follows the appearance list with
next_since, and never resumes on a time alone - You deliver
player_ids, never names, and one rating per appearance - Nothing you did not rate is sent as zero
-
contract_versionis the one in force, and a409is treated as a change to act on - Your job runs daily and clears the deadline by hours
- You batch each round, and check
/statusbefore resending one - You keep each receipt, with its
payload_sha256 - You have certified one completed round per competition you intend to cover
What to read next
- Delivery contract — the reference for every call above, with the paging cursor and the deadline rules in full.
- Scoring — how a delivered rating becomes a published number, and how to recompute one.
- Overview — what is measured, and what the board does not claim.
- Reading a leaderboard — the two rankings, the floor, and what a row on the board is telling you.