These developer docs are available in English only. View in English
GSP JSON-RPC
The Soccerverse GSP JSON-RPC interface: read methods and game-state envelope semantics, with request and response examples.
Purpose
The GSP (game-state processor) API exposes Soccerverse game-state data via JSON-RPC 2.0. That includes seasons, leagues, cups, squads, fixtures, tactics, transfers/auctions, manager history, votes, and share orderbooks.
Most apps should start with the Datacentre REST API, which has filters, paging and joined rows. For a whole page of data in one call, such as /v1/club/50 or /v1/player/1100, use the /v1 bundles from the overview. Use /v1/gsp only when a JSON-RPC method has no REST equivalent. It returns the raw game state: numeric ids, raw integer money values, Unix timestamps and a blockchain state envelope. Ids map to names through the datapack.
This page uses the public endpoints on play.soccerverse.com. If you run your own node, see Running your own node.
Base URL
Use this endpoint. It needs no API key and serves the methods most apps need:
POST https://play.soccerverse.com/v1/gsp
Write it exactly like that, with no trailing slash: /v1/gsp/ does not work.
Older docs and integrations used services.soccerverse.com/gsp/, which no longer exists: use /v1/gsp instead. Do not build on https://play.soccerverse.com/gsp either: it is an older, uncached endpoint that is being retired, with no stability promise.
Protocol
- Transport: HTTPS
POSTwith a JSON body.GETreturns405. - Content type:
application/json - JSON-RPC version:
2.0 - No authentication and no API key.
- Send a
User-Agentheader that names your app, for examplemy-app/1.0. Requests that use the default Pythonurllibagent are rejected with HTTP403. Browsers set their own and are not affected. paramsmust be a JSON object, or left out. An array gives error-32602.- Browsers can call
/v1/gspdirectly: it accepts requests from any origin. - Batches: to send several calls at once,
POSTa JSON array of calls./v1/gspaccepts up to 100 calls and 256 KiB per request. Replies come back in request order, but still match them byid. - Limit, per client IP address: 20 requests per second (bursts of 40), shared with all
/v1/*and/datacentre/*calls. A batch counts as one request. Past the limit the server answers HTTP429, which is not a JSON-RPC error. Slow down and retry.
Request shape:
{
"jsonrpc": "2.0",
"method": "get_seasons",
"id": 1
}
Request with params:
{
"jsonrpc": "2.0",
"method": "get_squad",
"params": { "club_id": 50 },
"id": 2
}
Response shape:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"blockhash": "...",
"chain": "polygon",
"data": [ ... ],
"gameid": "sv",
"height": 94635948,
"state": "up-to-date",
"version": "44fb30c65872fb59f5ca51d2d1540cd80c47b816"
}
}
Most useful payloads are in result.data. A few methods still return object payloads in result.data rather than lists. Always check the JSON-RPC error member before reading result.
State envelope fields
The get_* methods return a wrapper around the game data.
| Field | Meaning |
|---|---|
result.data | The actual method payload. Usually a list; sometimes an object, or null when there is nothing to return. |
result.height | Block height of the state behind this response. Treat it as the consistency marker for cache/debugging, not a fixture/gameweek number. It can be behind the chain head: see How fresh is the data. |
result.blockhash | Block hash for the indexed state behind the response. |
result.chain | Chain name. Returns polygon. |
result.gameid | Game id. Returns sv. |
result.state | up-to-date in normal operation. Anything else means the data may be behind. When a node has no state yet, height and blockhash can be missing. |
result.version | Commit of the GSP build that answered. Not always present: /v1/gsp leaves it out of some answers, so do not rely on it. |
Callers should display or degrade carefully when result.state is not up-to-date.
Pitfall: the Soccerverse MCP tools return only the payload. When you call GSP directly you get the full envelope and read result.data yourself.
How fresh is the data
/v1/gsp answers from a cache, so result.height is the height of the copy you received and can be behind the chain head. Live club, squad, market and orderbook reads are usually within a few seconds. Seasons, leagues, associations and game parameters can be up to about an hour old. Two calls in a row can also be answered by different servers, so height can differ a little between them.
- Current head: call
getnullstate. It returns the headheightand the node'sstate, and is never cached. - Just sent a transaction? Add the header
X-GSP-Min-Height: <height>to a/v1/gspcall and it will not answer from a cached copy older than that height. If the server has not reached that height yet, you get its current state, so checkheight. A value that is not a number gets HTTP400. - Waiting for something to change: poll
getnullstatefor a newheight. Server-side apps can use the events stream instead.
Example: list seasons
curl -sS https://play.soccerverse.com/v1/gsp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"get_seasons","id":1}'
Response, trimmed to the row for season 4. The real list has one row per season:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockhash": "4221174b0bd316751a332686d777d390db2763f06eb681d4c356a6110acc743b",
"chain": "polygon",
"data": [
{
"end": 1798848000,
"finished": false,
"name": 0,
"number": 4,
"season_id": 4,
"start": 1783123200
}
],
"gameid": "sv",
"height": 94634097,
"state": "up-to-date"
}
}
To find the current season, read seasonId from GET https://play.soccerverse.com/v1/bootstrap.
Python example: unwrapping result.data
import json
import urllib.request
url = "https://play.soccerverse.com/v1/gsp"
payload = {
"jsonrpc": "2.0",
"method": "get_squad",
"params": {"club_id": 50},
"id": 1,
}
request = urllib.request.Request(
url,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json", "User-Agent": "my-app/1.0"},
method="POST",
)
with urllib.request.urlopen(request, timeout=20) as response:
body = json.loads(response.read().decode("utf-8"))
if "error" in body:
raise RuntimeError(body["error"])
envelope = body["result"]
players = envelope["data"]
print(envelope["height"], envelope["state"], len(players))
get_squad for club_id=50 returns a list of players. First-player keys include player_id, club_id, country_id, position, rating, rating_gk, rating_tackling, rating_passing, rating_shooting, rating_stamina, rating_aggression, fitness, morale, wages, value, loaned_to_club, injured, banned, and card counters.
Method catalogue
Every method below only reads game state. The Params column is a working sample of the params object. It uses the sample ids from the overview (club 50, player 1100, user snailbrain) and season 4 where a value is needed. The one exception is get_game_world_history, which only has rows for a finished season, so its sample uses season 3.
The On /v1/gsp column says whether the hosted endpoint serves the method. Raw only methods are not served there. They belong to the raw GSP interface that a node you run exposes (see Running your own node).
On the hosted service, look for the same data in the Datacentre REST API instead. For example, GET https://play.soccerverse.com/datacentre/league_tables?league_id=1665 replaces get_league_table.
Methods
Tactics
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_club_tactics | Yes | {"club_id":50} | Returns {commitment: <hash>} if the club has committed tactics (the contents stay hidden), otherwise an object with tactic_actions, team_sheet and validation. null if the club does not exist. |
Helper/Metadata
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
getnullstate | Yes | {} | Returns the envelope without data (blockhash, chain, gameid, height, state, version): the chain head, and whether the node is up to date. Never cached. |
get_extfile | Raw only | {"hash":"0000000000000000000000000000000000000000000000000000000000000000"} | Returns external-file availability metadata for a content hash; object with keys: exists, hash. |
get_params | Yes | {"name":""} | Returns game parameter values, optionally by name; object with parameter keys such as agent-min-bps, ban-length-yellowred, coins-to-club-multiplier-bps, dilution-max-bps, and more. |
Clubs/Squads
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_club_ids | Raw only | {} | Lists all club ids; returns a list of {"club_id": ...} objects. |
get_squad | Yes | {"club_id":50} | Returns players owned/loaned by a club; returns a list. |
get_club_schedule | Yes | {"club_id":50,"season_id":4} | Returns club fixtures for a season; returns a list. |
get_club | Yes | {"club_id":50} | Returns club state by club id; object with keys: away_colour, balance, club_id, country_id, default_formation, fans_current, fans_start, form, home_colour, manager_locked, and more. |
get_club_extended | Yes | {"club_id":50} | Returns club state plus squad transfer/loan counters; object with keys: away_colour, balance, club_id, country_id, default_formation, fans_current, fans_start, form, home_colour, loans, and more. |
get_stadiums_club | Raw only | {"stadium_id":555} | Returns club(s) for a stadium id; returns a list. |
get_managers_club | Yes | {"manager_name":"snailbrain"} | Returns club managed by a manager name; object with keys: away_colour, balance, club_id, country_id, default_formation, fans_current, fans_start, form, home_colour, manager_locked, and more. |
get_all_clubs | Raw only | {} | Returns all club rows; returns a list. |
get_club_balance_sheet | Raw only | {"club_id":50,"season_id":4} | Returns balance-sheet rows for a club and season; returns a list. |
get_clubs_league | Raw only | {"club_id":50} | Returns league ids associated with a club; returns a list of {"league_id": ...} objects. |
get_clubs_next_fixture | Raw only | {"club_id":50} | Returns next fixture object for a club; object with keys: attendance, away_club, away_goals, away_manager, comp_type, country_id, date, fixture_id, home_club, home_goals, and more. |
get_clubs_last_fixture | Raw only | {"club_id":50} | Returns last fixture object for a club; object with keys: attendance, away_club, away_goals, away_manager, away_pen_score, comp_type, country_id, date, fixture_id, home_club, and more. |
get_all_stadium_data_ids | Raw only | {} | Lists all stadium ids; returns a list of {"stadium_id": ...} objects. |
get_clubs_transfer_auctions | Yes | {"club_id":50} | Returns outgoing transfer auctions for a club; returns a list. |
get_clubs_transfer_bids | Yes | {"club_id":50} | Returns transfer auctions with bids from a club; returns a list. |
get_clubs_player_loan_offers | Yes | {"club_id":50} | Returns loan offers for a club; returns a list. |
get_comp_history_by_club | Yes | {"club_id":50} | Returns competition-history rows for a club; returns a list. |
get_manager_history_by_club | Yes | {"club_id":50} | Returns manager-tenure history for a club; returns a list. |
get_all_managers | Raw only | {} | Returns all manager names/rows; returns a list. |
Players
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_player_payouts | Raw only | {"player_id":1100} | Returns derived payout values for a player; returns a list. |
get_players | Yes | {"player_ids":[1100]} | Returns player records for up to 100 ids per call; returns a list. Ids with no player record are left out. More than 100 ids in one call is refused. |
get_agents_players | Yes | {"agent_name":"snailbrain"} | Returns players represented by an agent name; returns a list. |
get_comp_player_data | Yes | {"player_id":1100} | Returns league/cup stat rows for one player; object with keys: cups, leagues. |
get_league_top_players | Yes | {"league_id":1665} | Returns player leaderboard/stat rows for a league; returns a list. |
get_player_loan_offer | Raw only | {"player_id":1100} | Returns a loan offer for a player. |
To search players by rating, age, country or position, or to list free agents, use the Datacentre REST API instead: GET https://play.soccerverse.com/datacentre/players/detailed, with filters such as rating_min, rating_max, age_min, age_max, country_id, positions and free_agents=true.
Users/Shares/Market
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_user_wages | Raw only | {"id":1100,"season_id":4,"wage_type":"agent"} | Returns derived agent or manager wage estimate for a player/club; returns a list. |
get_best_managers | Raw only | {} | Returns every manager-tenure history row (all managers, all clubs), highest points first; returns a list. About 7 MB. For a ranked list of managers use /datacentre/best_managers; for one manager, get_manager_history_by_manager. |
get_manager_history_by_manager | Yes | {"name":"snailbrain"} | Returns manager-tenure history for a manager; returns a list. |
get_user_account | Yes | {"name":"snailbrain"} | Returns one user account row; object with keys: balance, last_active, name. |
get_users_last_active | Raw only | {"names":["snailbrain"]} | Returns last-active info for user names; returns a list. |
get_vaults | Yes | {"controller":"snailbrain","ids":[1,2,3]} | Returns vault rows by controller and ids; returns a list. |
get_vaults_by_founder | Raw only | {"founder":"snailbrain"} | Returns vault rows by founder; returns a list. |
get_user_share_balances | Yes | {"name":"snailbrain"} | Returns share balances for a user; returns a list. |
get_share_owners | Raw only | {"share":{"club":50}} | Returns owners for a share; returns a list. |
get_user_share_orders | Yes | {"name":"snailbrain"} | Returns active share orders for a user; returns a list. |
get_share_orderbook | Yes | {"share":{"club":50}} | Returns current orderbook for a share; object with keys: ask, bid, share. |
get_share_overview | Yes | {"type":"club","id":50,"since":0} | Returns share overview data by type/id/since; returns a list. |
get_share_dilutions | Yes | {"user":"snailbrain","type":"","id":0} | Returns share-dilution events; returns a list. All three params are required: pass an empty string for user or type, or 0 for id, to skip that filter. |
Competitions/Fixtures
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_all_turns | Yes | {"comp_id":1665} | Returns turns/gameweeks for a competition id; returns a list. |
get_fixture | Yes | {"fixture_id":363277} | Returns fixture details/stats for a fixture id; returns a list. |
get_league_table | Raw only | {"league_id":1665} | Returns table rows for a league id; returns a list. |
get_turn_fixtures | Yes | {"turn_id":45362} | Returns fixtures in a turn; returns a list. |
get_associations | Yes | {"association_type":"national"} | Returns association config rows by type; returns a list. |
get_association | Raw only | {"country_id":"ENG"} | Returns association config rows by country id; returns a list. |
get_association_qualifiers | Raw only | {"association_id":255} | Returns qualifier country/count rows for an association; returns a list. |
get_leagues | Yes | {"season_id":4} | Returns leagues for a season; returns a list. |
get_leagues_by_country | Raw only | {"country_id":"ENG","season_id":4} | Returns leagues for country and season; returns a list. |
get_league | Yes | {"league_id":1665} | Returns league details; returns a list. |
get_cups | Yes | {"season_id":4} | Returns cups for a season; returns a list. |
get_cups_by_country | Raw only | {"country_id":"ENG","season_id":4} | Returns cups for country and season; returns a list. |
get_cup | Raw only | {"cup_id":1675} | Returns cup details; returns a list. |
get_seasons | Yes | {} | Returns available seasons; returns a list. |
get_season | Raw only | {"season_id":4} | Returns one season row; returns a list. |
get_comp_history_by_manager | Raw only | {"name":"snailbrain"} | Returns competition-history rows for a manager; returns a list. |
Other
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_match_subs | Raw only | {"fixture_id":363277} | Returns substitutions for a fixture; returns a list. |
get_game_world_history | Raw only | {"season_id":3} | Returns game-world history rows for a finished season; returns a list. |
Votes/Proposals
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_all_votes | Yes | {} | Returns all proposal/vote rows; returns a list. |
get_votes_for_shareholder | Raw only | {"name":"snailbrain"} | Returns votes relevant to a shareholder name; returns a list. |
get_share_proposals | Yes | {"share":{"club":50}} | Returns proposals for a share; returns a list. |
Transfers/Loans
| JSON-RPC method | On /v1/gsp | Params | Returns |
|---|---|---|---|
get_top_transfer_auctions | Yes | {"num":3} | Returns top active transfer auctions; returns a list. |
get_transfer_auction_details | Yes | {"player_id":1100} | Returns an active auction detail and bids for a player; object with keys: agent_name, bids, club_id, concerns, contract, country_id, dob, free_with_no_bids, high_bid, injured, and more. null if the player has no active auction. To see a real one, take a player_id from get_top_transfer_auctions. |
Worked examples
Send these to https://play.soccerverse.com/v1/gsp.
get_comp_player_data example
Returns cup/league stat arrays for player 1100.
{
"jsonrpc": "2.0",
"method": "get_comp_player_data",
"id": 1,
"params": {
"player_id": 1100
}
}
Sample result.data shape, with each list trimmed to one row:
{
"cups": [
{
"Active": 1,
"apearances": 1,
"assists": 1,
"ave_rating": 7.0,
"clean_sheets": 0,
"club_id": 50,
"comp_id": 1675,
"comp_type": 1,
"country_id": "ENG",
"goals": 0,
"key_passes": 0,
"key_tackles": 0,
"minutes_played": 59,
"mom": 0,
"player_id": 1100,
"red_cards": 0,
"saves": 0,
"season_id": 4,
"shots": 0,
"sub_apearances": 0,
"yellow_cards": 0,
"yellowred_cards": 0
}
],
"leagues": [
{
"Active": 1,
"apearances": 17,
"assists": 0,
"ave_rating": 6.764705882352941,
"clean_sheets": 0,
"club_id": 50,
"comp_id": 1665,
"comp_type": 0,
"country_id": "ENG",
"goals": 6,
"key_passes": 0,
"key_tackles": 0,
"minutes_played": 1088,
"mom": 0,
"player_id": 1100,
"red_cards": 0,
"saves": 0,
"season_id": 4,
"shots": 0,
"sub_apearances": 1,
"yellow_cards": 2,
"yellowred_cards": 0
}
]
}
get_share_orderbook example
Returns an orderbook object with singular bid and ask arrays, plus the share it belongs to.
{
"jsonrpc": "2.0",
"method": "get_share_orderbook",
"id": 2,
"params": {
"share": {
"club": 50
}
}
}
Sample result.data shape, with the lists trimmed:
{
"ask": [
{
"mint": false,
"name": "Theramoe",
"num": 82,
"price": 390000
}
],
"bid": [
{
"mint": false,
"name": "Johnelo",
"num": 958,
"price": 157600
},
{
"mint": false,
"name": "OrtechoOscar",
"num": 1,
"price": 33400
},
{
"mint": false,
"name": "Cthulhu",
"num": 1000,
"price": 11000
}
],
"share": {
"club": 50
}
}
Error handling
A JSON-RPC error comes back with HTTP 200 and an error member instead of result. A method /v1/gsp does not serve looks like this:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "method not allowed: get_league_table"
}
}
Other failures you can meet on /v1/gsp:
| HTTP | What you get | What it means |
|---|---|---|
| 200 | Error -32601 with a message ending in unsafe methods not enabled: ... | The public service switches this call off, for example get_players with over 100 ids. |
| 200 | Error -32602, params must be an object | You sent params as an array. |
| 200 | Error -32602, INVALID_PARAMS: Invalid method parameters ... | A required param is missing, misspelled or has the wrong type. |
| 400 | {"detail":"invalid JSON"} or {"detail":"empty batch"} | The body is not valid JSON, or it is an empty array. |
| 400 | {"detail":"invalid X-GSP-Min-Height"} | The X-GSP-Min-Height header is not a number. |
| 403 | error code: 1010 | Your User-Agent is blocked. Send one that names your app. |
| 405 | {"detail":"Method Not Allowed"} | You used GET. Use POST. |
| 413 | {"detail":"batch too large (max 100)"} or {"detail":"request body too large"} | Send fewer calls per request, or a smaller body. |
| 429 | Not JSON-RPC | You are over the rate limit. See Protocol. |
Callers should:
- Check the HTTP status. If it is not
200, the body may not be JSON-RPC. - Parse JSON.
- If top-level
errorexists, handle it and do not readresult. - If
result.stateis notup-to-date, warn or avoid making strong current-state claims. - Read
result.datafor the payload.
Notes
- GSP returns ids, not names. Expect ids such as
club_id,player_id,league_id,stadium_id; look names up in the datapack. - Unix timestamps in payloads are seconds, not milliseconds.
dateappears on fixtures and turns; do not assume a generictimestampfield.- Empty arrays are valid for no active bids, auctions, orders, manager history, share dilutions, or qualifiers.
nullis valid when a single record does not exist, for example an unknown club id (get_club,get_club_tactics), a user who manages no club (get_managers_club), a player with no auction (get_transfer_auction_details) or no loan offer (get_player_loan_offer). - Unknown ids are not errors.
get_user_accountfor an unknown user name returns an object with zero balances andlast_active: null, notnull. Missing or wrongly named params are errors (-32602). The HTTP status stays200either way. - A few Raw only methods return a lot of data:
get_best_managers(about 7 MB),get_all_clubs(about 2 MB),get_game_world_history(about 0.5 MB) andget_all_managers(about 170 KB). Avoid calling them repeatedly. For clubs, the Datacentre REST API returns paged rows:GET https://play.soccerverse.com/datacentre/clubs/detailed. - Stat rows keep the game's own spellings, such as
apearancesandsub_apearances. Use them exactly as returned. - Money values (balances, wages, values, prices) are whole numbers in units of 1/10,000 SVC: divide by
10000to get SVC. In the orderbook example, apriceof390000is 39 SVC. See Money and value scaling in the overview. Only some MCP tools return formatted SVC strings. - Share params are objects such as
{"club": 50}or{"player": 1100}. MCP schemas may expose friendlier strings likeclub_50, but GSP expects the object form.
Running your own node
Everything above is the public service on play.soccerverse.com, apart from the Raw only methods. If you run your own node, you talk to the game server (the GSP) directly, with nothing in front of it.
- JSON-RPC: the GSP Docker image serves it on port
8600(POST http://localhost:8600/, plain HTTP, JSON-RPC 2.0), by default only from inside its own container. To reach it from outside, start the node with--nogame_rpc_listen_locally. Every method in the catalogue exists there, and the curl and Python examples above work if you swap in your node's URL. Theget_*methods take named params (an object): a positional array givesINVALID_PARAMS. A method the node does not have gives error-32601(METHOD_NOT_FOUND). - Status: the image also serves
GET http://localhost:8700/stateandGET http://localhost:8700/healthz./statereturns the headheightand the node'sstate, likegetnullstate./healthzreturns the textok, or HTTP500while the node is not up to date. - New blocks:
waitforchange(not on/v1/gsp) is a long poll: pass the last block hash you know as a positional array,["<blockhash>"], and it returns the newest block hash. See Realtime events for the loop. - Nothing in front: there is no
/v1,/datacentre,/eventsor/graph, and no allowlist, cache, rate limit or batch limit. Those belong to the public service. A node runs 50 worker threads by default, so throttle your own callers. - Switched off by default:
get_freebench,get_all_users,get_player_ids,get_playerswith more than 100 ids,compressjobpost(a helper that compresses the text of a club job posting) and the admin callsstop,checkdb,hashcurrentstateandsettargetblockonly work if you start the node with--unsafe_rpc. Use that flag only on a private node that nobody else can reach. The public service keeps them off. From GSP v1.4.2 a node keeps them off by default too; older versions had them on. - Browsers: the RPC port answers calls from any website (
Access-Control-Allow-Origin: *), so expose it only to networks you trust.