تخطي إلى المحتوى الرئيسي
Loading market data…
SoccerverseSoccerverse

These developer docs are available in English only. View in English

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 GET and needs no API key or login. Other methods return 405. 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 to https://play.soccerverse.com/datacentre. It also lists the /v1 routes described in Related hosted endpoints.
  • Running your own node? This API is part of the hosted Soccerverse service on play.soccerverse.com and 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 /v1 routes share the same limit.
  • A 503 with a Retry-After header 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 ETag or Cache-Control headers, 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; Python requests does it for you). /dumps/share_orders is 6.4 MB plain and 1.4 MB gzipped.

Pitfalls:

  • Do not add a trailing slash: use /clubs, not /clubs/. The server answers 307 with a redirect to a different, non-public address, and following it ends in a 404 HTML page.
  • Python's built-in urllib is blocked by Cloudflare (403, body error code: 1010) unless you set your own User-Agent header, for example my-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=51 or names=snailbrain&names=DeepSeek. A parameter marked comma list takes commas: positions=GK,FC. Every other parameter takes one value. Mixing the styles fails quietly: commas in an array[...] parameter give 422 or no rows, and repeating a comma list parameter 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=50 returns every club). /players and /players/detailed reject unknown names with 400. Check names against the tables.
  • Sorting. sort_order is asc or desc. The allowed sort_by values (ClubsSortBy, PlayersSortBy and so on) are listed in the OpenAPI spec under components.schemas, and in the 422 message 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, read seasonId from /v1/bootstrap.

Common response and money notes

  • Paging. Paged endpoints generally return { page, per_page, total, total_pages, items }. /user_balance_sheet and /share_trade_history do not count rows, so their total and total_pages are null: request the next page until items comes back empty or shorter than per_page.
  • Other shapes. Some data endpoints return raw arrays (for example /countries, /transfers/basic, /messages and /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 by 10000: 1234567 is 123.4567 SVC. Counts and ratings are not scaled.
  • USDC amounts. Fields with usdc in their name (for example total_earnings_usdc) are already plain USDC amounts. To convert SVC yourself, use USDC = raw amount ÷ 10000 × svc2usdc, where svc2usdc is the USDC price of one SVC.
  • Shop prices and usd_spent. All prices on /shop/clubs (pricePerPack, current_price including the ones inside shares, and pricing[].price) and usd_spent on the referral leaderboards are USDC × 1,000,000. Divide by 1000000: 39500000 is 39.5 USDC.
  • Other units. On /market, the fields that start with SVCTrades are plain numbers, not scaled. The club earnings, club packs and seller-opportunity dumps state their units in meta.description.
  • Errors. Errors are JSON { "detail": ... }: 400 or 422 for bad input, 405 for a wrong method, 404 for a path that does not exist.
    • A search that finds nothing is not an error. Most routes answer 200 with total 0 and an empty items list (or []).
    • Only a few lookups of one item answer 404 when it is missing: /clubs/{club_id}/job, /user_activity (with name), /share_balance_by_user_club, /league_tables and /leaderboards/managers/history.
    • A 429 does not come back as JSON, so check the status code before you parse the body. See Usage rules for 429 and 503.

System

Operational health of the public Datacentre app.

MethodPathPurposeMain query/path parameters
GET/healthzHealth check. Returns { "status": "ok" } when the service is upNone

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.

MethodPathPurposeMain query/path parameters
GET/clubsInfluence market data. Only clubs with market data; /clubs/detailed has every clubpage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by ClubsSortBy
sort_order string default asc
club_id array[integer]
country_id string
owned string
manager_locked integer
balance_min integer
balance_max integer
GET/clubs/detailedDetailed data for every clubpage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by ClubsSortBy
sort_order string default asc
club_id array[integer]
country_id string
owned string
manager_locked integer
available integer
league_id integer
division integer (0 = top flight)
has_job_posting integer
balance_min integer
balance_max integer
division_start_min integer
division_start_max integer
fans_start_min integer
fans_start_max integer
fans_current_min integer
fans_current_max integer
stadium_size_start_min integer
stadium_size_start_max integer
stadium_size_current_min integer
stadium_size_current_max integer
stadium_id_min integer
stadium_id_max integer
value_min integer
value_max integer
rating_start_min integer
rating_start_max integer
default_formation_min integer
default_formation_max integer
penalty_taker_min integer
penalty_taker_max integer
transfers_in_min integer
transfers_in_max integer
transfers_out_min integer
transfers_out_max integer
GET/clubs/{club_id}/jobRetrieve job posting details for a specific clubclub_id (required) integer
GET/club_balance_sheet/weeksGet club balance sheet entries by game weekclub_id (required) integer
season_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:

  • /clubs lists only clubs with market data, meaning their influence has been bought or sold at least once. Use /clubs/detailed to list every club.
  • /clubs/{club_id}/job returns 404 when 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.

MethodPathPurposeMain query/path parameters
GET/playersInfluence market data. Only players with market data; /players/detailed has every playerpage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by PlayersSortBy
sort_order string default asc
age_min integer
age_max integer
age integer
player_id array[integer]
wages_min integer
wages_max integer
rating_min integer
rating_max integer
value_min integer
value_max integer
country_id string (comma list allowed)
owned string
positions string (comma list of position codes)
club_id integer
free_agents boolean default false (only players with no club; not together with club_id)
allow_transfer integer
allow_renew integer
GET/players/detailedDetailed data for every playerpage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by PlayersSortBy
sort_order string default asc
age_min integer
age_max integer
age integer
player_id array[integer]
wages_min integer
wages_max integer
contract_min integer
contract_max integer
rating_min integer
rating_max integer
rating_gk_min integer
rating_gk_max integer
rating_tackling_min integer
rating_tackling_max integer
rating_passing_min integer
rating_passing_max integer
rating_shooting_min integer
rating_shooting_max integer
rating_aggression_min integer
rating_aggression_max integer
rating_stamina_min integer
rating_stamina_max integer
value_min integer
value_max integer
desired_contract_min integer
desired_contract_max integer
country_id string (comma list allowed)
owned string
positions string (comma list of position codes)
club_id integer
position_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 false
free_agents boolean default false (only players with no club; not together with club_id)
allow_transfer integer
allow_renew integer
fitness integer
retired integer
morale integer
injured integer
injury_id integer
position integer
multi_position integer
ability_gk integer
ability_tackling integer
ability_passing integer
ability_shooting integer
banned integer
cup_tied integer
yellow_cards integer
red_cards integer
agent_name string
loan_offered string
loan_offer_accepted string
loaned_to_club string
GET/player/history/{player_id}Retrieve player historyplayer_id (required) integer
GET/players/morale_history/{player_id}Get morale change history for a playerplayer_id (required) integer
limit integer 1 to 100, default 10
GET/player/transfer_historyRetrieve transfer history. Needs at least one of season_id, club_id, player_id; without season_id it returns the latest season onlyseason_id integer
club_id integer
player_id integer
GET/players/loan_historyRetrieve loan history. Needs at least one of season_id, club_id; without season_id it covers all seasonsseason_id integer
club_id integer
GET/player_field_time/by-player/{player_id}Current-season domestic-league field time for one player, one row per clubplayer_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:

  • /players lists 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=50 can be incomplete. Use /players/detailed to list every player. The free_agents=true filter is not affected.
  • positions takes position codes as a comma list, for example positions=GK,FC, and matches every player who can play any of those positions. position_mask (/players/detailed only) 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), so position_mask=16385 is GK plus FC. On its own the mask checks only each player's main position, so it returns fewer players than positions. Add position_mask_multi=true and the two match exactly.
  • /player/transfer_history with only season_id returns every transfer of that season (thousands of rows), so add a club_id or player_id.
  • The field-time routes return league_minutes, available_rounds and field_time_pct. field_time_pct is minutes played as a percentage of the minutes available (available_rounds x 90), capped at 100.

Users/profile

User lookup, profile/trading details, achievements and balance-sheet/earnings views.

MethodPathPurposeMain query/path parameters
GET/usersGet user list and basic datapage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by UsersSortBy
sort_order string default asc
name_prefix string
names array[string]
GET/users/detailedGet detailed user and trading datapage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by UsersDetailedSortBy
sort_order string default asc
name_prefix string
names array[string]
buy_volume_min integer
buy_volume_max integer
sell_volume_min integer
sell_volume_max integer
total_volume_min integer
total_volume_max integer
GET/achievementsGet user achievements statususername (required) string
GET/user_activityActivity ranking. Without name it returns the top 50 ranked users; with name, just that username string
GET/user_balance_sheetGet user balance sheet entriespage integer default 1
per_page 5, 10, 20, 50 or 100, default 50
name (required) string
from_time integer (unix seconds, used together with to_time)
to_time integer (unix seconds, used together with from_time)
GET/user_balance_sheet/earningsGet aggregated SVC earningsname (required) string
GET/user_balance_sheet/weeksGet weekly aggregated user balance sheetspage integer default 1
per_page integer 1 to 100, default 10
name (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_activity refreshes 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 return 503, so give this route a longer timeout, for example 60 seconds.
  • On /user_balance_sheet, from_time and to_time only work as a pair: at most 30 days apart (otherwise 400). The whole range then comes back in one response, ignoring page and per_page. A lone from_time or to_time is ignored.

Reference/leagues/countries

Reference country/league data and current league-table snapshots.

MethodPathPurposeMain query/path parameters
GET/countriesRetrieve data for countriessort_by CountriesSortBy
sort_order string default desc
country_id string
GET/leaguesRetrieve data for leagues (with 5-min cache)page integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by LeaguesSortBy
sort_order string default asc
country_id string (comma list allowed)
division integer (0 = top flight)
league_id integer
season_id integer
GET/league_tablesGet league table standings. Give league_id, or country_id together with divisionleague_id integer
country_id string
division integer (0 = top flight)
season_id integer
GET/dumps/leaguesAll national leagues for the current seasonNone
GET/dumps/league_tablesLeague tables for all divisions, optionally filtered to Division 1 (top flight) by countrycountry_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_id when linking historical data.
  • division counts from 0: division=0 is the top flight, 1 the second tier, and so on (England currently has 0 to 9). The one exception is /dumps/league_tables?country_ids=..., which labels the top flight division: 1.

Market/trading

Market overview, SVC price, account/share balances, dilution events, recent trades, leader/rich lists and trading graphs.

MethodPathPurposeMain query/path parameters
GET/marketObtain overall market metricsNone
GET/svc_priceCurrent SVC to USDC price. Returns { "svc2usdc": ... }, the same value as SVC2USDC in /market, in a much smaller responseNone
GET/tickerGet ticker dataNone
GET/rich_listRetrieve the richest userspage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
name string
sort_by RichListSortBy default total_networth
sort_order string default desc
GET/best_managersGet best managers datapage integer default 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by BestManagersSortBy default rank_a_ranking
sort_order string default asc
name string
GET/share/transactionsRetrieve share transactions for a username (required) string
GET/share_balance_by_user_clubGet share balance for a specific user and clubname (required) string
club_id (required) integer
GET/share_balancesRetrieve 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 1
per_page 5, 10, 20, 50, 100 or 1000, default 20
sort_by ShareBalancesSortBy
sort_order string default asc
club_id integer
player_id integer
name string
share_type club or player
countries 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 boolean
has_agent boolean
manager_last_active_unix_min integer
manager_last_active_unix_max integer
agent_last_active_unix_min integer
agent_last_active_unix_max integer
GET/share_balances/detailedRetrieve detailed influence balances with position and earningspage integer default 1
per_page integer 5 to 100, default 20
name (required) string
share_type club or player
share_ids array[integer] (use with share_type)
sort_by DetailedShareBalancesSortBy
sort_order string default desc
has_manager boolean
has_agent boolean
manager_last_active_unix_min integer
manager_last_active_unix_max integer
agent_last_active_unix_min integer
agent_last_active_unix_max integer
issue 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/summaryPortfolio summary for one user: balance, net worth, club and player counts and values, 7-day and 30-day earningsname (required) string
GET/share_balances/active_proposalsActive proposals across all of one user's holdingsname (required) string
GET/share_balances/issue_countsCounts of portfolio issues (for example no_manager, low_balance) across one user's club or player holdingsname (required) string
share_type (required) club or player
agent_name string (also counts the players whose agent is this user, shown as my_agent)
GET/share_trade_historyRetrieve share trade history. Needs at least one of name, club_id, player_idpage integer default 1
per_page integer 1 to 100, default 50
name string
club_id integer
player_id integer
sort_by string
sort_order string default desc
GET/share_trade_history/allMost recent trades (default 20)per_page integer 1 to 100, default 20
GET/dilutionsDilution events with their contributions, state and totalspage integer default 1
per_page integer 1 to 5000, default 100
share_type string (for example club)
share_id integer
name string (contributor)
state active, finished, success or failed
sort_by total_raised, price, influence_created or date
sort_order string default asc
GET/trading_graphRetrieve aggregated trading data. Give exactly one of club_id or player_idclub_id integer
player_id integer
time_range (required) 1d, 7d, 30d, 90d, 6m or 1y
GET/trading_graph/allRetrieve daily and monthly payouts dataNone

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.

MethodPathPurposeMain query/path parameters
GET/dumps/club_earningsPre-calculated club earnings for buyersNone
GET/dumps/club_earnings_lightSimplified club earnings (club_id → SVC per influence per season)None
GET/dumps/club_packsClub pack dealsNone
GET/dumps/club_seller_opportunitiesPre-calculated club seller opportunitiesNone
GET/dumps/player_earningsPlayer earnings and ROI analysisthreshold (required) one of 2, 3, 4, 5, 6, 7, 8, 10, 12, 15 or 20 (anything else is 400)
country string
division integer (0 = top flight)
min_rating integer
max_rating integer
position string
min_age integer
max_age integer
min_buyable integer
player_id integer
min_match_time number
max_match_time number
sort string default payback
order string default asc
page integer default 1
limit integer 1 to 500, default 100
GET/dumps/share_ordersAll share orders (clubs + players combined)None
GET/dumps/share_orders/clubsClub share orders (optionally filtered by ID)ids array[integer]
GET/dumps/share_orders/playersPlayer share orders (optionally filtered by ID)ids array[integer]
GET/dumps/share_orders/jsonDownload share_orders as JSONNone
GET/dumps/share_orders/csvDownload share_orders as CSVNone

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 an ETag and Cache-Control: no-cache. Send the ETag back in an If-None-Match header and you get a 304 with no body while the data has not changed.
  • /dumps/share_orders/json and /dumps/share_orders/csv give 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.

MethodPathPurposeMain query/path parameters
GET/shop/clubsRetrieve pack-sale data for clubs. One row per packpage integer default 1
per_page integer 1 to 100, default 20
tiers 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 ShopClubsSortBy
sort_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. So club_ids=50 returns every pack that contains influence in club 50, and only one of those is club 50's own pack (the row where club_id is 50).
  • Every price in the response is USDC × 1,000,000: pricePerPack, current_price (also inside shares) and each pricing[].price. For example, a pricePerPack of 39500000 is 39.5 USDC.
  • Use per_page and the filters to keep responses small.

Transfers

Recent completed transfers and transfer-count summaries.

MethodPathPurposeMain query/path parameters
GET/transfers/basicGet latest completed transfersNone
GET/transfers/countsGet transfer counts for a club in a seasonclub_id (required) integer
season_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.

MethodPathPurposeMain query/path parameters
GET/commentary/match_commentary/{fixture_id}Get match commentary for a fixturefixture_id (required) integer
GET/commentary/match_events/{fixture_id}Get match events for a fixturefixture_id (required) integer
GET/fixture_history/players/{fixture_id}Get fixture player data for a fixturefixture_id (required) integer
GET/fixture_history/tactics/{fixture_id}Get fixture tactics data for a fixturefixture_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 the fixture_id you want.

Messages/news

Blockchain/game messages/news filtered by season, country, competition or club.

MethodPathPurposeMain query/path parameters
GET/messagesGet messages from the blockchain. Needs season_id plus at least one of country_id, comp_id, club_idseason_id (required) integer
country_id string
comp_id integer
club_id integer
limit 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_id is required, and so is at least one of country_id, comp_id or club_id (otherwise 400).
  • limit defaults to 500 and is capped at 10000; add a small limit to avoid very large responses.

Leaderboards

Earnings, referral, manager and scout leaderboards.

MethodPathPurposeMain query/path parameters
GET/leaderboards/earningsEarnings 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 1
per_page 5, 10, 20, 50 or 100, default 10
name string
GET/leaderboards/earnings/lifetimeAll-time payouts leaderboard (up to 200 rows)scope all (default), club or player
page integer default 1
per_page 5, 10, 20, 50 or 100, default 10
name string
GET/leaderboards/managersManagers leaderboard: titles, cups, promotions and form (up to 200 rows)page integer default 1
per_page 5, 10, 20, 50 or 100, default 10
view honours (default), form or streaks
season all (default) or a season id from the seasons list in the response
name string
GET/leaderboards/managers/historyOne manager's career: summary, every season managed and career spells. 404 if the name is not on the boardname (required) string
GET/leaderboards/scoutsScouts leaderboard: the rating gained by the players a user bought early (up to 200 rows)page integer default 1
per_page 5, 10, 20, 50 or 100, default 10
sort score (default), total_gain or avg_gain
name string
GET/leaderboards/scouts/picksBest individual scouting picks (up to 200 rows)page integer default 1
per_page 5, 10, 20, 50 or 100, default 10
GET/leaderboards/referrals/allAll-time referral leaderboard (up to 200 rows)None
GET/leaderboards/referrals/windowedReferral 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/earnings has two shapes. With none of page, per_page or name you 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 name to also get that user's own ranked row as you when they fall outside the page. The paged boards are 200 rows deep, so a page past row 200 returns 400 (for example page=41 with per_page=5).
  • In /leaderboards/earnings, total_earnings, club_earnings and player_earnings are raw SVC (divide by 10000); total_earnings_usdc is already in USDC.
  • The referral boards return { window, updated_at, entries }. Each entry has rank, account, referrals, bonus_shares, usd_spent, last_active_unix and last_active, ranked by bonus_shares. usd_spent is USDC × 1,000,000: divide by 1000000.

Votes/proposals

Active and historical proposal/vote views, finished-proposal results and graph data.

MethodPathPurposeMain query/path parameters
GET/proposals/activeGet currently active proposalspage integer default 1
per_page integer 1 to 5000, default 100
proposal_type agent, manager or unlock
share_type club or player
stage_filter proposal or voting
club_id integer
player_id integer
name string
GET/proposals/graphGet daily proposal completion counts for graphingdays_back integer 1 to 90, default 30
GET/proposals/historicalGet proposals that ended in the last N days with daily statisticsdays_back integer 1 to 30, default 7
proposal_type agent, manager or unlock
share_type club or player
club_id integer
player_id integer
name string
GET/proposals/finishedFinished proposals for a batch of clubs or players, with the frozen votes and the winnershares (required) string, comma list of type:id pairs, at most 100 (for example club:50,player:1100)
GET/proposals/outcomesFinal 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 200
share_type club or player
share_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 total 0 and an empty items list. That is normal, not an error.

The same service, play.soccerverse.com, also offers:

  • /v1 routes. GET routes that each return everything one page of the Soccerverse site needs in a single call. Use them for page-sized reads, for example https://play.soccerverse.com/v1/club/50, /v1/player/1100, /v1/user/snailbrain, /v1/home, /v1/transfer-market and /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.

شركاؤنا