# Add premium webhook user
Source: https://docs.henrikdev.xyz/api-reference/premium/add-premium-webhook-user
https://api.henrikdev.xyz/openapi.json post /public/v1/premium/webhook/users
# Delete premium webhook user
Source: https://docs.henrikdev.xyz/api-reference/premium/delete-premium-webhook-user
https://api.henrikdev.xyz/openapi.json delete /public/v1/premium/webhook/users/{id}
# Get premium webhook settings
Source: https://docs.henrikdev.xyz/api-reference/premium/get-premium-webhook-settings
https://api.henrikdev.xyz/openapi.json get /public/v1/premium/webhook
# Update premium webhook user
Source: https://docs.henrikdev.xyz/api-reference/premium/update-premium-webhook-user
https://api.henrikdev.xyz/openapi.json put /public/v1/premium/webhook/users/{id}
# Generate crosshair image (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/generate-crosshair-image-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/crosshair/generate
# Get account by PUUID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-account-by-puuid-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/by-puuid/account/{puuid}
# Get account by PUUID (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-account-by-puuid-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/by-puuid/account/{puuid}
# Get account (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-account-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/account/{name}/{tag}
# Get account (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-account-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/account/{name}/{tag}
# Get content (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-content-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/content
# Get esports schedule (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-esports-schedule-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/esports/schedule
# Get featured store items
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-featured-store-items
https://api.henrikdev.xyz/openapi.json get /valorant/{version}/store-featured
# Get game version (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-game-version-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/version/{affinity}
# Get leaderboard (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-leaderboard-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/leaderboard/{affinity}
# Get leaderboard (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-leaderboard-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/leaderboard/{affinity}
# Get leaderboard (v3)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-leaderboard-v3
https://api.henrikdev.xyz/openapi.json get /valorant/v3/leaderboard/{affinity}/{platform}
# Get match details (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-match-details-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/match/{match_id}
# Get match details (v4)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-match-details-v4
https://api.henrikdev.xyz/openapi.json get /valorant/v4/match/{affinity}/{match_id}
# Get matches by name (v3)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-matches-by-name-v3
https://api.henrikdev.xyz/openapi.json get /valorant/v3/matches/{affinity}/{name}/{tag}
# Get matches by name (v4)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-matches-by-name-v4
https://api.henrikdev.xyz/openapi.json get /valorant/v4/matches/{affinity}/{platform}/{name}/{tag}
# Get matches by PUUID (v3)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-matches-by-puuid-v3
https://api.henrikdev.xyz/openapi.json get /valorant/v3/by-puuid/matches/{affinity}/{puuid}
# Get matches by PUUID (v4)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-matches-by-puuid-v4
https://api.henrikdev.xyz/openapi.json get /valorant/v4/by-puuid/matches/{affinity}/{platform}/{puuid}
# Get MMR by name (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-by-name-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/mmr/{affinity}/{name}/{tag}
# Get MMR by name (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-by-name-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/mmr/{affinity}/{name}/{tag}
# Get MMR by name (v3)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-by-name-v3
https://api.henrikdev.xyz/openapi.json get /valorant/v3/mmr/{affinity}/{platform}/{name}/{tag}
# Get MMR by PUUID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-by-puuid-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/by-puuid/mmr/{affinity}/{puuid}
# Get MMR by PUUID (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-by-puuid-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/by-puuid/mmr/{affinity}/{puuid}
# Get MMR by PUUID (v3)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-by-puuid-v3
https://api.henrikdev.xyz/openapi.json get /valorant/v3/by-puuid/mmr/{affinity}/{platform}/{puuid}
# Get MMR history by name (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-history-by-name-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/mmr-history/{affinity}/{name}/{tag}
# Get MMR history by name (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-history-by-name-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/mmr-history/{affinity}/{platform}/{name}/{tag}
# Get MMR history by PUUID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-history-by-puuid-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/by-puuid/mmr-history/{affinity}/{puuid}
# Get MMR history by PUUID (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-mmr-history-by-puuid-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/by-puuid/mmr-history/{affinity}/{platform}/{puuid}
# Get Premier leaderboard (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-premier-leaderboard-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/premier/leaderboard/{affinity}
# Get Premier team by ID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-premier-team-by-id-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/premier/{id}
# Get Premier team by name (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-premier-team-by-name-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/premier/{name}/{tag}
# Get Premier team history by ID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-premier-team-history-by-id-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/premier/{id}/history
# Get Premier team history by name (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-premier-team-history-by-name-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/premier/{name}/{tag}/history
# Get queue status (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-queue-status-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/queue-status/{affinity}
# Get raw Riot API data (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-raw-riot-api-data-v1
https://api.henrikdev.xyz/openapi.json post /valorant/v1/raw
# Get status (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-status-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/status/{affinity}
# Get store offers
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-store-offers
https://api.henrikdev.xyz/openapi.json get /valorant/{version}/store-offers
# Get stored matches by name (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-stored-matches-by-name-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/stored-matches/{affinity}/{name}/{tag}
# Get stored matches by PUUID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-stored-matches-by-puuid-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/by-puuid/stored-matches/{affinity}/{puuid}
# Get stored MMR history by name (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-stored-mmr-history-by-name-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/stored-mmr-history/{affinity}/{name}/{tag}
# Get stored MMR history by name (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-stored-mmr-history-by-name-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/stored-mmr-history/{affinity}/{platform}/{name}/{tag}
# Get stored MMR history by PUUID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-stored-mmr-history-by-puuid-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/by-puuid/stored-mmr-history/{affinity}/{puuid}
# Get stored MMR history by PUUID (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-stored-mmr-history-by-puuid-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/by-puuid/stored-mmr-history/{affinity}/{platform}/{puuid}
# Get VLR esports events (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-esports-events-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/events
# Get VLR event matches (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-event-matches-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/events/{event_id}/matches
# Get VLR match details (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-match-details-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/matches/{match_id}
# Get VLR player matches (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-player-matches-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/players/{player}/matches
# Get VLR player (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-player-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/players/{player_id}
# Get VLR team matches (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-team-matches-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/teams/{team_id}/matches
# Get VLR team transactions (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-team-transactions-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/teams/{team_id}/transactions
# Get VLR team (v2)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-vlr-team-v2
https://api.henrikdev.xyz/openapi.json get /valorant/v2/esports/vlr/teams/{team_id}
# Get website content (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-website-content-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/website/{country_code}
# Get website entry by ID (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/get-website-entry-by-id-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/website/{country_code}/{db_id}
# Search Premier teams (v1)
Source: https://docs.henrikdev.xyz/api-reference/valorant/search-premier-teams-v1
https://api.henrikdev.xyz/openapi.json get /valorant/v1/premier/search
# Authentication & Authorization
Source: https://docs.henrikdev.xyz/general/auth
This API requires an API Key. You can generate one by follow the instructions:
* Go to the management dashboard: [https://api.henrikdev.xyz/dashboard/](https://api.henrikdev.xyz/dashboard/)
* Select "API Keys" from the sidebar
* Fill out the "Generate New Key" Form with the given parameters and fields
# Premium Features
Source: https://docs.henrikdev.xyz/general/premium
How to get premium features for the HenrikDev API
# Premium Features
Premium features unlock higher rate limits and additional capabilities for the HenrikDev API.
## Tiers
Default tier for every API key.
* Standard key rate limits
* 300s cache TTL
* No webhook updates
* No tracked users
US\$10.99/month
* Up to **130 req/min**
* **60% reduced caching** — 2-minute caches instead of the default 5-minute caches
* Webhooks for **10 users**
* Webhook deliveries within **60 seconds** max
US\$15.99/month
* Up to **200 req/min**
* **80% reduced caching** — 60-second caches
* Webhooks for **20 users**
* Webhook deliveries within **40 seconds** max
US\$25.99/month
* Up to **300 req/min**
* **90–100% reduced caching** — 30-second caches by default, force refresh for zero cache
* Webhooks for **50 users**
* Webhook deliveries within **20 seconds** max
## How to get premium
You can subscribe to premium directly through our Discord app listing:
Visit the HenrikDev Systems Discord app page to view available premium plans and subscribe.
## What's next
* More premium features are coming soon.
* Additional payment options will be added in the future.
# Rate Limiting
Source: https://docs.henrikdev.xyz/general/rate-limiting
How rate limits are calculated and enforced in API v4
# Rate Limiting
Rate limits are tied to your API key and are enforced globally per key.
## How usage is calculated (v4.0.0+)
Starting with v4.0.0, the rate limit counts both the call to the HenrikDev API and any Riot requests made in the background to build the response.
```text theme={null}
1 request to the API = +1
1 background request to Riot = +1
```
If the requested data is already cached or stored locally, no background Riot request is needed, so only the API call is counted.
### Example 1: partial cache miss
* Endpoint: `/valorant/v3/matches/eu/Henrik3/VALO?size=10`
* 7 of 10 matches are stored on the server
* Required Riot requests: 1 history + 3 matches
* Rate limit cost: **1 (API) + 4 (Riot) = 5**
### Example 2: full cache hit
* Endpoint: `/valorant/v3/matches/eu/Henrik3/VALO?size=10`
* All 10 matches are stored on the server
* Required Riot requests: 0
* Rate limit cost: **1 (API) + 0 (Riot) = 1**
## Headers
Every response includes headers to help you track usage:
| Header | Description |
| ----------------------- | ----------------------------------------------- |
| `RateLimit-Policy` | All rate-limit windows for the current key/plan |
| `RateLimit` | The most restrictive active window |
| `X-RateLimit-Limit` | Total requests in the shortest window |
| `X-RateLimit-Remaining` | Requests remaining in that window |
| `X-RateLimit-Reset` | Seconds until the shortest window resets |
| `X-RateLimit-Bucket` | Bucket identifier for this request |
| `X-Request-ID` | Request identifier for debugging |
### Cache headers
| Header | Description |
| ---------------- | ------------------------------------------------------------- |
| `X-Cache-Status` | `HIT` if the response was served from cache, otherwise `MISS` |
| `X-Cache-TTL` | Seconds until the cached response expires (only on `HIT`) |
## Exceeded limits
If you exceed a rate limit, the API returns `429 Too Many Requests`. The `Retry-After`/`X-RateLimit-Reset` headers indicate how long to wait before the next request.
## Increasing limits
You can raise your rate limits in two ways:
1. Request an upgraded API key type from the dashboard.
2. Subscribe to a premium plan — premium limits are merged with your key limits and the more generous value is used.
# Changes
Source: https://docs.henrikdev.xyz/valorant/changes
Valorant API changelog
# Changes
Latest Change: [v4.9.0](/valorant/changes/v4.9.0)
# v4.0.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.0.0
Major version 4.0.0 changelog
# v4.0.0
## Key Requirement
Due to recent botting attacks that impacted everyone in terms of global 429 errors, an API Key is now required. As this would break twitch bots (no ability to set headers), you can authenticate with the `?api_key` query param. But no worries, you can easily get a key without waiting time, just follow the following steps:
1. Join on the discord: [https://discord.com/invite/X3GaVkX2YN](https://discord.com/invite/X3GaVkX2YN)
2. Verify
3. Go to the **#get-a-key** channel
4. Select from the dropdown list **"VALORANT (Basic Key)"**
The bot will now present you an API Key that you can use instantly. If you need a higher rate limit key, please select "VALORANT (Advanced Key)". This type of key needs some information from you and follows an approval workflow and requires some waiting time.
Friendly reminder here: This API is not designed to be used in production apps, so custom keys are not guaranteed to be granted
## Performance & Capacity
Version 4 is written in Rust, which enables higher performance and lower latency for each request & and the overall ability to handle more requests at the same time.
The amount of backend proxies also were upgraded to 7.5x in comparison to v3, allowing higher limits and more requests to be handled.
## Rate Limit Calculation
The way of how the rate limit is calculated will be changed. Right now it's simply 1 request to API = +1 in your rate limit. As some of these calls require fetches from riot, some do not (cache, database or simply local generated like the crosshair endpoint) this will change. The biggest issue is the rate limit to riot, not the amount of requests the server can handle. So the new rate limiting will look like this:
```text theme={null}
1 Request to API = +1
1 Request to Riot in the background = +1
```
#### Example 1
* Endpoint: /valorant/v3/matches/eu/Henrik3/VALO?size=10
* 7 Matches stored on the server for this user
* Hit cache: **false**
* Required Requests to Riot:
* 1x history
* 3x matches (the ones not stored on server)
* Ratelimit increase: 1 (Call to API) + 4 (Calls to Riot) = **5**
#### Example 2
* Endpoint: /valorant/v3/matches/eu/Henrik3/VALO?size=10
* 10 Matches stored on the server for this user
* Hit cache: **true**
* Required Requests to Riot:
* 0x history
* 0x matches (the ones not stored on server)
* Ratelimit increase: 1 (Call to API) + 0 (Calls to Riot) = **1**
## New Headers
Every Request now contains a **X-Cache-Status** header, which indicates if the response data was created from the internal cache.
These values can be **HIT** or **MISS.**
If the state is **HIT**, there also is a **X-Cache-TTL** header, indicating the time in seconds the cache (or if multiple caches used the cache TTL that will expire first) will expire and new data can be fetched. If the state is **MISS**, this header will not exist.
## Error Handling & Error Codes
* Error messages should be now more clear and reliable, no more random 500 error codes except real code issues
* Due to this, the error codes have changed and there are some few more of them, you can find them [here](/valorant/error-codes)
## Deprecations
The following endpoints will be deprecated
* [/valorant/v1/mmr/:affinity/:name/:tag](/valorant/api-reference/mmr)
* [/valorant/v1/by-puuid/mmr/:affinity/:puuid](/valorant/api-reference/mmr)
* [/valorant/v1/leaderboard/:affinity](/valorant/api-reference/leaderboard)
* [/valorant/v1/lifetime/matches/:affinity/:name/:tag](/valorant/api-reference/stored-data)
* [/valorant/v1/by-puuid/lifetime/matches/:affinity/:puuid](/valorant/api-reference/stored-data)
* [/valorant/v1/lifetime/mmr/:affinity/:name/:tag](/valorant/api-reference/stored-data)
* [/valorant/v1/by-puuid/lifetime/matches/:affinity/:puuid](/valorant/api-reference/stored-data)
These deprecations will have their full effect 3 months after release of the respective patch (in this case v4)
## Routing Issues (Telekom)
As you may have noticed, there is an issue with routing if you have a Telekom (German, Hungary, Romania) connection. This is related to the peering between Telekom and CF, routing the package via NewArk in every case, resulting in a latency increase by 9x in average in the eu.
The change that should fix this is applied for `beta.api` and `eu.api` already.
#### For example:
```text theme={null}
api.henrikdev.xyz/valorant/v1/esports/schedule (CF) ~450ms
eu.api.henrikdev.xyz/valorant/v1/esports/schedule (Not CF) ~50ms
```
## Endpoint: Account
### New Version
```text theme={null}
/valorant/v2/account/:name/:tag
/valorant/by-puuid/v2/account/:puuid
```
* Implement new, more stable way to get the puuid
* Streamlined data structure (no more unix timestamps, no formated "X minutes ago")
```json theme={null}
{
"status": 200,
"data": {
"puuid": "60325b89-7524-55be-be68-8ab3e7c0f2a3",
"region": "eu",
"account_level": 1086,
"name": "FUT rAx",
"tag": "VAL",
"card": "29d6aced-4f66-e000-15eb-71b1906a113a",
"title": "c8be8fda-46a8-9843-87bc-ecbf9672c227",
"platforms": [
"PC",
"CONSOLE"
],
"updated_at": "2024-06-16T18:33:11.095Z"
}
}
```
## Endpoint: Leaderboard
### Changes
* Query params: `name`, `tag`, `puuid`, `season`
* Will now be fetched directly if it's the current season (and not from 30min update cycle)
* Has a cache of 5min to reduce load
### New Version
```text theme={null}
/valorant/v3/leaderboard/:region/:platform
```
* Improved fetching performance
* Support for `pc` and `console`
* Streamlined data structure (no mix between camelCase and under\_score properties)
* New query params:
* `start_index`: `number` => Between `1` & `amount Of Players (dynamic)`
* `size`: `number` => Defaults to 1000 => Between `1` & `amount Of Players (dynamic)`
## Endpoint: MMR
### Changes
* The MMR v2 endpoints will now not have the ability anymore to filter by season with `?season`
### New Version
```text theme={null}
/valorant/v3/mmr/:region/:platform/:name/:tag
/valorant/v3/by-puuid/:region/:platform/:puuid
```
* Streamline property names (like `currenttier` => `tier` or `ranking_in_tier` => `rr`
* `by_season` is now an array
## Endpoint: Matches
### New Version
```text theme={null}
/valorant/v4/match/:region/:platform/:id
/valorant/v4/matches/:region/:platform/:name/:tag
/valorant/v4/by-puuid/matches/:region/:platform/:puuid
```
* Skipped v3 for `/valorant/:version/match/:region/:id` to align version numbers
* Added `region` param to the url
* This saves (potentially) 3 unnecessary requests to the riot servers => 3 requests less that can be used elsewhere
* Removes duplicate data fragments and unnecessary data
## Endpoint: Premier
### Changes
#### `/valorant/v1/premier/search`
* The API now only returns 50 entries if no query parameters are provided instead of the whole database
* This was a bug in v3 and not intentional
* Added a new property to each object: `updated_at: Date`
#### `/valorant/v1/premier/:name/:tag` & `/valorant/v1/premier/:id`
* These endpoints will now not return the 500 error code anymore
* You can still only find teams that are enrolled and indexed in the ingame leaderboard
* The leaderboard is getting scanned for updated/teams every three hours
# v4.0.1
Source: https://docs.henrikdev.xyz/valorant/changes/v4.0.1
Version 4.0.1 changelog
# v4.0.1
## Bug Fixes
* Fixed a bug where the `date` value in the `/valorant/v1/esports/schedule` response was not ISO8061 conform
* Fixed a bug where multiple `league` queries would create a deserialization error on the esports endpoint above
* Fixed a bug where the `queue` filter for v3/v4 match list endpoints would return an empty array when filtering for custom games -> Tradeoff: You can't filter for maps when using the queue filter AND search for customs
* Fix that `mode_id` was null on custom games
* Fix u8 (unsigned integer 8 bits) overflow on Team Deathmatch games, resulting in rounds lost of 167 for example instead of something between 0 and 100
## Changes
* The league query on the `/valorant/v1/esports/schedule` now should be comma separated (for example `vct-international,vct-emea`)
* You can't filter for maps anymore when using the `queue` filter on v3/v4 match list endpoints
# v4.1.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.1.0
Version 4.1.0 changelog
# v4.1.0
## New
* Added the ability to paginate through the matches v4 endpoints with the query `?start=INDEX`
* Added MMR History v2 (see [here](/valorant/api-reference/mmr-history))
* Added Stored MMR History v2 (see [here](/valorant/api-reference/stored-data))
## Bug Fixes
* Fixed the issue that you were not able to filter for custom mode and maps at the same time (only v4)
* Fixed an issue were the `x-cache-ttl` header value was 100x higher then expected on account v1 and v2
## Changes
* Internal changes to how the redis connection is handled to improve performance (marginal performance improvements from 2-5%)
* Matches v4 now has a new way on how matches are fetched
* This should mitigate missing matches when using the `map` and `size` filter for example
* **Before:** Size = 10 and map = ascent => Only the last 10 matches were filtered for the map, resulting in 2-3 matches returned
* **Now:** Size = 10 and map = ascent => Database is filtered for the last 10 matches that were played on ascent for this user, resulting in 10 matches returned (if enough data is stored)
# v4.2.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.2.0
Version 4.2.0 changelog
# v4.2.0
## New
### MMR v3
* Added field `rr` to `.peak` \[i32]
* Added field `end_rr` to `.seasonal[]` \[i32]
* Added `rank_protection_shields` to `.current` \[i32]
### MMR History v2
* Added field `refunded_rr` \[i32]
* Added field `was_derank_protected` \[bool]
### Stored MMR History v2
* Added field `refunded_rr` \[i32]
* Added field `was_derank_protected` \[bool]
## Fixed
### CDN
* Fixed 404 error on some new premier icons
## Removed
### Store Offers
Riot removed the endpoint for that data, as a result removing this endpoint
# v4.3.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.3.0
Version 4.3.0 changelog
# v4.3.0
## Changes
* Match Infrastructure is now using a combination of metadata via database + Backblaze B2 + Cloudflare CDN + Redis Cache
* This change is required to be able to serve the API (especially the stored matches) for free without the need of charging everyone for it.
## Fixes
* The cluster should now return the correct cluster name again instead of null
## Additional stuff
* Preparing stuff for the upcoming admin panel for the API
* Will include request history, analytics, ability to request keys and the option to unlock additional "features" like ttl cache removal (currently 5min)
# v4.5.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.5.0
Version 4.5.0 changelog
# v4.5.0
## Changes
* **Multiple Rate Limits**
* The API now supports multiple rate limits to allow burst applications more overhead.
* To support this, we've implemented the **IETF Draft for RateLimit headers** to provide a clear indication of limits within the headers.
* As this is a draft, specifications may change, but it is currently the best way to display multiple limits.
* This adds two new headers: `ratelimit-policy` and `ratelimit`.
* *Example:* `ratelimit: "per1min";r=86;t=58;pk=:NzExYTliNTMtYzc1ZS00ZjI2LTk2ZGMtNDg4NmI2OTc4NTlj:`
* *Example:* `ratelimit-policy: "per1min";q=90;w=60;pk=:NzExYTliNTMtYzc1ZS00ZjI2LTk2ZGMtNDg4NmI2OTc4NTlj:`
* For more info, check the [IETF Draft](https://www.ietf.org/archive/id/draft-ietf-httpapi-ratelimit-headers-10.txt) or ask an LLM using the documentation content.
* The X-Ratelimit-\* headers will continue to show the lowest/nearest rate limit to reach, for 99% of users will therefore nothing change
* **MMR v3 Peak RR**
* Now defaults to `0`. Check this thread to find out why: [Incorrect PEAK MMR](https://discord.com/channels/704231681309278228/1442622130683383848)
# v4.6.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.6.0
Version 4.6.0 changelog
# v4.6.0
## New
* New up-to-date OpenAPI specs
* You can find them at the respective instance with `/docs`
* Prod: [https://api.henrikdev.xyz/docs/](https://api.henrikdev.xyz/docs/)
* Beta: [https://beta.api.henrikdev.xyz/docs/](https://beta.api.henrikdev.xyz/docs/)
* **Esports v2 endpoints**
* Based on [https://www.vlr.gg/](https://www.vlr.gg/) data
* There are several new endpoints available
* `/valorant/v2/esports/vlr/events`
* `/valorant/v2/esports/vlr/events/{event_id}/matches`
* `/valorant/v2/esports/vlr/matches/{match_id}`
* `/valorant/v2/esports/vlr/teams/{team_id}`
* `/valorant/v2/esports/vlr/teams/{team_id}/matches`
* `/valorant/v2/esports/vlr/teams/{team_id}/transactions`
* `/valorant/v2/esports/vlr/players/{player_id}`
* `/valorant/v2/esports/vlr/players/{player_id}/matches`
* Additional endpoints may be added on request and their data availability
## Changes
* /v1/stored-matches now include `name`& `tag` for new games
* Old games will be filled with this data over time, no ETA
# v4.6.1
Source: https://docs.henrikdev.xyz/valorant/changes/v4.6.1
Version 4.6.1 changelog
# v4.6.1
## Changes
* API keys applications can now be canceled
* Some key types will now be auto reviewed by a small LLM to reduce spam, meaning setting "test" as a description will be rejected automatically
# v4.9.0
Source: https://docs.henrikdev.xyz/valorant/changes/v4.9.0
Version 4.9.0 changelog
# v4.9.0
## New
* **Premier team lookup**
* Team lookups by name and tag now support the optional `affinity` filter
* Team lookups by name or UUID can now resolve teams even if they are not on the leaderboard this season
* Requirement tho is the name hasn't changed in the meantime since last time on leaderboard AND had to be on the leaderboard atleast once (played an official game)
* Ambiguous name and tag matches now return an explicit conflict response
* **Premium tiers and features**
* Premium plans provide higher rate limits, shorter cache times, and webhook access for tracked users
* See [Premium Features](/general/premium) for available tiers, limits, and pricing
## Changes
* Request history and detailed statistics now load faster
* OpenAPI documentation now includes clearer summaries for Valorant and public API routes.
## Fixes
* Fixes that new matches will not receive "" as queueid if there is a new mode which is not 100% supported by the API yet
# Error Codes
Source: https://docs.henrikdev.xyz/valorant/error-codes
Error codes and their meanings
# Error Codes
The API might return errors on user input error (mostly 400 status code) or errors that are related to fetching/parsing on the API side. As there can be multiple errors, the error codes is an array.
| Code | Status | Meaning |
| :--: | :----: | :---------------------------------------------------------------------------------------------------- |
| 0 | 404 | Endpoint not found |
| 0 | 400 | General bad user input |
| 0 | 401 | Missing API Key [INFO](/general/auth) |
| 0 | 403 | Invalid API Key [INFO](/general/auth) |
| 0 | 429 | Rate Limit, check headers for more information |
| 1 | 500 | Internal Error |
| 2 | 501 | API Endpoint in this version does not exist |
| 3 | 404 | File not found |
| 4 | 400 | Invalid File |
| 5 | 500 | Error while parsing |
| 6 | 400 | Invalid region |
| 7 | 400 | Invalid Country Code |
| 8 | 400 | Invalid website category |
| 9 | 500 | Error while fetching needed resource |
| 10 | 400 | Unknown raw type |
| 11 | 400 | JSON parsing error. Check input JSON |
| 12 | - | - Internal - |
| 13 | 500 | Internal Redis connection error |
| 14 | - | - Internal - |
| 15 | 500 | Premier endpoint temporary issues (check discord) |
| 16 | 404 | Premier team not found |
| 17 | 400 | Query param `division` must be a number |
| 18 | 400 | Query param `division` must be a number between 1 & 21 |
| 19 | 400 | Invalid premier conference |
| 20 | 400 | Premier mixed querys detected (name & tag and puuid) |
| 21 | 500 | Error while connecting to regular database |
| 22 | 404 | Account not found |
| 23 | 404 | Region for user not found. Please ask the user to play a deathmatch or another gamemode |
| 24 | 404 | Error while fetching needed match data to retrieve users level & more |
| 25 | 404 | No MMR data found for user |
| 26 | 404 | Match not found |
| 27 | 400 | Invalid mode/queue |
| 28 | 400 | Invalid map |
| 29 | 400 | Missing query param `size` |
| 30 | 400 | Query param `size` & `page` must be a number |
| 31 | 400 | Query param `size` must be greater than 0 |
| 32 | 400 | Query param `page` must be greater than 0 |
| 33 | 400 | Invalid season |
| 34 | 400 | Query `name` is required |
| 35 | 400 | Query `tag` is required |
| 36 | 404 | User not found in leaderboard |
| 37 | 400 | Invalid league |
| 38 | 400 | Invalid locale |
| 39 | 400 | Invalid crosshair code |
| 40 | 400 | Duplicate Season query, please only supply one season query "season\_short" or "season\_id" at a time |
| 41 | 404 | Leaderboard metadata not found |
| 42 | 400 | Invalid platform, must be "pc" or "console" |
| 43 | 400 | Invalid UUID/PUUID |
| 44 | 400 | Query "division" must be 22 for super divisions |
| 45 | 400 | Query "start" must be a valid number greater than 0 |
| 46 | 404 | Riot has removed this implementation. Please check the changelog for more information |
# General
Source: https://docs.henrikdev.xyz/valorant/general
General information about the Valorant API
# General
* Version: v4.5.0
* Last Updated: 18.12.2025
# Premier Team Lookup
Source: https://docs.henrikdev.xyz/valorant/guides/premier-team-lookup
Premier team lookup behavior, seasons, affinities, and fallback resolution
# Premier Team Lookup
This guide explains how to integrate with the Premier team lookup endpoints, including season selection, affinity disambiguation, and fallback resolution.
## Endpoints
| Use case | Endpoint |
| ---------------------------------------------- | ----------------------------------------------- |
| Look up a team by name and tag | `GET /valorant/v1/premier/{name}/{tag}` |
| Look up a team by roster UUID | `GET /valorant/v1/premier/{id}` |
| Look up a team's match history by name and tag | `GET /valorant/v1/premier/{name}/{tag}/history` |
| Look up a team's match history by roster UUID | `GET /valorant/v1/premier/{id}/history` |
| Search the stored Premier team index | `GET /valorant/v1/premier/search` |
The name and UUID lookup endpoints return a full `PremierTeamV1Response` envelope:
```json theme={null}
{
"status": 200,
"data": {
"id": "roster-uuid",
"name": "Example Team",
"tag": "EXMP",
"enrolled": true,
"ranked": true,
"stats": {
"wins": 4,
"matches": 6,
"losses": 2,
"rounds_won": 78,
"rounds_lost": 64
},
"placement": {
"points": 250,
"conference": "EU",
"division": 5,
"place": 42
},
"customization": {
"icon": "icon-asset-id",
"image": "https://cdn.henrikdev.xyz/valorant/v1/premier/team-icon/icon-asset-id?primary=...",
"primary": "#112233",
"secondary": "#445566",
"tertiary": "#778899"
},
"member": [
{"puuid": "player-uuid", "name": "Player", "tag": "TAG"}
]
}
}
```
`enrolled` is the team's actual enrollment state. It is no longer reported as `true` for every team. `ranked` indicates whether a ranking is available for the team. The lightweight objects returned by search and leaderboard also include `ranked`.
## Season selection
The following endpoints accept the optional `season` query parameter:
* `/valorant/v1/premier/{name}/{tag}`
* `/valorant/v1/premier/{name}/{tag}/history`
* `/valorant/v1/premier/{id}`
* `/valorant/v1/premier/{id}/history`
* `/valorant/v1/premier/search`
* `/valorant/v1/premier/leaderboard/{affinity}` and its conference/division variants
`season` is a Premier season ID. Season IDs can be obtained from `GET /valorant/v1/premier/seasons/{affinity}`.
If `season` is omitted, the API uses the current Premier season. If it is supplied, the ID is validated before the lookup. An invalid season returns HTTP `400` with the `Invalid season` error. When an affinity is supplied to a direct team lookup, the season must also exist for that affinity.
For a historical season, the history endpoints return the season's stored history. The live Riot match-history refresh is performed only for the current season. This means an old season should be treated as an archived snapshot, not as a live feed.
## Affinity disambiguation
The direct name and UUID lookup endpoints accept an optional `affinity` query parameter:
```text theme={null}
GET /valorant/v1/premier/Example%20Team/EXMP?season=&affinity=eu
GET /valorant/v1/premier/?season=&affinity=eu
```
Supported affinity values are `na`, `eu`, `ap`, `kr`, `br`, and `latam`. `br` and `latam` use the NA Riot service region internally, while remaining distinct API affinity values.
The affinity filter is useful when the same name/tag is used by more than one team. Without enough information to identify one team, the name lookup returns HTTP `409`:
```json theme={null}
{
"errors": [
{
"code": 49,
"message": "Multiple Premier teams match this name and tag. Supply an affinity query.",
"status": 409,
"details": null
}
]
}
```
The UUID lookup cannot be ambiguous because the UUID identifies the roster. It uses `affinity` to restrict which Riot service region is queried and to verify the returned team.
## How resolution works
The lookup is backed by both the local Premier index and Riot's public roster information:
1. The API checks the stored team record for the requested season.
2. If a name/tag lookup is not already stored for that season, it checks known teams with the same name/tag and revalidates them against Riot's public roster endpoint for the requested season.
3. If a UUID lookup is not stored, it probes the relevant Riot service region, or all supported regions when no affinity is provided.
4. The Riot response is accepted only when the roster has data for the requested season and the returned identity and affinity match the request.
5. A successfully resolved team is stored for later requests.
The name fallback is not a global Riot name search. It can rehydrate a team when the API already knows a candidate roster UUID from another stored season or lookup. A completely new name/tag may therefore still return `Premier Team not found` until a roster UUID or team record becomes known.
The fallback can also be slower and may consume background requests because it may contact Riot. A cache hit is normally returned directly from the stored team record.
## Lookup errors to handle
| HTTP status | Meaning |
| ----------- | ---------------------------------------------------------------------- |
| `400` | Invalid season, invalid affinity, or an invalid UUID on the UUID route |
| `404` | No team could be resolved for the requested season |
| `409` | Name/tag matches multiple teams; retry with `affinity` |
# Stored Matches
Source: https://docs.henrikdev.xyz/valorant/guides/stored-matches
Stored match history, pagination, and match-list completeness behavior
# Stored Matches
This guide explains how stored match history is built, paginated, and why it may be incomplete compared with Riot's full history.
## Endpoints
| Use case | Endpoint |
| ------------------------- | ------------------------------------------------------------- |
| Stored matches by Riot ID | `GET /valorant/v1/stored-matches/{affinity}/{name}/{tag}` |
| Stored matches by PUUID | `GET /valorant/v1/by-puuid/stored-matches/{affinity}/{puuid}` |
Both endpoints return the same response shape. The Riot ID route resolves the account first; the PUUID route uses the supplied player UUID.
## Query parameters
| Parameter | Description |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `mode` | Optional game-mode filter, using the API's mode name such as `competitive` or `unrated` |
| `map` | Optional map-name filter such as `Ascent` |
| `size` | Optional page size. Use a positive integer when paginating. If omitted, the endpoint returns all currently stored matching records. |
| `page` | Optional 1-based page number. `size` is required when `page` is used. |
Example:
```text theme={null}
GET /valorant/v1/stored-matches/eu/Example/1234?mode=competitive&map=Ascent&size=20&page=1
```
Results are sorted newest first by match start time. `page` and `size` are applied to the stored database records after the API has attempted to fetch the recent match IDs from Riot.
## Response shape
```json theme={null}
{
"status": 200,
"results": {
"total": 1,
"returned": 1,
"before": 0,
"after": 0
},
"data": [
{
"meta": {
"id": "match-uuid",
"map": {"id": "map-uuid", "name": "Ascent"},
"version": "release-10.00-shipping-12-3456789",
"mode": "Competitive",
"started_at": "2026-07-10T12:34:56Z",
"season": {"id": "season-uuid", "short": "E10A5"},
"region": "eu",
"cluster": "Frankfurt"
},
"stats": {
"puuid": "player-uuid",
"name": "Example",
"tag": "1234",
"team": "Blue",
"level": 150,
"character": {"id": "agent-uuid", "name": "Jett"},
"tier": 22,
"score": 250,
"kills": 20,
"deaths": 15,
"assists": 5,
"shots": {"head": 10, "body": 40, "leg": 5},
"damage": {"made": 3200, "received": 2800}
},
"teams": {"red": 13, "blue": 9}
}
]
}
```
`results.total`, `results.returned`, `before`, and `after` refer to the stored records matching the request. `teams.red` and `teams.blue` are the stored round-win values; they are not team IDs.
## Important completeness behavior
Stored matches are an accumulating materialized subset of Riot's match history, not a pre-populated mirror of every match.
When a stored-matches request runs, the API:
1. Fetches the player's recent match IDs from Riot's competitive-updates history.
2. Attempts to fetch each match's full details.
3. Stores successful match details in the match store and writes searchable metadata for the players, map, mode, season, and teams.
4. Reads the response from the stored metadata collection, applying the requested filters and pagination.
The endpoint does not return a placeholder for a match that could not be fetched or stored. A match may be absent because Riot did not return usable details, the match is temporarily unavailable, storage failed or was simply never requested by any developer using this API. The fetch attempts run concurrently and their individual errors are not returned as per-item errors by this endpoint.
As a result:
* The list may have holes compared with Riot's match history.
* `total` is not the player's total number of matches; it is the number currently stored that match the filters.
* A page can change between requests as previously unavailable matches are successfully stored.
* A successful fetch normally makes that match available to later stored-matches requests, subject to the same account, affinity, mode, and map filters.
Consumers should use `meta.id` and `meta.started_at` to identify and order matches, tolerate missing matches, and avoid assuming that page boundaries represent fixed positions in Riot's complete history. If a complete or immediately live history is required, use the non-stored match-history endpoints instead and treat their full-match availability separately.