# FACEIT public profiles

Use the existing authenticated routes with a server-held WOK key:

| Request | Data | Quota |
| --- | --- | --- |
| `GET /faceit/data/v4/players?game=cs2&game_player_id=<SteamID64>` | Public profile and game ranks | 1 unit |
| `GET /faceit/data/v4/players/<player_id>/stats/cs2` | Lifetime and optional map/competition statistics | 1 unit |
| `GET /faceit/data/v4/players/<player_id>/history?game=cs2&limit=5&page=0` | One recent-match page; limit 1–20, page 0–100 | 1 unit |

The profile retains `player_id`, `nickname`, `country`, `avatar`, `faceit_url`
and `games`. Each game retains its ELO, numeric skill level, game player ID,
game player name and region. The following additive fields are returned only
when the same source profile response supplies valid values:

| Field | Meaning |
| --- | --- |
| `created_at` | Source-reported account creation timestamp |
| `activated_at` | Source-reported account activation timestamp |
| `cover_image` | HTTPS cover image URL |
| `animated_avatar` | HTTPS animated avatar URL |
| `memberships` | Public membership labels as reported by FACEIT |
| `friends_count` | Number of entries in the returned public friends list |
| `steam_id_64` | SteamID64 from the public Steam platform linkage |
| `steam_nickname` | Steam nickname saved in that platform linkage |
| `games.<game>.skill_level_label` | Source-reported skill level label |
| `timezone` | Uninterpreted source timezone string, for example `"0.0"` |
| `user_type` | Source account-type label, for example `"user"` |

These extras cause **zero additional upstream requests**. Profiles do not
implicitly load lifetime statistics, history, friends' profiles or Steam data.
Membership labels do not establish current paid status or entitlement. The
friends list may be incomplete: `friends_count` counts the returned entries,
not a verified total of every friend. Friends IDs, raw tags and internal
account metadata are not exposed. A missing field means unavailable or invalid,
never an inferred `false`, zero, empty string or verification status. An
explicit empty membership list remains `[]`.
The `timezone` string is not converted to a UTC offset, hours or an IANA zone.
The `user_type` label does not establish a subscription, entitlement or ban status.

Dates use RFC 3339 timestamps with a timezone. Optional strings and collections
are bounded: timestamps 64 characters, image URLs 2048, membership lists 32
labels of 64 characters each, Steam nickname 128, skill level label 64, and
friends lists 5000 entries. The raw timezone and account-type strings are at most
64 characters. Malformed or over-limit optional fields are omitted
without breaking the existing profile. Treat all returned names and labels as
untrusted text in a UI.

Lifetime `lifetime` now also includes `"Wins"` when supplied by the source.
Numeric lifetime metrics remain strings, for example `"Wins": "1241"`.
Existing Matches, Win Rate %, Average K/D Ratio, Average Headshots % and
Recent Results retain their names and types. Missing wins are not assumed zero.

The same stats response may also include up to 256 `segments` rows:

```json
{
  "lifetime": {"Matches": "12", "Wins": "7"},
  "segments": [
    {
      "type": "Map",
      "mode": "5v5",
      "label": "de_mirage",
      "stats": {"Matches": "4", "Wins": "2", "Win Rate %": "50"}
    },
    {
      "type": "Competition",
      "mode": "5v5",
      "label": "00000000-0000-0000-0000-000000000001",
      "stats": {"Matches": "8", "Wins": "5"}
    }
  ]
}
```

This is an illustrative response, not a real player's record. `type` is `Map`
or `Competition`; `mode` is the source gameMode label, at most 64 characters.
`label` is a source map key or competition ID, at most 128 characters. A
competition ID is **not** a resolved competition name. Rows belong only to the
requested game; WOK does not combine modes or fetch competition details.

Each row exposes only the available validated `Matches`, `Wins`, `Win Rate %`,
`Average K/D Ratio` and `Average Headshots %`. All values remain strings:
numeric source values are formatted using the existing lifetime behavior, and
valid numeric strings keep their spelling. Counts are nonnegative integers up to
2^63−1; percentages are finite values from 0 through 100; K/D is finite and
nonnegative, up to 2^63−1. Invalid, nested, boolean or missing values are omitted.
`Recent Results` and opaque source metric codes are not exposed in a segment.

These segments cause zero additional source requests. They are a bounded
projection, not a full raw source dump. Missing or malformed segment data is
omitted; explicit source `segments: []` may remain `[]`. Neither omission nor
an empty list means zero matches across every map or competition.

History accepts an explicit `page` from 0 through 100. The default `page=0`
keeps the legacy outer `items`, `start`, `end` shape. A nonzero page also returns
`page` and `limit`; `start = page * limit`, and `end = start + len(items)`.
For example, `page=1&limit=5` requests the next five-position slice, with
`start=5`; a valid empty response has `end=5`. Each request costs one unit and
reads one bounded source page. No automatic page sweep is performed. Positions
can shift when matches change, so pages are not an immutable cursor or a
guarantee of a full-history total, stable ordering or further pages.

`match_stats.Headshots` is an optional count from the known source `i13` field,
separate from `Headshots %`. It is a string representing a nonnegative integer
up to 2^63−1, and is omitted if it exceeds a valid `Kills` count. Explicit zero
remains `"0"`; missing, malformed or inconsistent counts are not converted to zero
or inferred from a percentage.

Profile and lifetime snapshots use the existing configurable cache TTL, six
hours by default. Existing cached responses can lack the new fields until
natural expiration; no cache flush or forced refresh is performed. Account
creation/activation dates describe the account, **not** when WOK observed it.
The saved Steam nickname is not a fresh Steam lookup. Older cached stats may
lack segments until natural expiration. Recent history continues to use its
existing separate bounded request, now with explicit page selection. No
verification guarantee or new official-key resource is added.

The existing response and error behavior remains: profile absence is 404,
unavailable FACEIT data is 502, and a player with no lifetime statistics gets
200 with `{"lifetime": {}}`. Key/quota errors keep their existing statuses.
Cached calls still cost one WOK unit while using no upstream traffic. Concurrent
coalesced reads charge each admitted WOK request once and attribute upstream
traffic only to the actual fetching leader. Existing source retries remain
bounded to two attempts; no automatic replay or extra fanout is introduced.

JavaScript / TypeScript:

```js
const profile = await client.faceitPlayer(steamId, { game: "cs2" });
console.log(profile.created_at, profile.memberships, profile.games.cs2?.skill_level_label);
// Make this separate call only when lifetime data is needed.
const stats = await client.faceitStats(profile.player_id, { game: "cs2" });
console.log(stats.lifetime.Wins);
// Optional segment data; undefined does not mean zero matches.
console.log(stats.segments);
```

Python:

```python
profile = client.faceit_player(steam_id, game="cs2")
print(profile.get("created_at"), profile.get("memberships"))
# Make this separate call only when lifetime data is needed.
stats = client.faceit_stats(profile["player_id"], game="cs2")
print(stats["lifetime"].get("Wins"))
# None means the optional segment projection was not returned.
print(stats.get("segments"))
```

SDK 1.3.0 retains additive response fields. Its existing history helper still
requests the first page; it does not expose the new `page` option. Use an explicit
HTTP request for a later page. Replace the illustrative UUID below with the
validated `profile.player_id`, keep the WOK key on your server, and request another
page only when needed:

```bash
curl --fail-with-body --silent --show-error --max-time 35 --get \
  'https://woksteamapi.com/faceit/data/v4/players/00000000-0000-0000-0000-000000000001/history' \
  --header "Authorization: Bearer ${WOK_API_KEY:?Set WOK_API_KEY on the server}" \
  --data-urlencode 'game=cs2' --data-urlencode 'limit=20' --data-urlencode 'page=1'
```

This makes one request without automatic retry or redirect following. Inspect
the HTTP status before consuming the result; an unavailable page is not an empty
successful history. Source or quota errors keep their existing response status.

Optional fields align where possible with the
[official FACEIT player schema](https://docs.faceit.com/docs/data-api/data/).
WOK's adapter reads the public website source and exposes only its confirmed,
allowlisted fields; it does not promise complete official API coverage.
