StrinovaHub API
Version 1 · read-only

StrinovaHub API

Strinova match data collected by StrinovaHub from uploaded replays, public StrinovaHub profiles and the season schedule, over plain HTTPS and JSON. Build trackers, Discord bots and stats tools on top of it.

Base URLhttps://api.strinovahub.com/v1
FormatJSON, UTF-8, dates in ISO 8601 (UTC)
AccessFree, with a key granted on request
Where the data comes from. Strinova has no official API yet. Match data exists only for matches whose replay someone uploaded to the Replay Reader, so a player's history here is what StrinovaHub has seen, not everything they played.

Getting a key

Sign in to StrinovaHub and open Settings › Developer API. Tell us what you're building; the team reviews each request by hand, usually within a few days. Once approved, you create keys on the same page (up to three) and can revoke them there at any time.

A key is shown in full only once, when you create it. Keep it on your server: never ship it in a web page, a browser extension or a mobile app, where anyone can read it.

Authentication

Send the key in the Authorization header of every request.

curl https://api.strinovahub.com/v1/seasons \
  -H "Authorization: Bearer shk_live_…"
const res = await fetch('https://api.strinovahub.com/v1/players/5120934', {
  headers: { Authorization: `Bearer ${process.env.STRINOVAHUB_API_KEY}` },
});
const { data } = await res.json();

The X-API-Key: shk_live_… header works too. Requests without a valid key get 401.

Rate limits

Every key can make 60 requests a minute and 10,000 a day (the day resets at 00:00 UTC). If you need more, write to us from your request page. Each answer carries the current numbers:

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute.
X-RateLimit-RemainingRequests left in the current minute.
X-RateLimit-ResetSeconds until the minute window resets.
X-RateLimit-Daily-LimitRequests allowed per day.
X-RateLimit-Daily-RemainingRequests left today.

Over a limit, the API answers 429 with a Retry-After header in seconds. Wait that long, don't retry in a loop.

Errors

Errors use the HTTP status and a body with a stable code you can branch on:

{
  "error": {
    "code": "player_not_found",
    "message": "No player with this UID in StrinovaHub replays."
  }
}
StatusCodes
400bad_uid, bad_season, bad_cursor, bad_match_id, bad_username
401missing_key, invalid_key
403player_refused, match_history_hidden, profile_private
404player_not_found, match_not_found, profile_not_found
429rate_limited, daily_limit (with retryAfter)
5xxSomething broke on our side. Retry later with backoff.

Conventions

Successful answers wrap the result in data. Lists that can be long are paged with a cursor: when there's more, next holds the parameters for the following page, otherwise it's null.

A UID is a player's in-game Strinova UID (5 to 12 digits), passed and returned as a string. Seasons are referred to by code (26SP5, S3); a match belongs to the season its replay was recorded in.

GET/v1/key

The key you're using: its name, limits and requests made today. Handy to check a key works.

{
  "data": {
    "name": "Production",
    "prefix": "shk_live_Ab3x",
    "limits": { "perMinute": 60, "perDay": 10000 },
    "usedToday": 1284
  }
}
GET/v1/seasons

The Strinova season schedule, newest first. endsAt is informational: a season lasts until the next one starts.

{
  "data": [
    {
      "code": "26SP5",
      "title": "Seasonless Garden",
      "startsAt": "2026-09-17T07:00:00.000Z",
      "endsAt": "2026-11-18T23:59:59.000Z",
      "current": true
    }
  ]
}
GET/v1/players/{uid}

A player by in-game UID: name and level from their latest match, in-game rank and avatar, how many of their matches StrinovaHub has and in which seasons, and their StrinovaHub account when it's public.

{
  "data": {
    "uid": "5120934",
    "name": "Kasumi",
    "level": 212,
    "rank": 23,
    "casualRank": 6,
    "avatarId": 31000001,
    "matches": 2,
    "lastPlayedAt": "2026-09-24T17:22:43.510Z",
    "seasons": [
      { "code": "26SP5", "title": "Seasonless Garden", "matches": 2, "current": true }
    ],
    "account": { "username": "Kasumi", "url": "https://alpha.strinovahub.com/u/Kasumi" }
  }
}

rank, casualRank and avatarId are the game's own ids (ranked tier, casual tier, avatar item); null when unknown.

GET/v1/players/{uid}/matches

The player's matches, newest first, with their own line from each.

QueryDescription
seasonOnly matches of this season, e.g. 26SP5.
limit1 to 50, default 20.
beforeCursor: only matches played before this time. Use next.before from the previous page.
{
  "data": [
    {
      "id": "740728528238070680",
      "playedAt": "2026-09-24T17:22:43.510Z",
      "map": "Ocarnus",
      "mode": "Ranked",
      "team": 1,
      "score": { "team1": 9, "team2": 7 },
      "result": "win",
      "kills": 19, "deaths": 9, "assists": 16, "damage": 7346,
      "mvp": true,
      "characters": ["Nora", "Flavia"]
    }
  ],
  "next": { "before": "2026-09-24T17:22:43.510Z" }
}
GET/v1/matches/{id}

One match: map, mode, score and every player's line.

{
  "data": {
    "id": "740728528238070680",
    "playedAt": "2026-09-24T17:22:43.510Z",
    "map": "Ocarnus",
    "mode": "Ranked",
    "score": { "team1": 9, "team2": 7 },
    "winner": 1,
    "players": [
      {
        "team": 1,
        "uid": "5120934",
        "name": "Kasumi",
        "level": 212,
        "kills": 19, "deaths": 9, "assists": 16, "damage": 7346,
        "mvp": true,
        "characters": ["Nora", "Flavia"],
        "account": { "username": "Kasumi", "url": "https://alpha.strinovahub.com/u/Kasumi" }
      },
      { "team": 2, "refused": true }
    ]
  }
}

winner is null for a draw. A player StrinovaHub doesn't serve data for appears only as { "team", "refused": true }.

GET/v1/profiles/{username}

A public StrinovaHub profile by username or profile address.

{
  "data": {
    "username": "Kasumi",
    "url": "https://alpha.strinovahub.com/u/Kasumi",
    "uid": "5120934",
    "avatarUrl": "https://cdn.strinovahub.com/uploads/….webp",
    "bannerUrl": null,
    "bio": null,
    "level": 18,
    "region": "Asia",
    "country": "CN",
    "badges": { "official": true, "verified": true, "premium": false, "creator": false },
    "joinedAt": "2025-08-02T10:12:00.000Z"
  }
}

level here is the StrinovaHub level, not the in-game one.

Privacy

The API returns what's already public on StrinovaHub, and respects the same choices: private profiles answer profile_private; accounts that hide their match history answer match_history_hidden and aren't linked from other people's matches; players StrinovaHub refuses service to are anonymised. No e-mail addresses, IPs or other private data are ever exposed.

Use the data for your project as described in your request. Don't resell it, don't build profiles of people who opted out, and credit StrinovaHub where players see the numbers. Keys used against these terms are revoked.

Changelog

2026-09-28v1: seasons, players, player matches, matches and profiles.