Section 4: Evidence, Not a Number - API Design (with Pushback)
Executive Summary: This section designs the whole public contract of the leaderboard: one write endpoint and five reads. Every shape is defended under pressure. The write accepts a run, not a score, and answers with both ranks so the player reads their own write without a second call. The reads are bounded on purpose: the top 100 comes from a cache, around-me and friends are personal views keyed by the token, and paging stops at rank 10,000. We then work through the interviewer's pushback: why there is no PUT /score, why the POST returns ranks, why paging is capped, why me sits in the path, and what 409, 422 and 429 each mean. The contract is small, but each line of it is doing a job.
Section 3 ended with a reassuring result: one sorted set per board fits, and exact ranks cost O(log N). The interviewer nods, caps the marker and says, "Fine. Show me the API."
Most candidates now write POST /score with a body of {playerId, score}. That one line lets any client name any player, lets it set any score, and gives the server no way to tell a retry from a new run. The Staff answer starts from what the client is allowed to claim:
POST /v1/runs submit a finished run, get both ranks back
GET /v1/boards/{boardId}/top?limit=100 the top 100 (cached)
GET /v1/boards/{boardId}/me/around?radius=5 the players just above and below me
GET /v1/boards/{boardId}/me/friends me and my friends, ranked
GET /v1/boards/{boardId}/players/{playerId} one player's public rank
GET /v1/boards/{boardId}/page?fromRank=&limit=50 paging, capped at rank 10,000
boardId: weekly-2026-W44 | all-time
The surface has six endpoints and no write that names a score to store.
The Write: Submitting Evidence
Kai has just finished run r-7f3a91 in Manila. Their client sends this:
POST /v1/runs
Authorization: Bearer <token>
{
"runId": "r-7f3a91",
"endedAt": "2026-10-28T21:14:00Z",
"durationMs": 1140000,
"score": 1284500,
"ticket": "<server-signed run ticket>",
"summary": "<compact run summary>",
"signature": "<install-key signature over the summary>"
}
Every field has a job:
runIdis generated on the device before the first attempt to send. It is the idempotency key.endedAtis event time, so it decides which week the run belongs to. A run that ends before Monday 00:00 UTC still counts for the old week if it arrives within the 5-minute grace. A clock on the device is a claim, not a fact, so the server bounds it:ticketIssuedAt + durationMs ≤ endedAt ≤its own receive time.ticketis a server-signed run ticket issued when the run starts. ItsticketIssuedAtis the lower bound above, so a backdatedendedAtcan't win ties. Section 10 derives the tie time from it.durationMsis what makes the score checkable. The plausibility bound is ≤ 2,000 points per second of run time.summaryandsignatureare the evidence: a compact record of the run, signed with a key held by that install. Section 10 explains how they are verified and replayed.
Notice what the body does not contain: a playerId. Identity comes from the token. Kai's playerId, 48213377, never appears in a request Kai can edit.
The response gives the player everything the post-run screen needs about themselves:
200 OK
{
"weekly": { "rank": 88416, "best": 1284500, "improved": true, "status": "accepted" },
"allTime": { "rank": 1042311, "best": 1350200, "improved": false, "status": "accepted" }
}
That is a new weekly best, so Kai jumps from 412,907 to 88,416. The all-time best stays 1,350,200, so improved: false and the rank is unchanged. status is per board, and both say accepted because Kai is nowhere near the top 1,000. A run that enters the top 1,000 on a board comes back provisional on that board alone. The player sees their new rank at once, but nobody else does until replay validation finishes, which takes ≤ 15 minutes. If the board step fails after the run is durable, the submit still succeeds with "ranksPending": true and null ranks.
The budget for this whole exchange is p99 ≤ 300 ms worldwide, of which ≤ 50 ms is server time in the home region. The rest is the trip from Manila.
Quick check before moving on:
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson