Datacentre REST API
The Soccerverse Datacentre REST API: read endpoints for clubs, players, users, market, fixtures, transfers, news and leaderboards, with request examples.
Most apps should start here. These read-only routes return clubs, players, users, the market, fixtures, leaderboards and more as JSON, with filters and paging, and they need no API key. To get everything one Soccerverse page shows in a single call, use the /v1 routes instead.
Base URL and access
- Base URL:
https://play.soccerverse.com/datacentre. Add the paths on this page to it, as in the Quick start. - Previously served from
https://services.soccerverse.com/api/..., a host that no longer resolves. To update old code, change the host and the prefix:/api/<path>becomes/datacentre/<path>. - Every route in the tables below is a
GETand needs no API key or login. Other methods return405. Responses are JSON except the CSV download. - OpenAPI spec (JSON, lists every route with its parameters):
/datacentre/openapi.json. It has no server URL, so when you import it into Postman or a code generator, set the server tohttps://play.soccerverse.com/datacentre. It also lists the/v1routes described in Related hosted endpoints. - Running your own node? This API is part of the hosted Soccerverse service on
play.soccerverse.comand is not included in a node you run yourself. A self-hosted node gives you the raw GSP JSON-RPC interface instead.
Quick start
# Health check
curl -sS \
"https://play.soccerverse.com/datacentre/healthz" | jq .
# Club lookup using the sample club_id
curl -sS \
"https://play.soccerverse.com/datacentre/clubs/detailed?club_id=50&per_page=5" | jq '.items[0]'
# Player lookup using the sample player_id
curl -sS \
"https://play.soccerverse.com/datacentre/players/detailed?player_id=1100&per_page=5" | jq '.items[0]'
# User lookup using the sample username
curl -sS \
"https://play.soccerverse.com/datacentre/users/detailed?names=snailbrain&per_page=5" | jq '.items[0]'
List routes return their rows in items, which is why these examples print .items[0].
Usage rules
- Stay under about 20 requests per second per IP address (short bursts of up to 40 are fine). Above that the API answers
429: slow down and retry. The/v1routes share the same limit. - A
503with aRetry-Afterheader means the service is briefly busy. Wait that many seconds, then retry. - Any website can call these routes from browser JavaScript (CORS is open).
- Most responses have no
ETagorCache-Controlheaders, so cache what you need on your side (the dump routes are the exception, see the dumps section below). Some routes are cached on the server for up to 30 minutes (for example/market), so their values can lag. - Large responses compress well. Send
Accept-Encoding: gzip(curl--compressed; Pythonrequestsdoes it for you)./dumps/share_ordersis 6.4 MB plain and 1.4 MB gzipped.
Pitfalls:
- Do not add a trailing slash: use
/clubs, not/clubs/. The server answers307with a redirect to a different, non-public address, and following it ends in a404HTML page. - Python's built-in
urllibis blocked by Cloudflare (403, bodyerror code: 1010) unless you set your ownUser-Agentheader, for examplemy-app/1.0.requests, curl, Node, Go and browsers work as they are.
Filters and sorting
- Several values. A parameter shown as
array[...]takes repeats:club_id=50&club_id=51ornames=snailbrain&names=DeepSeek. A parameter markedcomma listtakes commas:positions=GK,FC. Every other parameter takes one value. Mixing the styles fails quietly: commas in anarray[...]parameter give422or no rows, and repeating acomma listparameter keeps only its last value. - Typos. Most routes ignore a parameter name they do not know, so a typo returns unfiltered data (
/clubs/detailed?clubid=50returns every club)./playersand/players/detailedreject unknown names with400. Check names against the tables. - Sorting.
sort_orderisascordesc. The allowedsort_byvalues (ClubsSortBy,PlayersSortByand so on) are listed in the OpenAPI spec undercomponents.schemas, and in the422message you get for a bad value. - Seasons. Where a route takes a
season_id, the example on this page uses season 4. To get the current season, readseasonIdfrom/v1/bootstrap.
Common response and money notes
- Paging. Paged endpoints generally return
{ page, per_page, total, total_pages, items }./user_balance_sheetand/share_trade_historydo not count rows, so theirtotalandtotal_pagesarenull: request the nextpageuntilitemscomes back empty or shorter thanper_page. - Other shapes. Some data endpoints return raw arrays (for example
/countries,/transfers/basic,/messagesand/league_tables). Dump endpoints often return{ meta, data }or a file download. - SVC amounts.
balance,wages,value,last_price, earnings and other SVC amounts are whole numbers in units of 1/10,000 SVC. Divide by10000:1234567is123.4567 SVC. Counts and ratings are not scaled. - USDC amounts. Fields with
usdcin their name (for exampletotal_earnings_usdc) are already plain USDC amounts. To convert SVC yourself, use USDC = raw amount ÷ 10000 ×svc2usdc, wheresvc2usdcis the USDC price of one SVC. - Shop prices and
usd_spent. All prices on/shop/clubs(pricePerPack,current_priceincluding the ones insideshares, andpricing[].price) andusd_spenton the referral leaderboards are USDC × 1,000,000. Divide by1000000:39500000is39.5 USDC. - Other units. On
/market, the fields that start withSVCTradesare plain numbers, not scaled. The club earnings, club packs and seller-opportunity dumps state their units inmeta.description. - Errors. Errors are JSON
{ "detail": ... }:400or422for bad input,405for a wrong method,404for a path that does not exist.- A search that finds nothing is not an error. Most routes answer
200withtotal0and an emptyitemslist (or[]). - Only a few lookups of one item answer
404when it is missing:/clubs/{club_id}/job,/user_activity(withname),/share_balance_by_user_club,/league_tablesand/leaderboards/managers/history. - A
429does not come back as JSON, so check the status code before you parse the body. See Usage rules for429and503.
- A search that finds nothing is not an error. Most routes answer
System
Operational health of the public Datacentre app.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /healthz | Health check. Returns { "status": "ok" } when the service is up | None |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/healthz' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/healthz", timeout=30)
response.raise_for_status()
print(response.json())
Clubs
Club market, detailed club records, job postings and weekly club balance sheets.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /clubs | Influence market data. Only clubs with market data; /clubs/detailed has every club | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by ClubsSortBysort_order string default ascclub_id array[integer]country_id stringowned stringmanager_locked integerbalance_min integerbalance_max integer |
| GET | /clubs/detailed | Detailed data for every club | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by ClubsSortBysort_order string default ascclub_id array[integer]country_id stringowned stringmanager_locked integeravailable integerleague_id integerdivision integer (0 = top flight)has_job_posting integerbalance_min integerbalance_max integerdivision_start_min integerdivision_start_max integerfans_start_min integerfans_start_max integerfans_current_min integerfans_current_max integerstadium_size_start_min integerstadium_size_start_max integerstadium_size_current_min integerstadium_size_current_max integerstadium_id_min integerstadium_id_max integervalue_min integervalue_max integerrating_start_min integerrating_start_max integerdefault_formation_min integerdefault_formation_max integerpenalty_taker_min integerpenalty_taker_max integertransfers_in_min integertransfers_in_max integertransfers_out_min integertransfers_out_max integer |
| GET | /clubs/{club_id}/job | Retrieve job posting details for a specific club | club_id (required) integer |
| GET | /club_balance_sheet/weeks | Get club balance sheet entries by game week | club_id (required) integerseason_id (required) integer |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/clubs?club_id=50&per_page=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/clubs?club_id=50&per_page=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
/clubslists only clubs with market data, meaning their influence has been bought or sold at least once. Use/clubs/detailedto list every club./clubs/{club_id}/jobreturns404when the club has no public job posting. That just means there is no job to show.
Players
Player search/detail, historical transfers/loans/morale, field time and combined player history.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /players | Influence market data. Only players with market data; /players/detailed has every player | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by PlayersSortBysort_order string default ascage_min integerage_max integerage integerplayer_id array[integer]wages_min integerwages_max integerrating_min integerrating_max integervalue_min integervalue_max integercountry_id string (comma list allowed)owned stringpositions string (comma list of position codes)club_id integerfree_agents boolean default false (only players with no club; not together with club_id)allow_transfer integerallow_renew integer |
| GET | /players/detailed | Detailed data for every player | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by PlayersSortBysort_order string default ascage_min integerage_max integerage integerplayer_id array[integer]wages_min integerwages_max integercontract_min integercontract_max integerrating_min integerrating_max integerrating_gk_min integerrating_gk_max integerrating_tackling_min integerrating_tackling_max integerrating_passing_min integerrating_passing_max integerrating_shooting_min integerrating_shooting_max integerrating_aggression_min integerrating_aggression_max integerrating_stamina_min integerrating_stamina_max integervalue_min integervalue_max integerdesired_contract_min integerdesired_contract_max integercountry_id string (comma list allowed)owned stringpositions string (comma list of position codes)club_id integerposition_mask integer (a sum of position bits, see Pitfalls)position_mask_multi boolean default false (match every position the player can play, not just the main one)include_loaned boolean default falsefree_agents boolean default false (only players with no club; not together with club_id)allow_transfer integerallow_renew integerfitness integerretired integermorale integerinjured integerinjury_id integerposition integermulti_position integerability_gk integerability_tackling integerability_passing integerability_shooting integerbanned integercup_tied integeryellow_cards integerred_cards integeragent_name stringloan_offered stringloan_offer_accepted stringloaned_to_club string |
| GET | /player/history/{player_id} | Retrieve player history | player_id (required) integer |
| GET | /players/morale_history/{player_id} | Get morale change history for a player | player_id (required) integerlimit integer 1 to 100, default 10 |
| GET | /player/transfer_history | Retrieve transfer history. Needs at least one of season_id, club_id, player_id; without season_id it returns the latest season only | season_id integerclub_id integerplayer_id integer |
| GET | /players/loan_history | Retrieve loan history. Needs at least one of season_id, club_id; without season_id it covers all seasons | season_id integerclub_id integer |
| GET | /player_field_time/by-player/{player_id} | Current-season domestic-league field time for one player, one row per club | player_id (required) integer |
| GET | /player_field_time/{club_id} | The same figures for every player of a club (cached for 5 minutes) | club_id (required) integer |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/players?player_id=1100&per_page=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/players?player_id=1100&per_page=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
/playerslists only players with market data, meaning their influence has been bought or sold at least once. That leaves out most players, so a squad from/players?club_id=50can be incomplete. Use/players/detailedto list every player. Thefree_agents=truefilter is not affected.positionstakes position codes as a comma list, for examplepositions=GK,FC, and matches every player who can play any of those positions.position_mask(/players/detailedonly) is the same filter as a number: add up the bits of the positions you want (GK=1,LB=2,CB=4,RB=8,DML=16,DMC=32,DMR=64,LM=128,CM=256,RM=512,AML=1024,AMC=2048,AMR=4096,FL=8192,FC=16384,FR=32768), soposition_mask=16385isGKplusFC. On its own the mask checks only each player's main position, so it returns fewer players thanpositions. Addposition_mask_multi=trueand the two match exactly./player/transfer_historywith onlyseason_idreturns every transfer of that season (thousands of rows), so add aclub_idorplayer_id.- The field-time routes return
league_minutes,available_roundsandfield_time_pct.field_time_pctis minutes played as a percentage of the minutes available (available_roundsx 90), capped at 100.
Users/profile
User lookup, profile/trading details, achievements and balance-sheet/earnings views.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /users | Get user list and basic data | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by UsersSortBysort_order string default ascname_prefix stringnames array[string] |
| GET | /users/detailed | Get detailed user and trading data | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by UsersDetailedSortBysort_order string default ascname_prefix stringnames array[string]buy_volume_min integerbuy_volume_max integersell_volume_min integersell_volume_max integertotal_volume_min integertotal_volume_max integer |
| GET | /achievements | Get user achievements status | username (required) string |
| GET | /user_activity | Activity ranking. Without name it returns the top 50 ranked users; with name, just that user | name string |
| GET | /user_balance_sheet | Get user balance sheet entries | page integer default 1per_page 5, 10, 20, 50 or 100, default 50name (required) stringfrom_time integer (unix seconds, used together with to_time)to_time integer (unix seconds, used together with from_time) |
| GET | /user_balance_sheet/earnings | Get aggregated SVC earnings | name (required) string |
| GET | /user_balance_sheet/weeks | Get weekly aggregated user balance sheets | page integer default 1per_page integer 1 to 100, default 10name (required) string |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/users/detailed?names=snailbrain&per_page=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/users/detailed?names=snailbrain&per_page=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
/user_activityrefreshes about every 30 minutes and normally answers straight away. Rarely, just after a server restart, a request can take up to about 40 seconds or return503, so give this route a longer timeout, for example 60 seconds.- On
/user_balance_sheet,from_timeandto_timeonly work as a pair: at most 30 days apart (otherwise400). The whole range then comes back in one response, ignoringpageandper_page. A lonefrom_timeorto_timeis ignored.
Reference/leagues/countries
Reference country/league data and current league-table snapshots.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /countries | Retrieve data for countries | sort_by CountriesSortBysort_order string default desccountry_id string |
| GET | /leagues | Retrieve data for leagues (with 5-min cache) | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by LeaguesSortBysort_order string default asccountry_id string (comma list allowed)division integer (0 = top flight)league_id integerseason_id integer |
| GET | /league_tables | Get league table standings. Give league_id, or country_id together with division | league_id integercountry_id stringdivision integer (0 = top flight)season_id integer |
| GET | /dumps/leagues | All national leagues for the current season | None |
| GET | /dumps/league_tables | League tables for all divisions, optionally filtered to Division 1 (top flight) by country | country_ids array[string] |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/countries?country_id=ENG' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/countries?country_id=ENG", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
- League IDs are season-specific; prefer
country_id + division + season_idwhen linking historical data. divisioncounts from 0:division=0is the top flight,1the second tier, and so on (England currently has 0 to 9). The one exception is/dumps/league_tables?country_ids=..., which labels the top flightdivision: 1.
Market/trading
Market overview, SVC price, account/share balances, dilution events, recent trades, leader/rich lists and trading graphs.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /market | Obtain overall market metrics | None |
| GET | /svc_price | Current SVC to USDC price. Returns { "svc2usdc": ... }, the same value as SVC2USDC in /market, in a much smaller response | None |
| GET | /ticker | Get ticker data | None |
| GET | /rich_list | Retrieve the richest users | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20name stringsort_by RichListSortBy default total_networthsort_order string default desc |
| GET | /best_managers | Get best managers data | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by BestManagersSortBy default rank_a_rankingsort_order string default ascname string |
| GET | /share/transactions | Retrieve share transactions for a user | name (required) string |
| GET | /share_balance_by_user_club | Get share balance for a specific user and club | name (required) stringclub_id (required) integer |
| GET | /share_balances | Retrieve influence balances. Give one of name, club_id, player_id, club_id + name or player_id + name (share_type alone is not enough) | page integer default 1per_page 5, 10, 20, 50, 100 or 1000, default 20sort_by ShareBalancesSortBysort_order string default ascclub_id integerplayer_id integername stringshare_type club or playercountries boolean default false (needs name; returns a plain array of per-country totals instead of the paged wrapper)leagues boolean default false (needs name; the same, per league)country_id string (needs name)league_id integer (needs name)has_manager booleanhas_agent booleanmanager_last_active_unix_min integermanager_last_active_unix_max integeragent_last_active_unix_min integeragent_last_active_unix_max integer |
| GET | /share_balances/detailed | Retrieve detailed influence balances with position and earnings | page integer default 1per_page integer 5 to 100, default 20name (required) stringshare_type club or playershare_ids array[integer] (use with share_type)sort_by DetailedShareBalancesSortBysort_order string default deschas_manager booleanhas_agent booleanmanager_last_active_unix_min integermanager_last_active_unix_max integeragent_last_active_unix_min integeragent_last_active_unix_max integerissue string (needs share_type; any, or a name from /share_balances/issue_counts, for example no_manager)agent_name string (only players whose agent is this user)wage_multiplier number default 0 (only affects sort_by=wage_change; pass economy-moneybase-multiplier from params in /v1/bootstrap)search string (name substring, needs share_type) |
| GET | /share_balances/summary | Portfolio summary for one user: balance, net worth, club and player counts and values, 7-day and 30-day earnings | name (required) string |
| GET | /share_balances/active_proposals | Active proposals across all of one user's holdings | name (required) string |
| GET | /share_balances/issue_counts | Counts of portfolio issues (for example no_manager, low_balance) across one user's club or player holdings | name (required) stringshare_type (required) club or playeragent_name string (also counts the players whose agent is this user, shown as my_agent) |
| GET | /share_trade_history | Retrieve share trade history. Needs at least one of name, club_id, player_id | page integer default 1per_page integer 1 to 100, default 50name stringclub_id integerplayer_id integersort_by stringsort_order string default desc |
| GET | /share_trade_history/all | Most recent trades (default 20) | per_page integer 1 to 100, default 20 |
| GET | /dilutions | Dilution events with their contributions, state and totals | page integer default 1per_page integer 1 to 5000, default 100share_type string (for example club)share_id integername string (contributor)state active, finished, success or failedsort_by total_raised, price, influence_created or datesort_order string default asc |
| GET | /trading_graph | Retrieve aggregated trading data. Give exactly one of club_id or player_id | club_id integerplayer_id integertime_range (required) 1d, 7d, 30d, 90d, 6m or 1y |
| GET | /trading_graph/all | Retrieve daily and monthly payouts data | None |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/market' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/market", timeout=30)
response.raise_for_status()
print(response.json())
Datacentre dumps/snapshots
Pre-calculated bulk snapshots for earnings, pack deals and order books. These can be larger than normal paged API responses.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /dumps/club_earnings | Pre-calculated club earnings for buyers | None |
| GET | /dumps/club_earnings_light | Simplified club earnings (club_id → SVC per influence per season) | None |
| GET | /dumps/club_packs | Club pack deals | None |
| GET | /dumps/club_seller_opportunities | Pre-calculated club seller opportunities | None |
| GET | /dumps/player_earnings | Player earnings and ROI analysis | threshold (required) one of 2, 3, 4, 5, 6, 7, 8, 10, 12, 15 or 20 (anything else is 400)country stringdivision integer (0 = top flight)min_rating integermax_rating integerposition stringmin_age integermax_age integermin_buyable integerplayer_id integermin_match_time numbermax_match_time numbersort string default paybackorder string default ascpage integer default 1limit integer 1 to 500, default 100 |
| GET | /dumps/share_orders | All share orders (clubs + players combined) | None |
| GET | /dumps/share_orders/clubs | Club share orders (optionally filtered by ID) | ids array[integer] |
| GET | /dumps/share_orders/players | Player share orders (optionally filtered by ID) | ids array[integer] |
| GET | /dumps/share_orders/json | Download share_orders as JSON | None |
| GET | /dumps/share_orders/csv | Download share_orders as CSV | None |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/dumps/player_earnings?threshold=10&limit=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/dumps/player_earnings?threshold=10&limit=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
- Dump endpoints can be large; prefer filtered endpoints (
ids,threshold,limit) where available. - Most whole-file dumps (for example
/dumps/club_packs) send anETagandCache-Control: no-cache. Send theETagback in anIf-None-Matchheader and you get a304with no body while the data has not changed. /dumps/share_orders/jsonand/dumps/share_orders/csvgive the same order book as/dumps/share_orders, as a file download (JSON or CSV).
Shop datacentre
Pack-sale data for clubs, from the Soccerverse shop.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /shop/clubs | Retrieve pack-sale data for clubs. One row per pack | page integer default 1per_page integer 1 to 100, default 20tiers array[integer]country_ids array[string]club_ids array[integer]pricePerPack_min integer (USDC × 1,000,000)pricePerPack_max integer (USDC × 1,000,000)sort_by ShopClubsSortBysort_order string default asc |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/shop/clubs?club_ids=50&per_page=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/shop/clubs?club_ids=50&per_page=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
- A pack holds one main club plus several others, listed in
shares. Soclub_ids=50returns every pack that contains influence in club 50, and only one of those is club 50's own pack (the row whereclub_idis50). - Every price in the response is USDC × 1,000,000:
pricePerPack,current_price(also insideshares) and eachpricing[].price. For example, apricePerPackof39500000is39.5 USDC. - Use
per_pageand the filters to keep responses small.
Transfers
Recent completed transfers and transfer-count summaries.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /transfers/basic | Get latest completed transfers | None |
| GET | /transfers/counts | Get transfer counts for a club in a season | club_id (required) integerseason_id (required) integer |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/transfers/basic' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/transfers/basic", timeout=30)
response.raise_for_status()
print(response.json())
Fixtures/commentary
Fixture commentary, match events, player stats and tactics snapshots.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /commentary/match_commentary/{fixture_id} | Get match commentary for a fixture | fixture_id (required) integer |
| GET | /commentary/match_events/{fixture_id} | Get match events for a fixture | fixture_id (required) integer |
| GET | /fixture_history/players/{fixture_id} | Get fixture player data for a fixture | fixture_id (required) integer |
| GET | /fixture_history/tactics/{fixture_id} | Get fixture tactics data for a fixture | fixture_id (required) integer |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/commentary/match_commentary/1' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/commentary/match_commentary/1", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
- The examples use fixture
1. Replace it with thefixture_idyou want.
Messages/news
Blockchain/game messages/news filtered by season, country, competition or club.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /messages | Get messages from the blockchain. Needs season_id plus at least one of country_id, comp_id, club_id | season_id (required) integercountry_id stringcomp_id integerclub_id integerlimit integer 1 to 10000, default 500 |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/messages?season_id=4&club_id=50&limit=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/messages?season_id=4&club_id=50&limit=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
season_idis required, and so is at least one ofcountry_id,comp_idorclub_id(otherwise400).limitdefaults to500and is capped at10000; add a smalllimitto avoid very large responses.
Leaderboards
Earnings, referral, manager and scout leaderboards.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /leaderboards/earnings | Earnings leaderboard over 7 or 30 days (top 10, or a paged board up to 200 deep) | days integer, 7 or 30, default 30 (anything else is 400)page integer, from 1per_page 5, 10, 20, 50 or 100, default 10name string |
| GET | /leaderboards/earnings/lifetime | All-time payouts leaderboard (up to 200 rows) | scope all (default), club or playerpage integer default 1per_page 5, 10, 20, 50 or 100, default 10name string |
| GET | /leaderboards/managers | Managers leaderboard: titles, cups, promotions and form (up to 200 rows) | page integer default 1per_page 5, 10, 20, 50 or 100, default 10view honours (default), form or streaksseason all (default) or a season id from the seasons list in the responsename string |
| GET | /leaderboards/managers/history | One manager's career: summary, every season managed and career spells. 404 if the name is not on the board | name (required) string |
| GET | /leaderboards/scouts | Scouts leaderboard: the rating gained by the players a user bought early (up to 200 rows) | page integer default 1per_page 5, 10, 20, 50 or 100, default 10sort score (default), total_gain or avg_gainname string |
| GET | /leaderboards/scouts/picks | Best individual scouting picks (up to 200 rows) | page integer default 1per_page 5, 10, 20, 50 or 100, default 10 |
| GET | /leaderboards/referrals/all | All-time referral leaderboard (up to 200 rows) | None |
| GET | /leaderboards/referrals/windowed | Referral leaderboard over a window (up to 200 rows) | window string: 30d (default, rolling) or season (current season to date); anything else is 400 |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/leaderboards/earnings?days=30' | jq .
curl -sS \
'https://play.soccerverse.com/datacentre/leaderboards/referrals/windowed?window=season' | jq '.entries[0]'
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/leaderboards/earnings?days=30", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
/leaderboards/earningshas two shapes. With none ofpage,per_pageornameyou get the top 10 as{ days, svc2usdc, entries }. With any of them you get the paged board{ days, svc2usdc, page, per_page, total, updated_at, entries, you }.- On the paged boards (earnings with paging, lifetime, managers, scouts), pass
nameto also get that user's own ranked row asyouwhen they fall outside the page. The paged boards are 200 rows deep, so apagepast row 200 returns400(for examplepage=41withper_page=5). - In
/leaderboards/earnings,total_earnings,club_earningsandplayer_earningsare raw SVC (divide by10000);total_earnings_usdcis already in USDC. - The referral boards return
{ window, updated_at, entries }. Each entry hasrank,account,referrals,bonus_shares,usd_spent,last_active_unixandlast_active, ranked bybonus_shares.usd_spentis USDC × 1,000,000: divide by1000000.
Votes/proposals
Active and historical proposal/vote views, finished-proposal results and graph data.
| Method | Path | Purpose | Main query/path parameters |
|---|---|---|---|
| GET | /proposals/active | Get currently active proposals | page integer default 1per_page integer 1 to 5000, default 100proposal_type agent, manager or unlockshare_type club or playerstage_filter proposal or votingclub_id integerplayer_id integername string |
| GET | /proposals/graph | Get daily proposal completion counts for graphing | days_back integer 1 to 90, default 30 |
| GET | /proposals/historical | Get proposals that ended in the last N days with daily statistics | days_back integer 1 to 30, default 7proposal_type agent, manager or unlockshare_type club or playerclub_id integerplayer_id integername string |
| GET | /proposals/finished | Finished proposals for a batch of clubs or players, with the frozen votes and the winner | shares (required) string, comma list of type:id pairs, at most 100 (for example club:50,player:1100) |
| GET | /proposals/outcomes | Final votes per option and the winner of finished proposals. Give either ids, or share_type with share_id (otherwise 400) | ids string, comma list of proposal ids, at most 200share_type club or playershare_id integer |
Example curl:
curl -sS \
'https://play.soccerverse.com/datacentre/proposals/active?per_page=5' | jq .
Example Python:
import requests
response = requests.get("https://play.soccerverse.com/datacentre/proposals/active?per_page=5", timeout=30)
response.raise_for_status()
print(response.json())
Pitfalls:
- A club or player with no active proposals returns
total0and an emptyitemslist. That is normal, not an error.
Related hosted endpoints
The same service, play.soccerverse.com, also offers:
/v1routes.GETroutes that each return everything one page of the Soccerverse site needs in a single call. Use them for page-sized reads, for examplehttps://play.soccerverse.com/v1/club/50,/v1/player/1100,/v1/user/snailbrain,/v1/home,/v1/transfer-marketand/v1/search?q=snail. They allow requests from any website and share the rate limit above. Their shapes follow the Soccerverse site, so they can change. All of them are listed in the OpenAPI spec.POST /v1/gsp. A cached JSON-RPC proxy for reading raw game state. Use it only when a JSON-RPC method has no route in this API: see GSP JSON-RPC./events. A live update stream (Server-Sent Events) that tells you when to reload data. It works from server-side code; browsers on other websites are blocked. See Realtime Events.