diff --git a/.DS_Store b/.DS_Store index d54028f..d977ea7 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index f540d57..efb132e 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,6 @@ go.work.sum data/nba.db /data/ /data -/data/*.DS_Store +/data/* +docs/restore_dump_remote.md +./docs/restore_dump_remote.md diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d9951f1 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +# Tells 'make' these are command names, not files +.PHONY: up down + +# Command to run: make up +up: + docker-compose -f docker-compose.local.yml up --build -d + +# Command to run: make down +down: + docker-compose down \ No newline at end of file diff --git a/README.md b/README.md index 2652ff9..61854ee 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # NBA_Go -### First‑time bootstrap +## First‑time bootstrap ```bash # 1. build + run @@ -18,19 +18,23 @@ curl http://localhost:8080/api/playeradvancedstats \ ``` -### Swagger Initiate Docs +## Swagger Initiate Docs ```bash swag init -g main.go -o docs ``` -### Test +## Test ```bash go run loadtest.go -n 100 -c 10 -url "http://127.0.0.1:8080/api/playeradvancedstats?page=1&pageSize=20" -log results.log -key "xxx" ``` -### Local Environment +## Local Environment + +```bash +docker compose down +``` ```bash docker-compose -f docker-compose.local.yml up --build -d diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 847d123..fafea45 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -125,4 +125,4 @@ volumes: grafana_data: networks: - api.network: null \ No newline at end of file + api.network: null diff --git a/docs/.DS_Store b/docs/.DS_Store index c6241e5..a80ce38 100644 Binary files a/docs/.DS_Store and b/docs/.DS_Store differ diff --git a/docs/postman/NBA Statistics Go.postman_collection.json b/docs/postman/NBA Statistics Go.postman_collection.json index 117627c..9527849 100644 --- a/docs/postman/NBA Statistics Go.postman_collection.json +++ b/docs/postman/NBA Statistics Go.postman_collection.json @@ -2,12 +2,1020 @@ "info": { "_postman_id": "f0cb3c13-063b-490a-aa7f-5af135aacbe6", "name": "NBA Statistics Go", - "description": "This collection provides access to the NBA_Go API, a service for retrieving comprehensive NBA player statistics. You can fetch total stats, advanced metrics, and detailed shot chart data.\n\n## Authentication\n\nAuthentication is not currently required for public endpoints. Future versions may require an API key to be sent in the `x-api-key` header.\n\n## Pagination\n\nThe stats endpoints (`playertotals` and `playeradvancedstats`) return a `pagination` object with metadata about the current page, page size, total pages, and total results.\n\nThe `playershotchart` endpoint has a fixed page size of 50 results.", + "description": "# NBA Statistics Go API\n\nThe NBA Statistics Go API provides comprehensive access to NBA player statistics, game data, and shot chart information. This RESTful API allows developers to retrieve historical and current season data for players, teams, and games across both regular season and playoff periods.\n\n## Base URL\n\nAll API requests should be made to the base URL stored in the `{{base_url}}` variable:\n\n``` text\nhttps://api.server.nbaapi.com\n\n ```\n\n## Authentication\n\n**No authentication is currently required** for accessing public endpoints. All endpoints are openly accessible without API keys or tokens.\n\n**Future Considerations:** Upcoming versions may introduce API key authentication via the `x-api-key` header for rate limiting and usage tracking purposes.\n\n## Pagination\n\nThe API implements cursor-based pagination for endpoints that return large datasets. Pagination behavior varies by endpoint:\n\n### Stats Endpoints (`/api/playertotals` and `/api/playeradvancedstats`)\n\nThese endpoints return a `pagination` object in the response containing:\n\n- **`page`** (integer): Current page number\n \n- **`pageSize`** (integer): Number of results per page (configurable via query parameter)\n \n- **`totalPages`** (integer): Total number of pages available\n \n- **`totalResults`** (integer): Total number of records matching the query\n \n\n**Query Parameters:**\n\n- `page` (integer, optional): Page number to retrieve. Defaults to `1`.\n \n- `pageSize` (integer, optional): Number of results per page. Defaults to `20`. Maximum recommended: `100`.\n \n\n### Shot Chart Endpoint (`/api/playershotchart`)\n\nThis endpoint has a **fixed page size of 50 results** per page. Use the `page` parameter to navigate through results.\n\n### Games Endpoint (`/api/games`)\n\nSupports flexible pagination with `page` and `pageSize` parameters similar to stats endpoints.\n\n## Common Query Parameters\n\nMany endpoints share common query parameters for filtering and sorting:\n\n| Parameter | Type | Description | Example |\n| --- | --- | --- | --- |\n| `season` | integer | Four-digit season year (year the season ends) | `2025` for 2024-25 season |\n| `team` | string | Three-letter team abbreviation | `LAL`, `BOS`, `GSW` |\n| `playerId` | string | Unique player identifier (Basketball Reference format) | `jamesle01`, `curryst01` |\n| `page` | integer | Page number for pagination | `1`, `2`, `3` |\n| `pageSize` | integer | Results per page (where applicable) | `20`, `50`, `100` |\n| `isPlayoff` | boolean | Filter for playoff vs regular season data | `true`, `false` |\n| `sortBy` | string | Field name to sort results by | `points`, `assists`, `winShares` |\n| `ascending` | boolean | Sort order direction | `true` (ascending), `false` (descending) |\n\n## Response Format\n\nAll API responses are returned in **JSON format** with the following general structure:\n\n### Successful Response (Games Endpoint)\n\n``` json\n{\n \"data\": [\n {\n \"gameId\": \"202512140POR\",\n \"date\": \"2025-12-14T14:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"9:00p\",\n \"arena\": \"Moda Center\",\n \"visitorTeam\": \"GSW\",\n \"visitorPts\": 131,\n \"homeTeam\": \"POR\",\n \"homePts\": 136,\n \"gameDuration\": \"2:23\"\n },\n {\n \"gameId\": \"202512140PHO\",\n \"date\": \"2025-12-14T13:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"8:00p\",\n \"arena\": \"Mortgage Matchup Center\",\n \"visitorTeam\": \"LAL\",\n \"visitorPts\": 116,\n \"homeTeam\": \"PHX\",\n \"homePts\": 114,\n \"gameDuration\": \"2:43\"\n },\n {\n \"gameId\": \"202512140CHI\",\n \"date\": \"2025-12-14T12:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"7:00p\",\n \"arena\": \"United Center\",\n \"visitorTeam\": \"NOP\",\n \"visitorPts\": 114,\n \"homeTeam\": \"CHI\",\n \"homePts\": 104,\n \"gameDuration\": \"2:14\"\n }\n ],\n \"pagination\": {\n \"total\": 26101,\n \"page\": 1,\n \"pageSize\": 3,\n \"pages\": 8701\n }\n}\n\n ```\n\n### Successful Response (Player Total Stats)\n\n``` json\n{\n \"data\": [\n {\n \"playerId\": \"duranke01\",\n \"playerName\": \"Kevin Durant\",\n \"position\": \"SF\",\n \"age\": 37,\n \"games\": 20,\n \"gamesStarted\": 20,\n \"minutesPg\": 707,\n \"fieldGoals\": 172,\n \"fieldAttempts\": 345,\n \"fieldPercent\": 0.499,\n \"threeFg\": 36,\n \"threeAttempts\": 91,\n \"threePercent\": 0.396,\n \"twoFg\": 136,\n \"twoAttempts\": 254,\n \"twoPercent\": 0.535,\n \"effectFgPercent\": 0.551,\n \"ft\": 116,\n \"ftAttempts\": 130,\n \"ftPercent\": 0.892,\n \"offensiveRb\": 6,\n \"defensiveRb\": 86,\n \"totalRb\": 92,\n \"assists\": 77,\n \"steals\": 19,\n \"blocks\": 12,\n \"turnovers\": 59,\n \"personalFouls\": 48,\n \"points\": 496,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"sengual01\",\n \"playerName\": \"Alperen ŞengΓΌn\",\n \"position\": \"C\",\n \"age\": 23,\n \"games\": 20,\n \"gamesStarted\": 20,\n \"minutesPg\": 718,\n \"fieldGoals\": 170,\n \"fieldAttempts\": 341,\n \"fieldPercent\": 0.499,\n \"threeFg\": 20,\n \"threeAttempts\": 55,\n \"threePercent\": 0.364,\n \"twoFg\": 150,\n \"twoAttempts\": 286,\n \"twoPercent\": 0.524,\n \"effectFgPercent\": 0.528,\n \"ft\": 100,\n \"ftAttempts\": 136,\n \"ftPercent\": 0.735,\n \"offensiveRb\": 60,\n \"defensiveRb\": 128,\n \"totalRb\": 188,\n \"assists\": 140,\n \"steals\": 29,\n \"blocks\": 19,\n \"turnovers\": 67,\n \"personalFouls\": 69,\n \"points\": 460,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"thompam01\",\n \"playerName\": \"Amen Thompson\",\n \"position\": \"PG\",\n \"age\": 23,\n \"games\": 22,\n \"gamesStarted\": 22,\n \"minutesPg\": 796,\n \"fieldGoals\": 150,\n \"fieldAttempts\": 310,\n \"fieldPercent\": 0.484,\n \"threeFg\": 9,\n \"threeAttempts\": 47,\n \"threePercent\": 0.191,\n \"twoFg\": 141,\n \"twoAttempts\": 263,\n \"twoPercent\": 0.536,\n \"effectFgPercent\": 0.498,\n \"ft\": 76,\n \"ftAttempts\": 94,\n \"ftPercent\": 0.809,\n \"offensiveRb\": 58,\n \"defensiveRb\": 99,\n \"totalRb\": 157,\n \"assists\": 115,\n \"steals\": 30,\n \"blocks\": 11,\n \"turnovers\": 57,\n \"personalFouls\": 56,\n \"points\": 385,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n }\n ],\n \"pagination\": {\n \"total\": 14,\n \"page\": 1,\n \"pageSize\": 3,\n \"pages\": 5\n }\n}\n\n ```\n\n### Error Response\n\n``` json\n{\n \"error\": \"Cannot GET /api/playertotal\"\n}\n\n ```\n\n## Error Handling\n\nThe API uses standard HTTP status codes to indicate success or failure:\n\n| Status Code | Meaning | Common Causes |\n| --- | --- | --- |\n| `200 OK` | Request successful | Valid request with results |\n| `400 Bad Request` | Invalid request parameters | Malformed query parameters, invalid data types |\n| `404 Not Found` | Resource not found | Invalid endpoint or no data matching criteria |\n| `500 Internal Server Error` | Server error | Unexpected server-side issue |\n| `503 Service Unavailable` | Service temporarily unavailable | Maintenance or high load |\n\n**Best Practices:**\n\n- Always check the HTTP status code before processing response data\n \n- Implement retry logic with exponential backoff for 5xx errors\n \n- Validate query parameters before making requests\n \n\n## Rate Limiting\n\n**Current Status:** No rate limiting is enforced on public endpoints.\n\n**Recommendations:**\n\n- Implement client-side throttling to avoid overwhelming the API\n \n- Cache responses when appropriate to reduce redundant requests\n \n- Consider batching requests during off-peak hours for large data pulls\n \n\n## Data Information\n\n### Season Year Format\n\nSeason years are represented by the **year in which the season ends**. For example:\n\n- `2025` represents the 2024-25 NBA season\n \n- `2024` represents the 2023-24 NBA season\n \n\n### Player ID Format\n\nPlayer IDs follow the Basketball Reference naming convention:\n\n- Format: First 5 letters of last name + first 2 letters of first name + `01` (incremented for duplicates)\n \n- Examples: `jamesle01` (LeBron James), `curryst01` (Stephen Curry), `duranke01` (Kevin Durant)\n \n\n### Playoff vs Regular Season Data\n\nUse the `isPlayoff` parameter to distinguish between regular season and playoff statistics:\n\n- `isPlayoff=false` or omitted: Regular season data\n \n- `isPlayoff=true`: Playoff data only\n \n\n**Note:** Playoff data is only available for players/teams that qualified for the playoffs in a given season.\n\n### Data Freshness\n\n- **Historical Data:** Complete data available from the 1946-47 season onwards\n \n- **Current Season:** Data is updated daily, typically within 2-4 hours after games conclude\n \n- **Live Data:** This API does not provide real-time game data\n \n\n### Team Abbreviations\n\nThe API uses standard three-letter NBA team abbreviations. Common examples:\n\n| Team | Abbreviation | Team | Abbreviation |\n| --- | --- | --- | --- |\n| Atlanta Hawks | ATL | Memphis Grizzlies | MEM |\n| Boston Celtics | BOS | Miami Heat | MIA |\n| Brooklyn Nets | BKN | Milwaukee Bucks | MIL |\n| Charlotte Hornets | CHA | Minnesota Timberwolves | MIN |\n| Chicago Bulls | CHI | New Orleans Pelicans | NOP |\n| Cleveland Cavaliers | CLE | New York Knicks | NYK |\n| Dallas Mavericks | DAL | Oklahoma City Thunder | OKC |\n| Denver Nuggets | DEN | Orlando Magic | ORL |\n| Detroit Pistons | DET | Philadelphia 76ers | PHI |\n| Golden State Warriors | GSW | Phoenix Suns | PHX |\n| Houston Rockets | HOU | Portland Trail Blazers | POR |\n| Indiana Pacers | IND | Sacramento Kings | SAC |\n| LA Clippers | LAC | San Antonio Spurs | SAS |\n| Los Angeles Lakers | LAL | Toronto Raptors | TOR |\n| Utah Jazz | UTA | Washington Wizards | WAS |\n\n**Note:** Historical teams use their abbreviations from the respective era (e.g., SEA for Seattle SuperSonics).\n\n## Common Use Cases\n\n### 1\\. Get Current Season Leaders\n\nRetrieve top scorers for the current season:\n\n``` http\nGET /api/playertotals?season=2025&page=1&pageSize=10&sortBy=points&ascending=false\n\n ```\n\n### 2\\. Team Roster Statistics\n\nGet all statistics for a specific team:\n\n``` http\nGET /api/playertotals?season=2025&team=LAL&pageSize=20\n\n ```\n\n### 3\\. Player Career Playoff Performance\n\nRetrieve a player's playoff statistics across multiple seasons:\n\n``` http\nGET /api/playertotals?playerId=jamesle01&isPlayoff=true&pageSize=50\n\n ```\n\n### 4\\. Advanced Analytics Comparison\n\nCompare advanced metrics for multiple players:\n\n``` http\nGET /api/playeradvancedstats?season=2025&sortBy=vorp&ascending=false&pageSize=50\n\n ```\n\n### 5\\. Shot Chart Visualization\n\nGet shot chart data for a specific player and game:\n\n``` http\nGET /api/playershotchart?playerId=curryst01&date=Dec 25,2024&page=1\n\n ```\n\n### 6\\. Historical Game Data\n\nRetrieve games from a specific date range:\n\n``` http\nGET /api/games?page=1&pageSize=20&sortBy=date&ascending=false\n\n ```\n\n## API Endpoints Overview\n\nThis collection includes the following endpoints:\n\n1. **Games** - Retrieve game schedules and results\n \n2. **Player Totals Stats** - Traditional counting statistics (points, rebounds, assists, etc.)\n \n3. **Player Totals Playoffs Stats** - Playoff-specific counting statistics\n \n4. **Player Advanced Stats** - Advanced metrics (PER, Win Shares, VORP, etc.)\n \n5. **Player Advanced Playoff Stats** - Playoff-specific advanced metrics\n \n6. **Shot Chart** - Detailed shot location and outcome data\n \n\n## Additional Resources\n\n- **API Status:** Check service status and uptime at the provider's status page\n \n- **Support:** For questions or issues, contact the API maintainers\n \n- **Updates:** Monitor the changelog for API updates and new features\n \n\n## Tips for Optimal Usage\n\n1. **Use Specific Filters:** Narrow down queries with season, team, or player filters to reduce response size\n \n2. **Implement Caching:** Cache frequently accessed data (e.g., historical statistics) to improve performance\n \n3. **Batch Requests:** When retrieving data for multiple entities, consider batching requests\n \n4. **Monitor Response Times:** Track API response times and adjust `pageSize` if experiencing slowdowns\n \n5. **Handle Empty Results:** Always check if the `data` array is empty before processing results\n \n6. **Validate Player IDs:** Verify player ID format before making requests to avoid 404 errors\n \n\n---\n\n**Version:** 1.0 \n**Last Updated:** 2025", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "25652688", "_collection_link": "https://www.postman.com/solar-meadow-682296/workspace/nba-stats/collection/25652688-f0cb3c13-063b-490a-aa7f-5af135aacbe6?action=share&source=collection_link&creator=25652688" }, "item": [ + { + "name": "Games", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var template = `", + "", + "
", + "
NBA Games
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each games}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/each}}", + " ", + "
Game IDDateVisitor TeamVisitor PtsHome TeamHome PtsArenaDuration
{{gameId}}{{date}}{{visitorTeam}}{{visitorPts}}{{homeTeam}}{{homePts}}{{arena}}{{gameDuration}}
", + "
", + "`;", + "", + "function constructVisualizerPayload() {", + " var response = pm.response.json();", + " var games = response.data.map(function(game) {", + " var dateObj = new Date(game.date);", + " var formattedDate = dateObj.toLocaleDateString('en-US', {", + " year: 'numeric',", + " month: 'short',", + " day: 'numeric'", + " });", + " return {", + " gameId: game.gameId,", + " date: formattedDate,", + " visitorTeam: game.visitorTeam,", + " visitorPts: game.visitorPts,", + " homeTeam: game.homeTeam,", + " homePts: game.homePts,", + " arena: game.arena,", + " gameDuration: game.gameDuration || 'N/A'", + " };", + " });", + " return { games: games };", + "}", + "", + "pm.visualizer.set(template, constructVisualizerPayload());" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=3&sortBy=date&ascending=false", + "protocol": "https", + "host": [ + "api", + "server", + "nbaapi", + "com" + ], + "path": [ + "api", + "games" + ], + "query": [ + { + "key": "isPlayoff", + "value": "false" + }, + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "3" + }, + { + "key": "sortBy", + "value": "date" + }, + { + "key": "ascending", + "value": "false" + }, + { + "key": "include", + "value": "lineScores%2C%20playerGameBasicStats", + "disabled": true + } + ] + } + }, + "response": [ + { + "name": "Games", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=8&sortBy=date&ascending=false", + "protocol": "https", + "host": [ + "api", + "server", + "nbaapi", + "com" + ], + "path": [ + "api", + "games" + ], + "query": [ + { + "key": "isPlayoff", + "value": "false" + }, + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "8" + }, + { + "key": "sortBy", + "value": "date" + }, + { + "key": "ascending", + "value": "false" + }, + { + "key": "include", + "value": "lineScores%2C%20playerGameBasicStats", + "disabled": true + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": [ + { + "key": "Alt-Svc", + "value": "h3=\":443\"; ma=2592000" + }, + { + "key": "Content-Encoding", + "value": "br" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Date", + "value": "Tue, 16 Dec 2025 07:47:19 GMT" + }, + { + "key": "Server", + "value": "nginx/1.28.0" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "Content-Length", + "value": "433" + } + ], + "cookie": [], + "body": "{\n \"data\": [\n {\n \"gameId\": \"202512140POR\",\n \"date\": \"2025-12-14T14:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"9:00p\",\n \"arena\": \"Moda Center\",\n \"visitorTeam\": \"GSW\",\n \"visitorPts\": 131,\n \"homeTeam\": \"POR\",\n \"homePts\": 136,\n \"gameDuration\": \"2:23\"\n },\n {\n \"gameId\": \"202512140PHO\",\n \"date\": \"2025-12-14T13:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"8:00p\",\n \"arena\": \"Mortgage Matchup Center\",\n \"visitorTeam\": \"LAL\",\n \"visitorPts\": 116,\n \"homeTeam\": \"PHX\",\n \"homePts\": 114,\n \"gameDuration\": \"2:43\"\n },\n {\n \"gameId\": \"202512140CHI\",\n \"date\": \"2025-12-14T12:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"7:00p\",\n \"arena\": \"United Center\",\n \"visitorTeam\": \"NOP\",\n \"visitorPts\": 114,\n \"homeTeam\": \"CHI\",\n \"homePts\": 104,\n \"gameDuration\": \"2:14\"\n },\n {\n \"gameId\": \"202512140MIN\",\n \"date\": \"2025-12-14T12:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"7:00p\",\n \"arena\": \"Target Center\",\n \"visitorTeam\": \"SAC\",\n \"visitorPts\": 103,\n \"homeTeam\": \"MIN\",\n \"homePts\": 117,\n \"gameDuration\": \"2:11\"\n },\n {\n \"gameId\": \"202512140ATL\",\n \"date\": \"2025-12-14T11:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"6:00p\",\n \"arena\": \"State Farm Arena\",\n \"visitorTeam\": \"PHI\",\n \"visitorPts\": 117,\n \"homeTeam\": \"ATL\",\n \"homePts\": 120,\n \"gameDuration\": \"2:21\"\n },\n {\n \"gameId\": \"202512140BRK\",\n \"date\": \"2025-12-14T11:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"6:00p\",\n \"arena\": \"Barclays Center\",\n \"visitorTeam\": \"MIL\",\n \"visitorPts\": 82,\n \"homeTeam\": \"BKN\",\n \"homePts\": 127,\n \"gameDuration\": \"2:05\"\n },\n {\n \"gameId\": \"202512140CLE\",\n \"date\": \"2025-12-14T08:30:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"3:30p\",\n \"arena\": \"Rocket Arena\",\n \"visitorTeam\": \"CHA\",\n \"visitorPts\": 119,\n \"homeTeam\": \"CLE\",\n \"homePts\": 111,\n \"gameDuration\": \"\"\n },\n {\n \"gameId\": \"202512140IND\",\n \"date\": \"2025-12-14T08:00:00Z\",\n \"isPlayoff\": false,\n \"startTimeET\": \"3:00p\",\n \"arena\": \"Gainbridge Fieldhouse\",\n \"visitorTeam\": \"WAS\",\n \"visitorPts\": 108,\n \"homeTeam\": \"IND\",\n \"homePts\": 89,\n \"gameDuration\": \"2:20\"\n }\n ],\n \"pagination\": {\n \"total\": 26101,\n \"page\": 1,\n \"pageSize\": 8,\n \"pages\": 3263\n }\n}" + } + ] + }, + { + "name": "Games Detail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var template = `", + "", + "", + "
", + " ", + "
", + "
", + " πŸ“Š Games Summary", + "
", + "
", + "
", + "
", + "
{{totalGames}}
", + "
Total Games
", + "
", + "
", + "
{{avgScore}}
", + "
Avg Total Score
", + "
", + "
", + "
{{highestScore}}
", + "
Highest Team Score
", + "
", + "
", + "
", + "
", + "", + " ", + "
", + "
", + " πŸ€ NBA Games Overview", + "
", + "
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each games}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/each}}", + " ", + "
Game IDDateVisitorScoreHomeScoreArenaDuration
{{gameId}}{{date}}{{visitorTeam}}{{visitorPts}}{{homeTeam}}{{homePts}}{{arena}}{{gameDuration}}
", + "
", + "
", + "", + " ", + "
", + "
", + " πŸ“ˆ Detailed Game Breakdown", + "
", + "
", + " {{#each gamesDetailed}}", + "
", + "
", + "
{{visitorTeam}} {{visitorPts}} @ {{homeTeam}} {{homePts}}
", + "
{{date}} | {{arena}}
", + "
", + "
", + " ", + "

Quarter-by-Quarter Breakdown

", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#if hasOT}}", + " ", + " ", + " ", + " {{/if}}", + " ", + " ", + " ", + " ", + " {{#each lineScores}}", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#if ../hasOT}}", + " ", + " ", + " ", + " {{/if}}", + " ", + " ", + " {{/each}}", + " ", + "
TeamQ1Q2Q3Q4OT1OT2OT3Total
{{team}}{{q1}}{{q2}}{{q3}}{{q4}}{{ot1}}{{ot2}}{{ot3}}{{total}}
", + "", + " ", + "
", + "
Scoring by Quarter
", + " ", + "
", + "", + " ", + "
", + " {{#each teamStats}}", + "
", + " {{teamName}} Player Statistics", + "
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each players}}", + " ", + " {{#if isDNP}}", + " ", + " ", + " {{else}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/if}}", + " ", + " {{/each}}", + " ", + "
PlayerMINPTSFGFG%3P3P%FTFT%REBASTSTLBLKTOV+/-
{{playerName}}Did Not Play{{playerName}}{{mp}}{{pts}}{{fg}}-{{fga}}{{fgPct}}{{threeP}}-{{threePa}}{{threePPct}}{{ft}}-{{fta}}{{ftPct}}{{trb}}{{ast}}{{stl}}{{blk}}{{tov}}{{plusMinusDisplay}}
", + " {{/each}}", + "
", + "
", + "
", + " {{/each}}", + "
", + "
", + "
", + "", + "", + "", + "`;", + "", + "function constructVisualizerPayload() {", + " var response = pm.response.json();", + " var data = response.data || [];", + " ", + " // Calculate summary stats", + " var totalGames = data.length;", + " var totalScores = data.map(function(g) { return g.visitorPts + g.homePts; });", + " var avgScore = totalGames > 0 ? Math.round(totalScores.reduce(function(a, b) { return a + b; }, 0) / totalGames) : 0;", + " var allScores = [];", + " data.forEach(function(g) {", + " allScores.push(g.visitorPts);", + " allScores.push(g.homePts);", + " });", + " var highestScore = allScores.length > 0 ? Math.max.apply(null, allScores) : 0;", + " ", + " // Format games for overview table", + " var games = data.map(function(game) {", + " var dateObj = new Date(game.date);", + " var formattedDate = dateObj.toLocaleDateString('en-US', { ", + " month: 'short', ", + " day: 'numeric', ", + " year: 'numeric' ", + " });", + " ", + " var visitorWon = game.visitorPts > game.homePts;", + " ", + " return {", + " gameId: game.gameId,", + " date: formattedDate,", + " visitorTeam: game.visitorTeam,", + " visitorPts: game.visitorPts,", + " visitorClass: visitorWon ? 'winner' : 'loser',", + " homeTeam: game.homeTeam,", + " homePts: game.homePts,", + " homeClass: visitorWon ? 'loser' : 'winner',", + " arena: game.arena,", + " gameDuration: game.gameDuration", + " };", + " });", + " ", + " // Format detailed game data", + " var gamesDetailed = data.map(function(game, index) {", + " var dateObj = new Date(game.date);", + " var formattedDate = dateObj.toLocaleDateString('en-US', { ", + " weekday: 'short',", + " month: 'short', ", + " day: 'numeric', ", + " year: 'numeric' ", + " });", + " ", + " // Check if overtime was played", + " var hasOT = false;", + " if (game.lineScores && game.lineScores.length > 0) {", + " game.lineScores.forEach(function(ls) {", + " if (ls.ot1 > 0 || ls.ot2 > 0 || ls.ot3 > 0) {", + " hasOT = true;", + " }", + " });", + " }", + " ", + " // Group players by team", + " var teamStatsMap = {};", + " if (game.playerGameBasicStats) {", + " game.playerGameBasicStats.forEach(function(player) {", + " if (!teamStatsMap[player.team]) {", + " teamStatsMap[player.team] = [];", + " }", + " ", + " var isDNP = player.status === 'Did Not Play' || player.mp === '';", + " var plusMinusVal = player.plusMinus || 0;", + " ", + " teamStatsMap[player.team].push({", + " playerName: player.playerName,", + " mp: player.mp || '-',", + " pts: player.pts,", + " fg: player.fg,", + " fga: player.fga,", + " fgPct: player.fgPercent ? (player.fgPercent * 100).toFixed(1) + '%' : '-',", + " threeP: player.threeP,", + " threePa: player.threePa,", + " threePPct: player.threePPercent ? (player.threePPercent * 100).toFixed(1) + '%' : '-',", + " ft: player.ft,", + " fta: player.fta,", + " ftPct: player.ftPercent ? (player.ftPercent * 100).toFixed(1) + '%' : '-',", + " trb: player.trb,", + " ast: player.ast,", + " stl: player.stl,", + " blk: player.blk,", + " tov: player.tov,", + " plusMinus: plusMinusVal,", + " plusMinusDisplay: plusMinusVal > 0 ? '+' + plusMinusVal : plusMinusVal.toString(),", + " plusMinusClass: plusMinusVal > 0 ? 'positive' : (plusMinusVal < 0 ? 'negative' : ''),", + " isDNP: isDNP", + " });", + " });", + " }", + " ", + " // Convert to array and sort by points", + " var teamStats = Object.keys(teamStatsMap).map(function(teamName) {", + " var players = teamStatsMap[teamName].sort(function(a, b) {", + " return b.pts - a.pts;", + " });", + " return {", + " teamName: teamName,", + " players: players", + " };", + " });", + " ", + " return {", + " gameIndex: index,", + " gameId: game.gameId,", + " date: formattedDate,", + " visitorTeam: game.visitorTeam,", + " visitorPts: game.visitorPts,", + " homeTeam: game.homeTeam,", + " homePts: game.homePts,", + " arena: game.arena,", + " gameDuration: game.gameDuration,", + " hasOT: hasOT,", + " lineScores: game.lineScores || [],", + " teamStats: teamStats", + " };", + " });", + " ", + " return {", + " totalGames: totalGames,", + " avgScore: avgScore,", + " highestScore: highestScore,", + " games: games,", + " gamesDetailed: gamesDetailed", + " };", + "}", + "", + "pm.visualizer.set(template, constructVisualizerPayload());" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "protocolProfileBehavior": { + "disableCookies": true + }, + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=5&sortBy=date&ascending=false&include=lineScores%2C%20playerGameBasicStats", + "protocol": "https", + "host": [ + "api", + "server", + "nbaapi", + "com" + ], + "path": [ + "api", + "games" + ], + "query": [ + { + "key": "isPlayoff", + "value": "false" + }, + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "5" + }, + { + "key": "sortBy", + "value": "date" + }, + { + "key": "ascending", + "value": "false" + }, + { + "key": "include", + "value": "lineScores%2C%20playerGameBasicStats" + } + ] + }, + "description": "### Game Information with additional details" + }, + "response": [] + }, { "name": "Player Totals Stats", "event": [ @@ -32,10 +1040,6 @@ " pm.expect(responseData.data).to.be.an('array');", " ", " responseData.data.forEach(function(player) {", - " pm.expect(player).to.have.property('ID');", - " pm.expect(player).to.have.property('CreatedAt');", - " pm.expect(player).to.have.property('UpdatedAt');", - " pm.expect(player).to.have.property('DeletedAt');", " pm.expect(player).to.have.property('playerId');", " pm.expect(player).to.have.property('playerName');", " pm.expect(player).to.have.property('position');", @@ -56,100 +1060,128 @@ " pm.expect(responseData.pagination).to.have.property('pages');", " pm.expect(responseData.pagination).to.have.property('total');", "});", + "", + "// Visualization for Player Totals Stats", "var template = `", "", - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " {{#each response.data}}", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " {{/each}}", - "
IDCreatedAtUpdatedAtDeletedAtidplayerIdplayerNamepositionagegamesgamesStartedminutesPgfieldGoalsfieldAttemptsfieldPercentthreeFgthreeAttemptsthreePercenttwoFgtwoAttemptstwoPercenteffectFgPercentftftAttemptsftPercentoffensiveRbdefensiveRbtotalRbassistsstealsblocksturnoverspersonalFoulspointsteamseason
{{ID}}{{CreatedAt}}{{UpdatedAt}}{{DeletedAt}}{{id}}{{playerId}}{{playerName}}{{position}}{{age}}{{games}}{{gamesStarted}}{{minutesPg}}{{fieldGoals}}{{fieldAttempts}}{{fieldPercent}}{{threeFg}}{{threeAttempts}}{{threePercent}}{{twoFg}}{{twoAttempts}}{{twoPercent}}{{effectFgPercent}}{{ft}}{{ftAttempts}}{{ftPercent}}{{offensiveRb}}{{defensiveRb}}{{totalRb}}{{assists}}{{steals}}{{blocks}}{{turnovers}}{{personalFouls}}{{points}}{{team}}{{season}}
", + "
", + "
Player Statistics
", + "
Season {{season}} | Total Players: {{totalPlayers}}
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each players}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/each}}", + " ", + "
PlayerPosGamesPointsAssistsReboundsPPG
{{playerName}}{{position}}{{games}}{{points}}{{assists}}{{totalRb}}{{ppg}}
", + "
", "`;", "", "function constructVisualizerPayload() {", - " return {response: pm.response.json()}", + " var response = pm.response.json();", + " var players = response.data.map(function(player) {", + " return {", + " playerName: player.playerName || 'N/A',", + " position: player.position || 'N/A',", + " games: player.games || 0,", + " points: player.points || 0,", + " assists: player.assists || 0,", + " totalRb: player.totalRb || 0,", + " ppg: player.games > 0 ? (player.points / player.games).toFixed(1) : '0.0'", + " };", + " });", + " ", + " return {", + " players: players,", + " season: response.data.length > 0 ? response.data[0].season : 'N/A',", + " totalPlayers: response.pagination ? response.pagination.total : players.length", + " };", "}", "", "pm.visualizer.set(template, constructVisualizerPayload());" @@ -180,7 +1212,7 @@ } ], "url": { - "raw": "{{base_url}}/api/playertotals?season=2025&team=HOU&page=1&pageSize=35&isPlayoff=False", + "raw": "{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=3&isPlayoff=False", "host": [ "{{base_url}}" ], @@ -191,7 +1223,7 @@ "query": [ { "key": "season", - "value": "2025", + "value": "2026", "description": "(Optional) The season year (e.g., 2025 for the 2024-25 season)." }, { @@ -206,7 +1238,7 @@ }, { "key": "pageSize", - "value": "35", + "value": "3", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { @@ -232,7 +1264,7 @@ } ], "url": { - "raw": "{{base_url}}/api/playertotals?season=2025&team=HOU&page=1&pageSize=35&isPlayoff=False", + "raw": "{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=20&isPlayoff=False", "host": [ "{{base_url}}" ], @@ -243,7 +1275,7 @@ "query": [ { "key": "season", - "value": "2025", + "value": "2026", "description": "(Optional) The season year (e.g., 2025 for the 2024-25 season)." }, { @@ -258,7 +1290,7 @@ }, { "key": "pageSize", - "value": "35", + "value": "20", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { @@ -271,7 +1303,7 @@ }, "status": "OK", "code": 200, - "_postman_previewlanguage": "json", + "_postman_previewlanguage": null, "header": [ { "key": "Alt-Svc", @@ -287,7 +1319,7 @@ }, { "key": "Date", - "value": "Wed, 02 Jul 2025 01:16:40 GMT" + "value": "Tue, 16 Dec 2025 07:22:18 GMT" }, { "key": "Server", @@ -298,15 +1330,497 @@ "value": "Accept-Encoding" }, { - "key": "Transfer-Encoding", - "value": "chunked" + "key": "Content-Length", + "value": "1390" } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"ID\": 1648,\n \"id\": 13,\n \"playerId\": \"greenja05\",\n \"playerName\": \"Jalen Green\",\n \"position\": \"SG\",\n \"age\": 22,\n \"games\": 82,\n \"gamesStarted\": 82,\n \"minutesPg\": 2697,\n \"fieldGoals\": 608,\n \"fieldAttempts\": 1437,\n \"fieldPercent\": 0.423,\n \"threeFg\": 234,\n \"threeAttempts\": 661,\n \"threePercent\": 0.354,\n \"twoFg\": 374,\n \"twoAttempts\": 776,\n \"twoPercent\": 0.482,\n \"effectFgPercent\": 0.505,\n \"ft\": 273,\n \"ftAttempts\": 336,\n \"ftPercent\": 0.813,\n \"offensiveRb\": 45,\n \"defensiveRb\": 332,\n \"totalRb\": 377,\n \"assists\": 282,\n \"steals\": 71,\n \"blocks\": 27,\n \"turnovers\": 203,\n \"personalFouls\": 127,\n \"points\": 1723,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:06:56.81977Z\",\n \"UpdatedAt\": \"2025-06-20T01:06:56.81977Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1664,\n \"id\": 27,\n \"playerId\": \"sengual01\",\n \"playerName\": \"Alperen Şengün\",\n \"position\": \"C\",\n \"age\": 22,\n \"games\": 76,\n \"gamesStarted\": 76,\n \"minutesPg\": 2395,\n \"fieldGoals\": 567,\n \"fieldAttempts\": 1143,\n \"fieldPercent\": 0.496,\n \"threeFg\": 21,\n \"threeAttempts\": 90,\n \"threePercent\": 0.233,\n \"twoFg\": 546,\n \"twoAttempts\": 1053,\n \"twoPercent\": 0.519,\n \"effectFgPercent\": 0.505,\n \"ft\": 296,\n \"ftAttempts\": 428,\n \"ftPercent\": 0.692,\n \"offensiveRb\": 262,\n \"defensiveRb\": 524,\n \"totalRb\": 786,\n \"assists\": 372,\n \"steals\": 84,\n \"blocks\": 61,\n \"turnovers\": 194,\n \"personalFouls\": 209,\n \"points\": 1451,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:06:59.072751Z\",\n \"UpdatedAt\": \"2025-06-20T01:06:59.072751Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1725,\n \"id\": 78,\n \"playerId\": \"brookdi01\",\n \"playerName\": \"Dillon Brooks\",\n \"position\": \"SF\",\n \"age\": 29,\n \"games\": 75,\n \"gamesStarted\": 75,\n \"minutesPg\": 2388,\n \"fieldGoals\": 384,\n \"fieldAttempts\": 895,\n \"fieldPercent\": 0.429,\n \"threeFg\": 186,\n \"threeAttempts\": 469,\n \"threePercent\": 0.397,\n \"twoFg\": 198,\n \"twoAttempts\": 426,\n \"twoPercent\": 0.465,\n \"effectFgPercent\": 0.533,\n \"ft\": 99,\n \"ftAttempts\": 121,\n \"ftPercent\": 0.818,\n \"offensiveRb\": 75,\n \"defensiveRb\": 200,\n \"totalRb\": 275,\n \"assists\": 128,\n \"steals\": 60,\n \"blocks\": 16,\n \"turnovers\": 76,\n \"personalFouls\": 242,\n \"points\": 1053,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:08.04821Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:08.04821Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1741,\n \"id\": 91,\n \"playerId\": \"thompam01\",\n \"playerName\": \"Amen Thompson\",\n \"position\": \"SF\",\n \"age\": 22,\n \"games\": 69,\n \"gamesStarted\": 42,\n \"minutesPg\": 2225,\n \"fieldGoals\": 388,\n \"fieldAttempts\": 697,\n \"fieldPercent\": 0.557,\n \"threeFg\": 25,\n \"threeAttempts\": 91,\n \"threePercent\": 0.275,\n \"twoFg\": 363,\n \"twoAttempts\": 606,\n \"twoPercent\": 0.599,\n \"effectFgPercent\": 0.575,\n \"ft\": 169,\n \"ftAttempts\": 247,\n \"ftPercent\": 0.684,\n \"offensiveRb\": 192,\n \"defensiveRb\": 372,\n \"totalRb\": 564,\n \"assists\": 265,\n \"steals\": 97,\n \"blocks\": 89,\n \"turnovers\": 138,\n \"personalFouls\": 167,\n \"points\": 970,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:10.362164Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:10.362164Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1763,\n \"id\": 109,\n \"playerId\": \"vanvlfr01\",\n \"playerName\": \"Fred VanVleet\",\n \"position\": \"PG\",\n \"age\": 30,\n \"games\": 60,\n \"gamesStarted\": 60,\n \"minutesPg\": 2111,\n \"fieldGoals\": 287,\n \"fieldAttempts\": 759,\n \"fieldPercent\": 0.378,\n \"threeFg\": 159,\n \"threeAttempts\": 461,\n \"threePercent\": 0.345,\n \"twoFg\": 128,\n \"twoAttempts\": 298,\n \"twoPercent\": 0.43,\n \"effectFgPercent\": 0.483,\n \"ft\": 111,\n \"ftAttempts\": 137,\n \"ftPercent\": 0.81,\n \"offensiveRb\": 32,\n \"defensiveRb\": 189,\n \"totalRb\": 221,\n \"assists\": 333,\n \"steals\": 94,\n \"blocks\": 25,\n \"turnovers\": 87,\n \"personalFouls\": 140,\n \"points\": 844,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:13.597703Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:13.597703Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1821,\n \"id\": 155,\n \"playerId\": \"smithja05\",\n \"playerName\": \"Jabari Smith Jr.\",\n \"position\": \"PF\",\n \"age\": 21,\n \"games\": 57,\n \"gamesStarted\": 39,\n \"minutesPg\": 1716,\n \"fieldGoals\": 248,\n \"fieldAttempts\": 566,\n \"fieldPercent\": 0.438,\n \"threeFg\": 98,\n \"threeAttempts\": 277,\n \"threePercent\": 0.354,\n \"twoFg\": 150,\n \"twoAttempts\": 289,\n \"twoPercent\": 0.519,\n \"effectFgPercent\": 0.525,\n \"ft\": 104,\n \"ftAttempts\": 126,\n \"ftPercent\": 0.825,\n \"offensiveRb\": 105,\n \"defensiveRb\": 294,\n \"totalRb\": 399,\n \"assists\": 60,\n \"steals\": 25,\n \"blocks\": 41,\n \"turnovers\": 61,\n \"personalFouls\": 123,\n \"points\": 698,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:21.954232Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:21.954232Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1825,\n \"id\": 159,\n \"playerId\": \"easonta01\",\n \"playerName\": \"Tari Eason\",\n \"position\": \"PF\",\n \"age\": 23,\n \"games\": 57,\n \"gamesStarted\": 16,\n \"minutesPg\": 1420,\n \"fieldGoals\": 272,\n \"fieldAttempts\": 559,\n \"fieldPercent\": 0.487,\n \"threeFg\": 63,\n \"threeAttempts\": 184,\n \"threePercent\": 0.342,\n \"twoFg\": 209,\n \"twoAttempts\": 375,\n \"twoPercent\": 0.557,\n \"effectFgPercent\": 0.543,\n \"ft\": 79,\n \"ftAttempts\": 104,\n \"ftPercent\": 0.76,\n \"offensiveRb\": 128,\n \"defensiveRb\": 234,\n \"totalRb\": 362,\n \"assists\": 83,\n \"steals\": 97,\n \"blocks\": 50,\n \"turnovers\": 65,\n \"personalFouls\": 136,\n \"points\": 686,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:22.520553Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:22.520553Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1919,\n \"id\": 239,\n \"playerId\": \"whitmca01\",\n \"playerName\": \"Cam Whitmore\",\n \"position\": \"SF\",\n \"age\": 20,\n \"games\": 51,\n \"gamesStarted\": 3,\n \"minutesPg\": 827,\n \"fieldGoals\": 179,\n \"fieldAttempts\": 403,\n \"fieldPercent\": 0.444,\n \"threeFg\": 65,\n \"threeAttempts\": 183,\n \"threePercent\": 0.355,\n \"twoFg\": 114,\n \"twoAttempts\": 220,\n \"twoPercent\": 0.518,\n \"effectFgPercent\": 0.525,\n \"ft\": 54,\n \"ftAttempts\": 72,\n \"ftPercent\": 0.75,\n \"offensiveRb\": 36,\n \"defensiveRb\": 115,\n \"totalRb\": 151,\n \"assists\": 49,\n \"steals\": 31,\n \"blocks\": 13,\n \"turnovers\": 46,\n \"personalFouls\": 44,\n \"points\": 477,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:36.322627Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:36.322627Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1992,\n \"id\": 292,\n \"playerId\": \"holidaa01\",\n \"playerName\": \"Aaron Holiday\",\n \"position\": \"PG\",\n \"age\": 28,\n \"games\": 62,\n \"gamesStarted\": 3,\n \"minutesPg\": 792,\n \"fieldGoals\": 117,\n \"fieldAttempts\": 268,\n \"fieldPercent\": 0.437,\n \"threeFg\": 72,\n \"threeAttempts\": 181,\n \"threePercent\": 0.398,\n \"twoFg\": 45,\n \"twoAttempts\": 87,\n \"twoPercent\": 0.517,\n \"effectFgPercent\": 0.571,\n \"ft\": 34,\n \"ftAttempts\": 41,\n \"ftPercent\": 0.829,\n \"offensiveRb\": 13,\n \"defensiveRb\": 65,\n \"totalRb\": 78,\n \"assists\": 83,\n \"steals\": 19,\n \"blocks\": 11,\n \"turnovers\": 37,\n \"personalFouls\": 64,\n \"points\": 340,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:46.800477Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:46.800477Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2066,\n \"id\": 344,\n \"playerId\": \"sheppre01\",\n \"playerName\": \"Reed Sheppard\",\n \"position\": \"PG\",\n \"age\": 20,\n \"games\": 52,\n \"gamesStarted\": 3,\n \"minutesPg\": 654,\n \"fieldGoals\": 84,\n \"fieldAttempts\": 239,\n \"fieldPercent\": 0.351,\n \"threeFg\": 48,\n \"threeAttempts\": 142,\n \"threePercent\": 0.338,\n \"twoFg\": 36,\n \"twoAttempts\": 97,\n \"twoPercent\": 0.371,\n \"effectFgPercent\": 0.452,\n \"ft\": 13,\n \"ftAttempts\": 16,\n \"ftPercent\": 0.813,\n \"offensiveRb\": 16,\n \"defensiveRb\": 62,\n \"totalRb\": 78,\n \"assists\": 75,\n \"steals\": 35,\n \"blocks\": 17,\n \"turnovers\": 37,\n \"personalFouls\": 53,\n \"points\": 229,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:57.495833Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:57.495833Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2068,\n \"id\": 346,\n \"playerId\": \"adamsst01\",\n \"playerName\": \"Steven Adams\",\n \"position\": \"C\",\n \"age\": 31,\n \"games\": 58,\n \"gamesStarted\": 3,\n \"minutesPg\": 794,\n \"fieldGoals\": 91,\n \"fieldAttempts\": 167,\n \"fieldPercent\": 0.545,\n \"threeFg\": 0,\n \"threeAttempts\": 2,\n \"threePercent\": 0,\n \"twoFg\": 91,\n \"twoAttempts\": 165,\n \"twoPercent\": 0.552,\n \"effectFgPercent\": 0.545,\n \"ft\": 43,\n \"ftAttempts\": 93,\n \"ftPercent\": 0.462,\n \"offensiveRb\": 166,\n \"defensiveRb\": 161,\n \"totalRb\": 327,\n \"assists\": 66,\n \"steals\": 22,\n \"blocks\": 28,\n \"turnovers\": 54,\n \"personalFouls\": 60,\n \"points\": 225,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:57.793469Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:57.793469Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2080,\n \"id\": 356,\n \"playerId\": \"landajo01\",\n \"playerName\": \"Jock Landale\",\n \"position\": \"C\",\n \"age\": 29,\n \"games\": 42,\n \"gamesStarted\": 3,\n \"minutesPg\": 500,\n \"fieldGoals\": 81,\n \"fieldAttempts\": 152,\n \"fieldPercent\": 0.533,\n \"threeFg\": 11,\n \"threeAttempts\": 26,\n \"threePercent\": 0.423,\n \"twoFg\": 70,\n \"twoAttempts\": 126,\n \"twoPercent\": 0.556,\n \"effectFgPercent\": 0.569,\n \"ft\": 27,\n \"ftAttempts\": 40,\n \"ftPercent\": 0.675,\n \"offensiveRb\": 56,\n \"defensiveRb\": 81,\n \"totalRb\": 137,\n \"assists\": 37,\n \"steals\": 13,\n \"blocks\": 10,\n \"turnovers\": 21,\n \"personalFouls\": 49,\n \"points\": 200,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:07:59.521078Z\",\n \"UpdatedAt\": \"2025-06-20T01:07:59.521078Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2090,\n \"id\": 364,\n \"playerId\": \"tateja01\",\n \"playerName\": \"Jae'Sean Tate\",\n \"position\": \"SF\",\n \"age\": 29,\n \"games\": 52,\n \"gamesStarted\": 2,\n \"minutesPg\": 588,\n \"fieldGoals\": 70,\n \"fieldAttempts\": 148,\n \"fieldPercent\": 0.473,\n \"threeFg\": 16,\n \"threeAttempts\": 46,\n \"threePercent\": 0.348,\n \"twoFg\": 54,\n \"twoAttempts\": 102,\n \"twoPercent\": 0.529,\n \"effectFgPercent\": 0.527,\n \"ft\": 32,\n \"ftAttempts\": 47,\n \"ftPercent\": 0.681,\n \"offensiveRb\": 50,\n \"defensiveRb\": 67,\n \"totalRb\": 117,\n \"assists\": 47,\n \"steals\": 26,\n \"blocks\": 7,\n \"turnovers\": 22,\n \"personalFouls\": 82,\n \"points\": 188,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:08:00.954562Z\",\n \"UpdatedAt\": \"2025-06-20T01:08:00.954562Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2097,\n \"id\": 371,\n \"playerId\": \"greenje02\",\n \"playerName\": \"Jeff Green\",\n \"position\": \"PF\",\n \"age\": 38,\n \"games\": 32,\n \"gamesStarted\": 3,\n \"minutesPg\": 396,\n \"fieldGoals\": 61,\n \"fieldAttempts\": 121,\n \"fieldPercent\": 0.504,\n \"threeFg\": 29,\n \"threeAttempts\": 79,\n \"threePercent\": 0.367,\n \"twoFg\": 32,\n \"twoAttempts\": 42,\n \"twoPercent\": 0.762,\n \"effectFgPercent\": 0.624,\n \"ft\": 21,\n \"ftAttempts\": 26,\n \"ftPercent\": 0.808,\n \"offensiveRb\": 11,\n \"defensiveRb\": 47,\n \"totalRb\": 58,\n \"assists\": 20,\n \"steals\": 6,\n \"blocks\": 4,\n \"turnovers\": 9,\n \"personalFouls\": 32,\n \"points\": 172,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:08:02.008397Z\",\n \"UpdatedAt\": \"2025-06-20T01:08:02.008397Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2242,\n \"id\": 461,\n \"playerId\": \"willije02\",\n \"playerName\": \"Jeenathan Williams\",\n \"position\": \"SG\",\n \"age\": 25,\n \"games\": 20,\n \"gamesStarted\": 0,\n \"minutesPg\": 147,\n \"fieldGoals\": 27,\n \"fieldAttempts\": 62,\n \"fieldPercent\": 0.435,\n \"threeFg\": 6,\n \"threeAttempts\": 26,\n \"threePercent\": 0.231,\n \"twoFg\": 21,\n \"twoAttempts\": 36,\n \"twoPercent\": 0.583,\n \"effectFgPercent\": 0.484,\n \"ft\": 5,\n \"ftAttempts\": 8,\n \"ftPercent\": 0.625,\n \"offensiveRb\": 5,\n \"defensiveRb\": 8,\n \"totalRb\": 13,\n \"assists\": 9,\n \"steals\": 8,\n \"blocks\": 4,\n \"turnovers\": 14,\n \"personalFouls\": 16,\n \"points\": 65,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:08:23.073002Z\",\n \"UpdatedAt\": \"2025-06-20T01:08:23.073002Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2303,\n \"id\": 508,\n \"playerId\": \"nfalyda01\",\n \"playerName\": \"N'Faly Dante\",\n \"position\": \"C\",\n \"age\": 23,\n \"games\": 4,\n \"gamesStarted\": 0,\n \"minutesPg\": 51,\n \"fieldGoals\": 10,\n \"fieldAttempts\": 13,\n \"fieldPercent\": 0.769,\n \"threeFg\": 0,\n \"threeAttempts\": 0,\n \"threePercent\": 0,\n \"twoFg\": 10,\n \"twoAttempts\": 13,\n \"twoPercent\": 0.769,\n \"effectFgPercent\": 0.769,\n \"ft\": 4,\n \"ftAttempts\": 5,\n \"ftPercent\": 0.8,\n \"offensiveRb\": 6,\n \"defensiveRb\": 15,\n \"totalRb\": 21,\n \"assists\": 2,\n \"steals\": 1,\n \"blocks\": 5,\n \"turnovers\": 2,\n \"personalFouls\": 9,\n \"points\": 24,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:08:31.603297Z\",\n \"UpdatedAt\": \"2025-06-20T01:08:31.603297Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2322,\n \"id\": 525,\n \"playerId\": \"mcveija01\",\n \"playerName\": \"Jack McVeigh\",\n \"position\": \"PF\",\n \"age\": 28,\n \"games\": 9,\n \"gamesStarted\": 0,\n \"minutesPg\": 43,\n \"fieldGoals\": 5,\n \"fieldAttempts\": 17,\n \"fieldPercent\": 0.294,\n \"threeFg\": 4,\n \"threeAttempts\": 13,\n \"threePercent\": 0.308,\n \"twoFg\": 1,\n \"twoAttempts\": 4,\n \"twoPercent\": 0.25,\n \"effectFgPercent\": 0.412,\n \"ft\": 0,\n \"ftAttempts\": 0,\n \"ftPercent\": 0,\n \"offensiveRb\": 2,\n \"defensiveRb\": 3,\n \"totalRb\": 5,\n \"assists\": 1,\n \"steals\": 0,\n \"blocks\": 2,\n \"turnovers\": 2,\n \"personalFouls\": 3,\n \"points\": 14,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:08:34.253789Z\",\n \"UpdatedAt\": \"2025-06-20T01:08:34.253789Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2116,\n \"id\": 385,\n \"playerId\": \"roddyda01\",\n \"playerName\": \"David Roddy\",\n \"position\": \"PF\",\n \"age\": 23,\n \"games\": 3,\n \"gamesStarted\": 0,\n \"minutesPg\": 35,\n \"fieldGoals\": 5,\n \"fieldAttempts\": 13,\n \"fieldPercent\": 0.385,\n \"threeFg\": 1,\n \"threeAttempts\": 7,\n \"threePercent\": 0.143,\n \"twoFg\": 4,\n \"twoAttempts\": 6,\n \"twoPercent\": 0.667,\n \"effectFgPercent\": 0.423,\n \"ft\": 2,\n \"ftAttempts\": 4,\n \"ftPercent\": 0.5,\n \"offensiveRb\": 0,\n \"defensiveRb\": 5,\n \"totalRb\": 5,\n \"assists\": 2,\n \"steals\": 0,\n \"blocks\": 1,\n \"turnovers\": 1,\n \"personalFouls\": 1,\n \"points\": 13,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:08:04.73934Z\",\n \"UpdatedAt\": \"2025-06-20T01:08:04.73934Z\",\n \"DeletedAt\": null\n }\n ],\n \"pagination\": {\n \"page\": 1,\n \"pageSize\": 35,\n \"pages\": 1,\n \"total\": 18\n }\n}" + "body": "{\n \"data\": [\n {\n \"playerId\": \"duranke01\",\n \"playerName\": \"Kevin Durant\",\n \"position\": \"SF\",\n \"age\": 37,\n \"games\": 20,\n \"gamesStarted\": 20,\n \"minutesPg\": 707,\n \"fieldGoals\": 172,\n \"fieldAttempts\": 345,\n \"fieldPercent\": 0.499,\n \"threeFg\": 36,\n \"threeAttempts\": 91,\n \"threePercent\": 0.396,\n \"twoFg\": 136,\n \"twoAttempts\": 254,\n \"twoPercent\": 0.535,\n \"effectFgPercent\": 0.551,\n \"ft\": 116,\n \"ftAttempts\": 130,\n \"ftPercent\": 0.892,\n \"offensiveRb\": 6,\n \"defensiveRb\": 86,\n \"totalRb\": 92,\n \"assists\": 77,\n \"steals\": 19,\n \"blocks\": 12,\n \"turnovers\": 59,\n \"personalFouls\": 48,\n \"points\": 496,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"sengual01\",\n \"playerName\": \"Alperen Şengün\",\n \"position\": \"C\",\n \"age\": 23,\n \"games\": 20,\n \"gamesStarted\": 20,\n \"minutesPg\": 718,\n \"fieldGoals\": 170,\n \"fieldAttempts\": 341,\n \"fieldPercent\": 0.499,\n \"threeFg\": 20,\n \"threeAttempts\": 55,\n \"threePercent\": 0.364,\n \"twoFg\": 150,\n \"twoAttempts\": 286,\n \"twoPercent\": 0.524,\n \"effectFgPercent\": 0.528,\n \"ft\": 100,\n \"ftAttempts\": 136,\n \"ftPercent\": 0.735,\n \"offensiveRb\": 60,\n \"defensiveRb\": 128,\n \"totalRb\": 188,\n \"assists\": 140,\n \"steals\": 29,\n \"blocks\": 19,\n \"turnovers\": 67,\n \"personalFouls\": 69,\n \"points\": 460,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"thompam01\",\n \"playerName\": \"Amen Thompson\",\n \"position\": \"PG\",\n \"age\": 23,\n \"games\": 22,\n \"gamesStarted\": 22,\n \"minutesPg\": 796,\n \"fieldGoals\": 150,\n \"fieldAttempts\": 310,\n \"fieldPercent\": 0.484,\n \"threeFg\": 9,\n \"threeAttempts\": 47,\n \"threePercent\": 0.191,\n \"twoFg\": 141,\n \"twoAttempts\": 263,\n \"twoPercent\": 0.536,\n \"effectFgPercent\": 0.498,\n \"ft\": 76,\n \"ftAttempts\": 94,\n \"ftPercent\": 0.809,\n \"offensiveRb\": 58,\n \"defensiveRb\": 99,\n \"totalRb\": 157,\n \"assists\": 115,\n \"steals\": 30,\n \"blocks\": 11,\n \"turnovers\": 57,\n \"personalFouls\": 56,\n \"points\": 385,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"smithja05\",\n \"playerName\": \"Jabari Smith Jr.\",\n \"position\": \"PF\",\n \"age\": 22,\n \"games\": 21,\n \"gamesStarted\": 21,\n \"minutesPg\": 704,\n \"fieldGoals\": 115,\n \"fieldAttempts\": 253,\n \"fieldPercent\": 0.455,\n \"threeFg\": 42,\n \"threeAttempts\": 118,\n \"threePercent\": 0.356,\n \"twoFg\": 73,\n \"twoAttempts\": 135,\n \"twoPercent\": 0.541,\n \"effectFgPercent\": 0.538,\n \"ft\": 51,\n \"ftAttempts\": 64,\n \"ftPercent\": 0.797,\n \"offensiveRb\": 30,\n \"defensiveRb\": 108,\n \"totalRb\": 138,\n \"assists\": 41,\n \"steals\": 16,\n \"blocks\": 16,\n \"turnovers\": 28,\n \"personalFouls\": 64,\n \"points\": 323,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"sheppre01\",\n \"playerName\": \"Reed Sheppard\",\n \"position\": \"SG\",\n \"age\": 21,\n \"games\": 22,\n \"gamesStarted\": 4,\n \"minutesPg\": 548,\n \"fieldGoals\": 106,\n \"fieldAttempts\": 223,\n \"fieldPercent\": 0.475,\n \"threeFg\": 56,\n \"threeAttempts\": 126,\n \"threePercent\": 0.444,\n \"twoFg\": 50,\n \"twoAttempts\": 97,\n \"twoPercent\": 0.515,\n \"effectFgPercent\": 0.601,\n \"ft\": 15,\n \"ftAttempts\": 21,\n \"ftPercent\": 0.714,\n \"offensiveRb\": 8,\n \"defensiveRb\": 61,\n \"totalRb\": 69,\n \"assists\": 71,\n \"steals\": 34,\n \"blocks\": 12,\n \"turnovers\": 29,\n \"personalFouls\": 45,\n \"points\": 283,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"holidaa01\",\n \"playerName\": \"Aaron Holiday\",\n \"position\": \"PG\",\n \"age\": 29,\n \"games\": 17,\n \"gamesStarted\": 0,\n \"minutesPg\": 291,\n \"fieldGoals\": 50,\n \"fieldAttempts\": 110,\n \"fieldPercent\": 0.455,\n \"threeFg\": 33,\n \"threeAttempts\": 74,\n \"threePercent\": 0.446,\n \"twoFg\": 17,\n \"twoAttempts\": 36,\n \"twoPercent\": 0.472,\n \"effectFgPercent\": 0.605,\n \"ft\": 25,\n \"ftAttempts\": 29,\n \"ftPercent\": 0.862,\n \"offensiveRb\": 2,\n \"defensiveRb\": 15,\n \"totalRb\": 17,\n \"assists\": 19,\n \"steals\": 8,\n \"blocks\": 3,\n \"turnovers\": 16,\n \"personalFouls\": 23,\n \"points\": 158,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"okogijo01\",\n \"playerName\": \"Josh Okogie\",\n \"position\": \"SG\",\n \"age\": 27,\n \"games\": 22,\n \"gamesStarted\": 16,\n \"minutesPg\": 460,\n \"fieldGoals\": 49,\n \"fieldAttempts\": 109,\n \"fieldPercent\": 0.45,\n \"threeFg\": 23,\n \"threeAttempts\": 58,\n \"threePercent\": 0.397,\n \"twoFg\": 26,\n \"twoAttempts\": 51,\n \"twoPercent\": 0.51,\n \"effectFgPercent\": 0.555,\n \"ft\": 24,\n \"ftAttempts\": 33,\n \"ftPercent\": 0.727,\n \"offensiveRb\": 30,\n \"defensiveRb\": 34,\n \"totalRb\": 64,\n \"assists\": 22,\n \"steals\": 30,\n \"blocks\": 5,\n \"turnovers\": 18,\n \"personalFouls\": 41,\n \"points\": 145,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"easonta01\",\n \"playerName\": \"Tari Eason\",\n \"position\": \"PF\",\n \"age\": 24,\n \"games\": 11,\n \"gamesStarted\": 1,\n \"minutesPg\": 255,\n \"fieldGoals\": 47,\n \"fieldAttempts\": 95,\n \"fieldPercent\": 0.495,\n \"threeFg\": 27,\n \"threeAttempts\": 53,\n \"threePercent\": 0.509,\n \"twoFg\": 20,\n \"twoAttempts\": 42,\n \"twoPercent\": 0.476,\n \"effectFgPercent\": 0.637,\n \"ft\": 5,\n \"ftAttempts\": 7,\n \"ftPercent\": 0.714,\n \"offensiveRb\": 16,\n \"defensiveRb\": 41,\n \"totalRb\": 57,\n \"assists\": 18,\n \"steals\": 9,\n \"blocks\": 5,\n \"turnovers\": 19,\n \"personalFouls\": 18,\n \"points\": 126,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"adamsst01\",\n \"playerName\": \"Steven Adams\",\n \"position\": \"C\",\n \"age\": 32,\n \"games\": 18,\n \"gamesStarted\": 5,\n \"minutesPg\": 389,\n \"fieldGoals\": 42,\n \"fieldAttempts\": 79,\n \"fieldPercent\": 0.532,\n \"threeFg\": 0,\n \"threeAttempts\": 0,\n \"threePercent\": 0,\n \"twoFg\": 42,\n \"twoAttempts\": 79,\n \"twoPercent\": 0.532,\n \"effectFgPercent\": 0.532,\n \"ft\": 32,\n \"ftAttempts\": 42,\n \"ftPercent\": 0.762,\n \"offensiveRb\": 85,\n \"defensiveRb\": 78,\n \"totalRb\": 163,\n \"assists\": 28,\n \"steals\": 14,\n \"blocks\": 13,\n \"turnovers\": 20,\n \"personalFouls\": 34,\n \"points\": 116,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"capelca01\",\n \"playerName\": \"Clint Capela\",\n \"position\": \"C\",\n \"age\": 31,\n \"games\": 21,\n \"gamesStarted\": 1,\n \"minutesPg\": 245,\n \"fieldGoals\": 35,\n \"fieldAttempts\": 62,\n \"fieldPercent\": 0.565,\n \"threeFg\": 0,\n \"threeAttempts\": 0,\n \"threePercent\": 0,\n \"twoFg\": 35,\n \"twoAttempts\": 62,\n \"twoPercent\": 0.565,\n \"effectFgPercent\": 0.565,\n \"ft\": 10,\n \"ftAttempts\": 15,\n \"ftPercent\": 0.667,\n \"offensiveRb\": 55,\n \"defensiveRb\": 45,\n \"totalRb\": 100,\n \"assists\": 9,\n \"steals\": 9,\n \"blocks\": 16,\n \"turnovers\": 10,\n \"personalFouls\": 21,\n \"points\": 80,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"tateja01\",\n \"playerName\": \"Jae'Sean Tate\",\n \"position\": \"SF\",\n \"age\": 30,\n \"games\": 14,\n \"gamesStarted\": 0,\n \"minutesPg\": 116,\n \"fieldGoals\": 17,\n \"fieldAttempts\": 32,\n \"fieldPercent\": 0.531,\n \"threeFg\": 5,\n \"threeAttempts\": 12,\n \"threePercent\": 0.417,\n \"twoFg\": 12,\n \"twoAttempts\": 20,\n \"twoPercent\": 0.6,\n \"effectFgPercent\": 0.609,\n \"ft\": 2,\n \"ftAttempts\": 2,\n \"ftPercent\": 1,\n \"offensiveRb\": 8,\n \"defensiveRb\": 14,\n \"totalRb\": 22,\n \"assists\": 7,\n \"steals\": 4,\n \"blocks\": 0,\n \"turnovers\": 4,\n \"personalFouls\": 20,\n \"points\": 41,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"greenje02\",\n \"playerName\": \"Jeff Green\",\n \"position\": \"PF\",\n \"age\": 39,\n \"games\": 10,\n \"gamesStarted\": 0,\n \"minutesPg\": 48,\n \"fieldGoals\": 8,\n \"fieldAttempts\": 16,\n \"fieldPercent\": 0.5,\n \"threeFg\": 5,\n \"threeAttempts\": 12,\n \"threePercent\": 0.417,\n \"twoFg\": 3,\n \"twoAttempts\": 4,\n \"twoPercent\": 0.75,\n \"effectFgPercent\": 0.656,\n \"ft\": 0,\n \"ftAttempts\": 0,\n \"ftPercent\": 0,\n \"offensiveRb\": 1,\n \"defensiveRb\": 3,\n \"totalRb\": 4,\n \"assists\": 1,\n \"steals\": 0,\n \"blocks\": 1,\n \"turnovers\": 0,\n \"personalFouls\": 4,\n \"points\": 21,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"davisjd01\",\n \"playerName\": \"JD Davison\",\n \"position\": \"PG\",\n \"age\": 23,\n \"games\": 11,\n \"gamesStarted\": 0,\n \"minutesPg\": 74,\n \"fieldGoals\": 8,\n \"fieldAttempts\": 17,\n \"fieldPercent\": 0.471,\n \"threeFg\": 4,\n \"threeAttempts\": 9,\n \"threePercent\": 0.444,\n \"twoFg\": 4,\n \"twoAttempts\": 8,\n \"twoPercent\": 0.5,\n \"effectFgPercent\": 0.588,\n \"ft\": 0,\n \"ftAttempts\": 2,\n \"ftPercent\": 0,\n \"offensiveRb\": 1,\n \"defensiveRb\": 3,\n \"totalRb\": 4,\n \"assists\": 10,\n \"steals\": 3,\n \"blocks\": 1,\n \"turnovers\": 1,\n \"personalFouls\": 4,\n \"points\": 20,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"crawfis01\",\n \"playerName\": \"Isaiah Crawford\",\n \"position\": \"SF\",\n \"age\": 24,\n \"games\": 2,\n \"gamesStarted\": 0,\n \"minutesPg\": 5,\n \"fieldGoals\": 0,\n \"fieldAttempts\": 1,\n \"fieldPercent\": 0,\n \"threeFg\": 0,\n \"threeAttempts\": 1,\n \"threePercent\": 0,\n \"twoFg\": 0,\n \"twoAttempts\": 0,\n \"twoPercent\": 0,\n \"effectFgPercent\": 0,\n \"ft\": 0,\n \"ftAttempts\": 0,\n \"ftPercent\": 0,\n \"offensiveRb\": 0,\n \"defensiveRb\": 0,\n \"totalRb\": 0,\n \"assists\": 0,\n \"steals\": 0,\n \"blocks\": 0,\n \"turnovers\": 0,\n \"personalFouls\": 0,\n \"points\": 0,\n \"team\": \"HOU\",\n \"season\": 2026,\n \"isPlayoff\": false\n }\n ],\n \"pagination\": {\n \"total\": 14,\n \"page\": 1,\n \"pageSize\": 20,\n \"pages\": 1\n }\n}" } ] }, + { + "name": "Player Totals Stats", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "pm.test(\"Response time is less than 200ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(200);", + "});", + "", + "", + "pm.test(\"Response has the required fields\", function () {", + " const responseData = pm.response.json();", + " ", + " pm.expect(responseData).to.be.an('object');", + " pm.expect(responseData.data).to.be.an('array');", + " ", + " responseData.data.forEach(function(player) {", + " pm.expect(player).to.have.property('playerId');", + " pm.expect(player).to.have.property('minutesPg');", + " pm.expect(player).to.have.property('fieldGoals');", + " pm.expect(player).to.have.property('threeAttempts');", + " pm.expect(player).to.have.property('team');", + " pm.expect(player).to.have.property('playerName');", + " pm.expect(player).to.have.property('position');", + " pm.expect(player).to.have.property('season');", + " pm.expect(player).to.have.property('games');", + " });", + "});", + "", + "", + "", + "pm.test(\"Pagination object is present and contains expected fields\", function () {", + " const responseData = pm.response.json();", + " ", + " pm.expect(responseData).to.be.an('object');", + " pm.expect(responseData.pagination).to.exist;", + " pm.expect(responseData.pagination).to.have.property('page');", + " pm.expect(responseData.pagination).to.have.property('pageSize');", + " pm.expect(responseData.pagination).to.have.property('pages');", + " pm.expect(responseData.pagination).to.have.property('total');", + "});", + "", + "// Visualization for Player Totals Stats", + "var template = `", + "", + "
", + "
Player Statistics
", + "
Season {{season}} | Total Players: {{totalPlayers}}
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each players}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/each}}", + " ", + "
PlayerPosGamesPointsAssistsReboundsPPG
{{playerName}}{{position}}{{games}}{{points}}{{assists}}{{totalRb}}{{ppg}}
", + "
", + "`;", + "", + "function constructVisualizerPayload() {", + " var response = pm.response.json();", + " var players = response.data.map(function(player) {", + " return {", + " playerName: player.playerName || 'N/A',", + " position: player.position || 'N/A',", + " games: player.games || 0,", + " points: player.points || 0,", + " assists: player.assists || 0,", + " totalRb: player.totalRb || 0,", + " ppg: player.games > 0 ? (player.points / player.games).toFixed(1) : '0.0'", + " };", + " });", + " ", + " return {", + " players: players,", + " season: response.data.length > 0 ? response.data[0].season : 'N/A',", + " totalPlayers: response.pagination ? response.pagination.total : players.length", + " };", + "}", + "", + "pm.visualizer.set(template, constructVisualizerPayload());" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "x-api-key", + "value": "{{api-key}}", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=20&isPlayoff=False", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "playertotals" + ], + "query": [ + { + "key": "season", + "value": "2026", + "description": "(Optional) The season year (e.g., 2025 for the 2024-25 season)." + }, + { + "key": "team", + "value": "HOU", + "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL)." + }, + { + "key": "page", + "value": "1", + "description": "(Optional) The page number for pagination. Defaults to 1." + }, + { + "key": "pageSize", + "value": "20", + "description": "(Optional) The number of results to return per page. Defaults to 20." + }, + { + "key": "isPlayoff", + "value": "False", + "description": "(Optional) Set to 'true' to retrieve playoff stats, or 'false' for regular season stats." + } + ] + }, + "description": "### Player Totals Houston Rockets" + }, + "response": [] + }, + { + "name": "Player Totals Stats", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "pm.test(\"Response time is less than 200ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(200);", + "});", + "", + "", + "pm.test(\"Response has the required fields\", function () {", + " const responseData = pm.response.json();", + " ", + " pm.expect(responseData).to.be.an('object');", + " pm.expect(responseData.data).to.be.an('array');", + " ", + " responseData.data.forEach(function(player) {", + " pm.expect(player).to.have.property('playerId');", + " pm.expect(player).to.have.property('playerName');", + " pm.expect(player).to.have.property('position');", + " pm.expect(player).to.have.property('age');", + " pm.expect(player).to.have.property('games');", + " });", + "});", + "", + "", + "", + "pm.test(\"Pagination object is present and contains expected fields\", function () {", + " const responseData = pm.response.json();", + " ", + " pm.expect(responseData).to.be.an('object');", + " pm.expect(responseData.pagination).to.exist;", + " pm.expect(responseData.pagination).to.have.property('page');", + " pm.expect(responseData.pagination).to.have.property('pageSize');", + " pm.expect(responseData.pagination).to.have.property('pages');", + " pm.expect(responseData.pagination).to.have.property('total');", + "});", + "", + "// Visualization for Player Totals Stats", + "var template = `", + "", + "
", + "
Player Statistics
", + "
Season {{season}} | Total Players: {{totalPlayers}}
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each players}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/each}}", + " ", + "
PlayerPosGamesPointsAssistsReboundsPPG
{{playerName}}{{position}}{{games}}{{points}}{{assists}}{{totalRb}}{{ppg}}
", + "
", + "`;", + "", + "function constructVisualizerPayload() {", + " var response = pm.response.json();", + " var players = response.data.map(function(player) {", + " return {", + " playerName: player.playerName || 'N/A',", + " position: player.position || 'N/A',", + " games: player.games || 0,", + " points: player.points || 0,", + " assists: player.assists || 0,", + " totalRb: player.totalRb || 0,", + " ppg: player.games > 0 ? (player.points / player.games).toFixed(1) : '0.0'", + " };", + " });", + " ", + " return {", + " players: players,", + " season: response.data.length > 0 ? response.data[0].season : 'N/A',", + " totalPlayers: response.pagination ? response.pagination.total : players.length", + " };", + "}", + "", + "pm.visualizer.set(template, constructVisualizerPayload());" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "x-api-key", + "value": "{{api-key}}", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "{{base_url}}/api/playertotals?season=2026&team=OKC&page=1&pageSize=12&isPlayoff=False", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "playertotals" + ], + "query": [ + { + "key": "season", + "value": "2026", + "description": "(Optional) The season year (e.g., 2025 for the 2024-25 season)." + }, + { + "key": "team", + "value": "OKC", + "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL)." + }, + { + "key": "page", + "value": "1", + "description": "(Optional) The page number for pagination. Defaults to 1." + }, + { + "key": "pageSize", + "value": "12", + "description": "(Optional) The number of results to return per page. Defaults to 20." + }, + { + "key": "isPlayoff", + "value": "False", + "description": "(Optional) Set to 'true' to retrieve playoff stats, or 'false' for regular season stats." + } + ] + } + }, + "response": [] + }, { "name": "Player Totals Playoffs Stats", "event": [ @@ -331,10 +1845,6 @@ " pm.expect(responseData.data).to.be.an('array');", " ", " responseData.data.forEach(function(player) {", - " pm.expect(player).to.have.property('ID');", - " pm.expect(player).to.have.property('CreatedAt');", - " pm.expect(player).to.have.property('UpdatedAt');", - " pm.expect(player).to.have.property('DeletedAt');", " pm.expect(player).to.have.property('playerId');", " pm.expect(player).to.have.property('playerName');", " pm.expect(player).to.have.property('position');", @@ -355,106 +1865,262 @@ " pm.expect(responseData.pagination).to.have.property('pages');", " pm.expect(responseData.pagination).to.have.property('total');", "});", + "", + "// Player Statistics Visualization", "var template = `", - "", "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", + "
", + "
", + "

πŸ€ Player Statistics

", + "

{{subtitle}}

", + "
", " ", - " {{#each response.data}}", - "
", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " {{/each}}", - "
IDCreatedAtUpdatedAtDeletedAtidplayerIdplayerNamepositionagegamesgamesStartedminutesPgfieldGoalsfieldAttemptsfieldPercentthreeFgthreeAttemptsthreePercenttwoFgtwoAttemptstwoPercenteffectFgPercentftftAttemptsftPercentoffensiveRbdefensiveRbtotalRbassistsstealsblocksturnoverspersonalFoulspointsteamseason
{{ID}}{{CreatedAt}}{{UpdatedAt}}{{DeletedAt}}{{id}}{{playerId}}{{playerName}}{{position}}{{age}}{{games}}{{gamesStarted}}{{minutesPg}}{{fieldGoals}}{{fieldAttempts}}{{fieldPercent}}{{threeFg}}{{threeAttempts}}{{threePercent}}{{twoFg}}{{twoAttempts}}{{twoPercent}}{{effectFgPercent}}{{ft}}{{ftAttempts}}{{ftPercent}}{{offensiveRb}}{{defensiveRb}}{{totalRb}}{{assists}}{{steals}}{{blocks}}{{turnovers}}{{personalFouls}}{{points}}{{team}}{{season}}
", + " {{#if hasData}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{#each players}}", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " {{/each}}", + " ", + "
Player NamePositionGamesPointsAssistsReboundsFG%
{{playerName}}{{position}}{{games}}{{points}}{{assists}}{{totalRb}}{{fieldPercent}}
", + " ", + "
", + "
", + " Page:", + " {{pagination.page}} of {{pagination.pages}}", + "
", + "
", + " Showing:", + " {{pagination.pageSize}} players", + "
", + "
", + " Total Players:", + " {{pagination.total}}", + "
", + "
", + " {{else}}", + "
No player data available
", + " {{/if}}", + "", + "", + "", "`;", "", "function constructVisualizerPayload() {", - " return {response: pm.response.json()}", + " const response = pm.response.json();", + " const data = response.data || [];", + " const pagination = response.pagination || { page: 1, pageSize: 0, pages: 1, total: 0 };", + " ", + " const players = data.map(player => {", + " const fgPercent = player.fieldPercent || 0;", + " let fgClass = 'fg-low';", + " if (fgPercent >= 0.5) {", + " fgClass = 'fg-high';", + " } else if (fgPercent >= 0.4) {", + " fgClass = 'fg-mid';", + " }", + " ", + " return {", + " playerName: player.playerName || 'Unknown',", + " position: player.position || 'N/A',", + " games: player.games || 0,", + " points: player.points || 0,", + " assists: player.assists || 0,", + " totalRb: player.totalRb || 0,", + " fieldPercent: (fgPercent * 100).toFixed(1) + '%',", + " fgClass: fgClass", + " };", + " });", + " ", + " const subtitle = 'Playoff Statistics | Team: ' + (data[0]?.team || 'N/A') + ' | Season: ' + (data[0]?.season || 'N/A');", + " ", + " return {", + " players: players,", + " pagination: pagination,", + " hasData: players.length > 0,", + " subtitle: subtitle", + " };", "}", "", "pm.visualizer.set(template, constructVisualizerPayload());" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } }, { @@ -464,7 +2130,8 @@ "" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } } ], @@ -479,7 +2146,7 @@ } ], "url": { - "raw": "{{base_url}}/api/playertotals?season=2019&page=1&pageSize=20&sortBy=assists&isPlayoff=true", + "raw": "{{base_url}}/api/playertotals?team=HOU&page=1&pageSize=10&sortBy=assists&isPlayoff=true&season={{season}}", "host": [ "{{base_url}}" ], @@ -488,16 +2155,10 @@ "playertotals" ], "query": [ - { - "key": "season", - "value": "2019", - "description": "(Optional) The season year (e.g., 2025 for the 2024-25 season)." - }, { "key": "team", "value": "HOU", - "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL).", - "disabled": true + "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL)." }, { "key": "page", @@ -506,7 +2167,7 @@ }, { "key": "pageSize", - "value": "20", + "value": "10", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { @@ -518,6 +2179,10 @@ "key": "isPlayoff", "value": "true", "description": "(Optional) Set to 'true' to retrieve playoff stats, or 'false' for regular season stats." + }, + { + "key": "season", + "value": "{{season}}" } ] }, @@ -537,9 +2202,13 @@ } ], "url": { - "raw": "{{base_url}}/api/playertotals?season=2019&page=1&pageSize=20&sortBy=assists&isPlayoff=true", + "raw": "https://api.server.nbaapi.com/api/playertotals?season=2019&page=1&pageSize=10&sortBy=assists&isPlayoff=true", + "protocol": "https", "host": [ - "{{base_url}}" + "api", + "server", + "nbaapi", + "com" ], "path": [ "api", @@ -564,7 +2233,7 @@ }, { "key": "pageSize", - "value": "20", + "value": "10", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { @@ -642,9 +2311,6 @@ " pm.expect(responseData.data).to.be.an('array').that.is.not.empty;", " ", " responseData.data.forEach(function(playerStats) {", - " pm.expect(playerStats).to.have.property('ID');", - " pm.expect(playerStats).to.have.property('CreatedAt');", - " pm.expect(playerStats).to.have.property('UpdatedAt');", " pm.expect(playerStats).to.have.property('playerId');", " pm.expect(playerStats).to.have.property('playerName');", " pm.expect(playerStats).to.have.property('position');", @@ -675,12 +2341,94 @@ " pm.expect(playerStats).to.have.property('season');", " });", "});", + "", "pm.test(\"Response time is within acceptable range\", function () {", " pm.expect(pm.response.responseTime).to.be.below(200);", - "});" + "});", + "", + "// Visualization: Top Players by Win Shares Bar Chart", + "var template = `", + "

Top Players by Win Shares

", + "", + "", + "", + "`;", + "", + "function constructVisualizerPayload() {", + " var response = pm.response.json();", + " var players = response.data || [];", + " ", + " // Sort by winShares descending and take top players", + " var sortedPlayers = players.slice().sort(function(a, b) {", + " return b.winShares - a.winShares;", + " });", + " ", + " return {", + " playerNames: sortedPlayers.map(function(player) { return player.playerName; }),", + " winShares: sortedPlayers.map(function(player) { return player.winShares; })", + " };", + "}", + "", + "pm.visualizer.set(template, constructVisualizerPayload());" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } }, { @@ -690,7 +2438,8 @@ "" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } } ], @@ -705,7 +2454,7 @@ } ], "url": { - "raw": "{{base_url}}/api/playeradvancedstats?season=2025&team=HOU&page=1&pageSize=35&sortBy=vorp&ascending=false&isPlayoff=false", + "raw": "{{base_url}}/api/playeradvancedstats?season=2026&team=HOU&page=1&pageSize=15&ascending=false&isPlayoff=false", "host": [ "{{base_url}}" ], @@ -716,7 +2465,7 @@ "query": [ { "key": "season", - "value": "2025", + "value": "2026", "description": "(Optional) The NBA season year (e.g., 2025 for the 2024-25 season)." }, { @@ -731,13 +2480,14 @@ }, { "key": "pageSize", - "value": "35", + "value": "15", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { "key": "sortBy", "value": "vorp", - "description": "(Optional) The field to sort the results by. Defaults to 'winShares'." + "description": "(Optional) The field to sort the results by. Defaults to 'winShares'.", + "disabled": true }, { "key": "ascending", @@ -816,7 +2566,7 @@ }, "status": "OK", "code": 200, - "_postman_previewlanguage": "json", + "_postman_previewlanguage": null, "header": [ { "key": "Alt-Svc", @@ -832,7 +2582,7 @@ }, { "key": "Date", - "value": "Wed, 02 Jul 2025 01:18:43 GMT" + "value": "Tue, 16 Dec 2025 07:39:43 GMT" }, { "key": "Server", @@ -843,12 +2593,12 @@ "value": "Accept-Encoding" }, { - "key": "Transfer-Encoding", - "value": "chunked" + "key": "Content-Length", + "value": "1787" } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"ID\": 1451,\n \"id\": 35,\n \"playerId\": \"sengual01\",\n \"playerName\": \"Alperen Şengün\",\n \"position\": \"C\",\n \"age\": 22,\n \"games\": 76,\n \"minutesPlayed\": 2395,\n \"per\": 21.4,\n \"tsPercent\": 0.545,\n \"threePAR\": 0.079,\n \"ftr\": 0.374,\n \"offensiveRBPercent\": 11.4,\n \"defensiveRBPercent\": 23.8,\n \"totalRBPercent\": 17.5,\n \"assistPercent\": 24.1,\n \"stealPercent\": 1.7,\n \"blockPercent\": 2.3,\n \"turnoverPercent\": 12.7,\n \"usagePercent\": 26.2,\n \"offensiveWS\": 4.1,\n \"defensiveWS\": 4.2,\n \"winShares\": 8.3,\n \"winSharesPer\": 0.166,\n \"offensiveBox\": 2.6,\n \"defensiveBox\": 1.8,\n \"box\": 4.4,\n \"vorp\": 3.9,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T00:59:56.345088Z\",\n \"UpdatedAt\": \"2025-06-20T00:59:56.345088Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1475,\n \"id\": 57,\n \"playerId\": \"thompam01\",\n \"playerName\": \"Amen Thompson\",\n \"position\": \"SF\",\n \"age\": 22,\n \"games\": 69,\n \"minutesPlayed\": 2225,\n \"per\": 18.7,\n \"tsPercent\": 0.602,\n \"threePAR\": 0.131,\n \"ftr\": 0.354,\n \"offensiveRBPercent\": 9,\n \"defensiveRBPercent\": 18.2,\n \"totalRBPercent\": 13.5,\n \"assistPercent\": 16.9,\n \"stealPercent\": 2.1,\n \"blockPercent\": 3.6,\n \"turnoverPercent\": 14.6,\n \"usagePercent\": 17.5,\n \"offensiveWS\": 4.1,\n \"defensiveWS\": 3.9,\n \"winShares\": 8,\n \"winSharesPer\": 0.172,\n \"offensiveBox\": 1.4,\n \"defensiveBox\": 2.6,\n \"box\": 4.1,\n \"vorp\": 3.4,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T00:59:59.812013Z\",\n \"UpdatedAt\": \"2025-06-20T00:59:59.812013Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1643,\n \"id\": 190,\n \"playerId\": \"easonta01\",\n \"playerName\": \"Tari Eason\",\n \"position\": \"PF\",\n \"age\": 23,\n \"games\": 57,\n \"minutesPlayed\": 1420,\n \"per\": 18.5,\n \"tsPercent\": 0.567,\n \"threePAR\": 0.329,\n \"ftr\": 0.186,\n \"offensiveRBPercent\": 9.4,\n \"defensiveRBPercent\": 17.9,\n \"totalRBPercent\": 13.6,\n \"assistPercent\": 8.5,\n \"stealPercent\": 3.3,\n \"blockPercent\": 3.2,\n \"turnoverPercent\": 9.7,\n \"usagePercent\": 19.4,\n \"offensiveWS\": 2.1,\n \"defensiveWS\": 2.9,\n \"winShares\": 5,\n \"winSharesPer\": 0.169,\n \"offensiveBox\": 1,\n \"defensiveBox\": 2.6,\n \"box\": 3.6,\n \"vorp\": 2,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:25.170944Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:25.170944Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1424,\n \"id\": 10,\n \"playerId\": \"greenja05\",\n \"playerName\": \"Jalen Green\",\n \"position\": \"SG\",\n \"age\": 22,\n \"games\": 82,\n \"minutesPlayed\": 2697,\n \"per\": 15.1,\n \"tsPercent\": 0.544,\n \"threePAR\": 0.46,\n \"ftr\": 0.234,\n \"offensiveRBPercent\": 1.7,\n \"defensiveRBPercent\": 13.4,\n \"totalRBPercent\": 7.4,\n \"assistPercent\": 16,\n \"stealPercent\": 1.3,\n \"blockPercent\": 0.9,\n \"turnoverPercent\": 11.4,\n \"usagePercent\": 27.3,\n \"offensiveWS\": 1.9,\n \"defensiveWS\": 3.2,\n \"winShares\": 5.1,\n \"winSharesPer\": 0.092,\n \"offensiveBox\": 1.1,\n \"defensiveBox\": -0.5,\n \"box\": 0.5,\n \"vorp\": 1.7,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T00:59:52.368605Z\",\n \"UpdatedAt\": \"2025-06-20T00:59:52.368605Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1494,\n \"id\": 74,\n \"playerId\": \"vanvlfr01\",\n \"playerName\": \"Fred VanVleet\",\n \"position\": \"PG\",\n \"age\": 30,\n \"games\": 60,\n \"minutesPlayed\": 2111,\n \"per\": 12.8,\n \"tsPercent\": 0.515,\n \"threePAR\": 0.607,\n \"ftr\": 0.181,\n \"offensiveRBPercent\": 1.6,\n \"defensiveRBPercent\": 9.7,\n \"totalRBPercent\": 5.6,\n \"assistPercent\": 21.2,\n \"stealPercent\": 2.2,\n \"blockPercent\": 1.1,\n \"turnoverPercent\": 9.6,\n \"usagePercent\": 17.7,\n \"offensiveWS\": 2.4,\n \"defensiveWS\": 2.8,\n \"winShares\": 5.2,\n \"winSharesPer\": 0.119,\n \"offensiveBox\": -0.4,\n \"defensiveBox\": 1.3,\n \"box\": 0.9,\n \"vorp\": 1.5,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:02.726841Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:02.726841Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1583,\n \"id\": 144,\n \"playerId\": \"smithja05\",\n \"playerName\": \"Jabari Smith Jr.\",\n \"position\": \"PF\",\n \"age\": 21,\n \"games\": 57,\n \"minutesPlayed\": 1716,\n \"per\": 12.6,\n \"tsPercent\": 0.562,\n \"threePAR\": 0.489,\n \"ftr\": 0.223,\n \"offensiveRBPercent\": 6.4,\n \"defensiveRBPercent\": 18.6,\n \"totalRBPercent\": 12.4,\n \"assistPercent\": 4.7,\n \"stealPercent\": 0.7,\n \"blockPercent\": 2.1,\n \"turnoverPercent\": 8.9,\n \"usagePercent\": 16.4,\n \"offensiveWS\": 1.9,\n \"defensiveWS\": 2.2,\n \"winShares\": 4.2,\n \"winSharesPer\": 0.117,\n \"offensiveBox\": -0.8,\n \"defensiveBox\": 0.1,\n \"box\": -0.7,\n \"vorp\": 0.6,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:16.318994Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:16.318994Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1792,\n \"id\": 301,\n \"playerId\": \"whitmca01\",\n \"playerName\": \"Cam Whitmore\",\n \"position\": \"SF\",\n \"age\": 20,\n \"games\": 51,\n \"minutesPlayed\": 827,\n \"per\": 15.5,\n \"tsPercent\": 0.549,\n \"threePAR\": 0.454,\n \"ftr\": 0.179,\n \"offensiveRBPercent\": 4.5,\n \"defensiveRBPercent\": 15.1,\n \"totalRBPercent\": 9.7,\n \"assistPercent\": 8.9,\n \"stealPercent\": 1.8,\n \"blockPercent\": 1.4,\n \"turnoverPercent\": 9.6,\n \"usagePercent\": 23.9,\n \"offensiveWS\": 0.6,\n \"defensiveWS\": 1.2,\n \"winShares\": 1.8,\n \"winSharesPer\": 0.106,\n \"offensiveBox\": 0.7,\n \"defensiveBox\": -0.4,\n \"box\": 0.3,\n \"vorp\": 0.5,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:46.875219Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:46.875219Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1795,\n \"id\": 304,\n \"playerId\": \"adamsst01\",\n \"playerName\": \"Steven Adams\",\n \"position\": \"C\",\n \"age\": 31,\n \"games\": 58,\n \"minutesPlayed\": 794,\n \"per\": 16.6,\n \"tsPercent\": 0.541,\n \"threePAR\": 0.012,\n \"ftr\": 0.557,\n \"offensiveRBPercent\": 21.8,\n \"defensiveRBPercent\": 22,\n \"totalRBPercent\": 21.9,\n \"assistPercent\": 10.9,\n \"stealPercent\": 1.3,\n \"blockPercent\": 3.2,\n \"turnoverPercent\": 20.6,\n \"usagePercent\": 13.6,\n \"offensiveWS\": 1,\n \"defensiveWS\": 1.3,\n \"winShares\": 2.3,\n \"winSharesPer\": 0.137,\n \"offensiveBox\": 0,\n \"defensiveBox\": 0.3,\n \"box\": 0.3,\n \"vorp\": 0.5,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:47.313648Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:47.313648Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1452,\n \"id\": 36,\n \"playerId\": \"brookdi01\",\n \"playerName\": \"Dillon Brooks\",\n \"position\": \"SF\",\n \"age\": 29,\n \"games\": 75,\n \"minutesPlayed\": 2388,\n \"per\": 11,\n \"tsPercent\": 0.555,\n \"threePAR\": 0.524,\n \"ftr\": 0.135,\n \"offensiveRBPercent\": 3.3,\n \"defensiveRBPercent\": 9.1,\n \"totalRBPercent\": 6.1,\n \"assistPercent\": 7.4,\n \"stealPercent\": 1.2,\n \"blockPercent\": 0.6,\n \"turnoverPercent\": 7.4,\n \"usagePercent\": 17.7,\n \"offensiveWS\": 2.7,\n \"defensiveWS\": 2.5,\n \"winShares\": 5.1,\n \"winSharesPer\": 0.103,\n \"offensiveBox\": -1.4,\n \"defensiveBox\": 0,\n \"box\": -1.4,\n \"vorp\": 0.4,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T00:59:56.492538Z\",\n \"UpdatedAt\": \"2025-06-20T00:59:56.492538Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1796,\n \"id\": 305,\n \"playerId\": \"holidaa01\",\n \"playerName\": \"Aaron Holiday\",\n \"position\": \"PG\",\n \"age\": 28,\n \"games\": 62,\n \"minutesPlayed\": 792,\n \"per\": 12.2,\n \"tsPercent\": 0.594,\n \"threePAR\": 0.675,\n \"ftr\": 0.153,\n \"offensiveRBPercent\": 1.7,\n \"defensiveRBPercent\": 8.9,\n \"totalRBPercent\": 5.2,\n \"assistPercent\": 14.3,\n \"stealPercent\": 1.2,\n \"blockPercent\": 1.2,\n \"turnoverPercent\": 11.5,\n \"usagePercent\": 16.8,\n \"offensiveWS\": 1.2,\n \"defensiveWS\": 0.8,\n \"winShares\": 2,\n \"winSharesPer\": 0.122,\n \"offensiveBox\": -0.4,\n \"defensiveBox\": 0.1,\n \"box\": -0.2,\n \"vorp\": 0.3,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:47.482453Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:47.482453Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1888,\n \"id\": 375,\n \"playerId\": \"landajo01\",\n \"playerName\": \"Jock Landale\",\n \"position\": \"C\",\n \"age\": 29,\n \"games\": 42,\n \"minutesPlayed\": 500,\n \"per\": 16,\n \"tsPercent\": 0.59,\n \"threePAR\": 0.171,\n \"ftr\": 0.263,\n \"offensiveRBPercent\": 11.7,\n \"defensiveRBPercent\": 17.6,\n \"totalRBPercent\": 14.6,\n \"assistPercent\": 10.3,\n \"stealPercent\": 1.3,\n \"blockPercent\": 1.8,\n \"turnoverPercent\": 11,\n \"usagePercent\": 15.7,\n \"offensiveWS\": 1,\n \"defensiveWS\": 0.7,\n \"winShares\": 1.7,\n \"winSharesPer\": 0.159,\n \"offensiveBox\": 0,\n \"defensiveBox\": 0.4,\n \"box\": 0.4,\n \"vorp\": 0.3,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:01:00.821492Z\",\n \"UpdatedAt\": \"2025-06-20T01:01:00.821492Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1862,\n \"id\": 353,\n \"playerId\": \"tateja01\",\n \"playerName\": \"Jae'Sean Tate\",\n \"position\": \"SF\",\n \"age\": 29,\n \"games\": 52,\n \"minutesPlayed\": 588,\n \"per\": 12.3,\n \"tsPercent\": 0.557,\n \"threePAR\": 0.311,\n \"ftr\": 0.318,\n \"offensiveRBPercent\": 8.9,\n \"defensiveRBPercent\": 12.4,\n \"totalRBPercent\": 10.6,\n \"assistPercent\": 10.5,\n \"stealPercent\": 2.2,\n \"blockPercent\": 1.1,\n \"turnoverPercent\": 11.5,\n \"usagePercent\": 13.3,\n \"offensiveWS\": 0.8,\n \"defensiveWS\": 0.8,\n \"winShares\": 1.6,\n \"winSharesPer\": 0.133,\n \"offensiveBox\": -2.1,\n \"defensiveBox\": 1.4,\n \"box\": -0.7,\n \"vorp\": 0.2,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:57.110788Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:57.110788Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1931,\n \"id\": 404,\n \"playerId\": \"greenje02\",\n \"playerName\": \"Jeff Green\",\n \"position\": \"PF\",\n \"age\": 38,\n \"games\": 32,\n \"minutesPlayed\": 396,\n \"per\": 13.6,\n \"tsPercent\": 0.649,\n \"threePAR\": 0.653,\n \"ftr\": 0.215,\n \"offensiveRBPercent\": 2.9,\n \"defensiveRBPercent\": 12.9,\n \"totalRBPercent\": 7.8,\n \"assistPercent\": 7,\n \"stealPercent\": 0.7,\n \"blockPercent\": 0.9,\n \"turnoverPercent\": 6.4,\n \"usagePercent\": 14.7,\n \"offensiveWS\": 0.9,\n \"defensiveWS\": 0.4,\n \"winShares\": 1.3,\n \"winSharesPer\": 0.159,\n \"offensiveBox\": 0.3,\n \"defensiveBox\": 0,\n \"box\": 0.4,\n \"vorp\": 0.2,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:01:07.235443Z\",\n \"UpdatedAt\": \"2025-06-20T01:01:07.235443Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1837,\n \"id\": 336,\n \"playerId\": \"sheppre01\",\n \"playerName\": \"Reed Sheppard\",\n \"position\": \"PG\",\n \"age\": 20,\n \"games\": 52,\n \"minutesPlayed\": 654,\n \"per\": 9.7,\n \"tsPercent\": 0.465,\n \"threePAR\": 0.594,\n \"ftr\": 0.067,\n \"offensiveRBPercent\": 2.6,\n \"defensiveRBPercent\": 10.3,\n \"totalRBPercent\": 6.4,\n \"assistPercent\": 15.2,\n \"stealPercent\": 2.6,\n \"blockPercent\": 2.3,\n \"turnoverPercent\": 13.1,\n \"usagePercent\": 17.8,\n \"offensiveWS\": -0.3,\n \"defensiveWS\": 1,\n \"winShares\": 0.8,\n \"winSharesPer\": 0.055,\n \"offensiveBox\": -3,\n \"defensiveBox\": 1.3,\n \"box\": -1.7,\n \"vorp\": 0.1,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:00:53.498684Z\",\n \"UpdatedAt\": \"2025-06-20T01:00:53.498684Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2101,\n \"id\": 523,\n \"playerId\": \"nfalyda01\",\n \"playerName\": \"N'Faly Dante\",\n \"position\": \"C\",\n \"age\": 23,\n \"games\": 4,\n \"minutesPlayed\": 51,\n \"per\": 24,\n \"tsPercent\": 0.789,\n \"threePAR\": 0,\n \"ftr\": 0.385,\n \"offensiveRBPercent\": 12.3,\n \"defensiveRBPercent\": 32,\n \"totalRBPercent\": 21.9,\n \"assistPercent\": 5.7,\n \"stealPercent\": 1,\n \"blockPercent\": 8.8,\n \"turnoverPercent\": 11.6,\n \"usagePercent\": 13.9,\n \"offensiveWS\": 0.2,\n \"defensiveWS\": 0.1,\n \"winShares\": 0.3,\n \"winSharesPer\": 0.283,\n \"offensiveBox\": 0.7,\n \"defensiveBox\": 1.7,\n \"box\": 2.4,\n \"vorp\": 0.1,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:01:31.754493Z\",\n \"UpdatedAt\": \"2025-06-20T01:01:31.754493Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 1924,\n \"id\": 397,\n \"playerId\": \"roddyda01\",\n \"playerName\": \"David Roddy\",\n \"position\": \"PF\",\n \"age\": 23,\n \"games\": 3,\n \"minutesPlayed\": 35,\n \"per\": 7.2,\n \"tsPercent\": 0.44,\n \"threePAR\": 0.538,\n \"ftr\": 0.308,\n \"offensiveRBPercent\": 0,\n \"defensiveRBPercent\": 15.5,\n \"totalRBPercent\": 7.6,\n \"assistPercent\": 7.7,\n \"stealPercent\": 0,\n \"blockPercent\": 2.6,\n \"turnoverPercent\": 6.3,\n \"usagePercent\": 18.5,\n \"offensiveWS\": 0,\n \"defensiveWS\": 0,\n \"winShares\": 0,\n \"winSharesPer\": 0.007,\n \"offensiveBox\": -5.1,\n \"defensiveBox\": -3.2,\n \"box\": -8.3,\n \"vorp\": -0.1,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:01:06.249889Z\",\n \"UpdatedAt\": \"2025-06-20T01:01:06.249889Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2038,\n \"id\": 472,\n \"playerId\": \"willije02\",\n \"playerName\": \"Jeenathan Williams\",\n \"position\": \"SG\",\n \"age\": 25,\n \"games\": 20,\n \"minutesPlayed\": 147,\n \"per\": 8.6,\n \"tsPercent\": 0.496,\n \"threePAR\": 0.419,\n \"ftr\": 0.129,\n \"offensiveRBPercent\": 3.6,\n \"defensiveRBPercent\": 5.9,\n \"totalRBPercent\": 4.7,\n \"assistPercent\": 8.8,\n \"stealPercent\": 2.6,\n \"blockPercent\": 2.4,\n \"turnoverPercent\": 17.6,\n \"usagePercent\": 22.3,\n \"offensiveWS\": -0.2,\n \"defensiveWS\": 0.2,\n \"winShares\": 0,\n \"winSharesPer\": -0.007,\n \"offensiveBox\": -5.5,\n \"defensiveBox\": -0.2,\n \"box\": -5.7,\n \"vorp\": -0.1,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:01:22.535279Z\",\n \"UpdatedAt\": \"2025-06-20T01:01:22.535279Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2106,\n \"id\": 528,\n \"playerId\": \"mcveija01\",\n \"playerName\": \"Jack McVeigh\",\n \"position\": \"PF\",\n \"age\": 28,\n \"games\": 9,\n \"minutesPlayed\": 43,\n \"per\": 4,\n \"tsPercent\": 0.412,\n \"threePAR\": 0.765,\n \"ftr\": 0,\n \"offensiveRBPercent\": 4.9,\n \"defensiveRBPercent\": 7.6,\n \"totalRBPercent\": 6.2,\n \"assistPercent\": 3,\n \"stealPercent\": 0,\n \"blockPercent\": 4.2,\n \"turnoverPercent\": 10.5,\n \"usagePercent\": 18.2,\n \"offensiveWS\": -0.1,\n \"defensiveWS\": 0,\n \"winShares\": 0,\n \"winSharesPer\": -0.031,\n \"offensiveBox\": -4.8,\n \"defensiveBox\": -3,\n \"box\": -7.7,\n \"vorp\": -0.1,\n \"team\": \"HOU\",\n \"season\": 2025,\n \"isPlayoff\": false,\n \"CreatedAt\": \"2025-06-20T01:01:32.499427Z\",\n \"UpdatedAt\": \"2025-06-20T01:01:32.499427Z\",\n \"DeletedAt\": null\n }\n ],\n \"pagination\": {\n \"total\": 18,\n \"page\": 1,\n \"pageSize\": 35,\n \"pages\": 1\n }\n}" + "body": "{\n \"data\": [\n {\n \"playerId\": \"sengual01\",\n \"playerName\": \"Alperen Şengün\",\n \"position\": \"C\",\n \"age\": 22,\n \"team\": \"HOU\",\n \"games\": 76,\n \"minutesPlayed\": 2395,\n \"per\": 21.4,\n \"tsPercent\": 0.545,\n \"threePAR\": 0.079,\n \"ftr\": 0.374,\n \"offensiveRBPercent\": 11.4,\n \"defensiveRBPercent\": 23.8,\n \"totalRBPercent\": 17.5,\n \"assistPercent\": 24.1,\n \"stealPercent\": 1.7,\n \"blockPercent\": 2.3,\n \"turnoverPercent\": 12.7,\n \"usagePercent\": 26.2,\n \"offensiveWS\": 4.1,\n \"defensiveWS\": 4.2,\n \"winShares\": 8.3,\n \"winSharesPer\": 0.166,\n \"offensiveBox\": 2.6,\n \"defensiveBox\": 1.8,\n \"box\": 4.4,\n \"vorp\": 3.9,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"thompam01\",\n \"playerName\": \"Amen Thompson\",\n \"position\": \"SF\",\n \"age\": 22,\n \"team\": \"HOU\",\n \"games\": 69,\n \"minutesPlayed\": 2225,\n \"per\": 18.7,\n \"tsPercent\": 0.602,\n \"threePAR\": 0.131,\n \"ftr\": 0.354,\n \"offensiveRBPercent\": 9,\n \"defensiveRBPercent\": 18.2,\n \"totalRBPercent\": 13.5,\n \"assistPercent\": 16.9,\n \"stealPercent\": 2.1,\n \"blockPercent\": 3.6,\n \"turnoverPercent\": 14.6,\n \"usagePercent\": 17.5,\n \"offensiveWS\": 4.1,\n \"defensiveWS\": 3.9,\n \"winShares\": 8,\n \"winSharesPer\": 0.172,\n \"offensiveBox\": 1.4,\n \"defensiveBox\": 2.6,\n \"box\": 4.1,\n \"vorp\": 3.4,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"easonta01\",\n \"playerName\": \"Tari Eason\",\n \"position\": \"PF\",\n \"age\": 23,\n \"team\": \"HOU\",\n \"games\": 57,\n \"minutesPlayed\": 1420,\n \"per\": 18.5,\n \"tsPercent\": 0.567,\n \"threePAR\": 0.329,\n \"ftr\": 0.186,\n \"offensiveRBPercent\": 9.4,\n \"defensiveRBPercent\": 17.9,\n \"totalRBPercent\": 13.6,\n \"assistPercent\": 8.5,\n \"stealPercent\": 3.3,\n \"blockPercent\": 3.2,\n \"turnoverPercent\": 9.7,\n \"usagePercent\": 19.4,\n \"offensiveWS\": 2.1,\n \"defensiveWS\": 2.9,\n \"winShares\": 5,\n \"winSharesPer\": 0.169,\n \"offensiveBox\": 1,\n \"defensiveBox\": 2.6,\n \"box\": 3.6,\n \"vorp\": 2,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"greenja05\",\n \"playerName\": \"Jalen Green\",\n \"position\": \"SG\",\n \"age\": 22,\n \"team\": \"HOU\",\n \"games\": 82,\n \"minutesPlayed\": 2697,\n \"per\": 15.1,\n \"tsPercent\": 0.544,\n \"threePAR\": 0.46,\n \"ftr\": 0.234,\n \"offensiveRBPercent\": 1.7,\n \"defensiveRBPercent\": 13.4,\n \"totalRBPercent\": 7.4,\n \"assistPercent\": 16,\n \"stealPercent\": 1.3,\n \"blockPercent\": 0.9,\n \"turnoverPercent\": 11.4,\n \"usagePercent\": 27.3,\n \"offensiveWS\": 1.9,\n \"defensiveWS\": 3.2,\n \"winShares\": 5.1,\n \"winSharesPer\": 0.092,\n \"offensiveBox\": 1.1,\n \"defensiveBox\": -0.5,\n \"box\": 0.5,\n \"vorp\": 1.7,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"vanvlfr01\",\n \"playerName\": \"Fred VanVleet\",\n \"position\": \"PG\",\n \"age\": 30,\n \"team\": \"HOU\",\n \"games\": 60,\n \"minutesPlayed\": 2111,\n \"per\": 12.8,\n \"tsPercent\": 0.515,\n \"threePAR\": 0.607,\n \"ftr\": 0.181,\n \"offensiveRBPercent\": 1.6,\n \"defensiveRBPercent\": 9.7,\n \"totalRBPercent\": 5.6,\n \"assistPercent\": 21.2,\n \"stealPercent\": 2.2,\n \"blockPercent\": 1.1,\n \"turnoverPercent\": 9.6,\n \"usagePercent\": 17.7,\n \"offensiveWS\": 2.4,\n \"defensiveWS\": 2.8,\n \"winShares\": 5.2,\n \"winSharesPer\": 0.119,\n \"offensiveBox\": -0.4,\n \"defensiveBox\": 1.3,\n \"box\": 0.9,\n \"vorp\": 1.5,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"smithja05\",\n \"playerName\": \"Jabari Smith Jr.\",\n \"position\": \"PF\",\n \"age\": 21,\n \"team\": \"HOU\",\n \"games\": 57,\n \"minutesPlayed\": 1716,\n \"per\": 12.6,\n \"tsPercent\": 0.562,\n \"threePAR\": 0.489,\n \"ftr\": 0.223,\n \"offensiveRBPercent\": 6.4,\n \"defensiveRBPercent\": 18.6,\n \"totalRBPercent\": 12.4,\n \"assistPercent\": 4.7,\n \"stealPercent\": 0.7,\n \"blockPercent\": 2.1,\n \"turnoverPercent\": 8.9,\n \"usagePercent\": 16.4,\n \"offensiveWS\": 1.9,\n \"defensiveWS\": 2.2,\n \"winShares\": 4.2,\n \"winSharesPer\": 0.117,\n \"offensiveBox\": -0.8,\n \"defensiveBox\": 0.1,\n \"box\": -0.7,\n \"vorp\": 0.6,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"whitmca01\",\n \"playerName\": \"Cam Whitmore\",\n \"position\": \"SF\",\n \"age\": 20,\n \"team\": \"HOU\",\n \"games\": 51,\n \"minutesPlayed\": 827,\n \"per\": 15.5,\n \"tsPercent\": 0.549,\n \"threePAR\": 0.454,\n \"ftr\": 0.179,\n \"offensiveRBPercent\": 4.5,\n \"defensiveRBPercent\": 15.1,\n \"totalRBPercent\": 9.7,\n \"assistPercent\": 8.9,\n \"stealPercent\": 1.8,\n \"blockPercent\": 1.4,\n \"turnoverPercent\": 9.6,\n \"usagePercent\": 23.9,\n \"offensiveWS\": 0.6,\n \"defensiveWS\": 1.2,\n \"winShares\": 1.8,\n \"winSharesPer\": 0.106,\n \"offensiveBox\": 0.7,\n \"defensiveBox\": -0.4,\n \"box\": 0.3,\n \"vorp\": 0.5,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"adamsst01\",\n \"playerName\": \"Steven Adams\",\n \"position\": \"C\",\n \"age\": 31,\n \"team\": \"HOU\",\n \"games\": 58,\n \"minutesPlayed\": 794,\n \"per\": 16.6,\n \"tsPercent\": 0.541,\n \"threePAR\": 0.012,\n \"ftr\": 0.557,\n \"offensiveRBPercent\": 21.8,\n \"defensiveRBPercent\": 22,\n \"totalRBPercent\": 21.9,\n \"assistPercent\": 10.9,\n \"stealPercent\": 1.3,\n \"blockPercent\": 3.2,\n \"turnoverPercent\": 20.6,\n \"usagePercent\": 13.6,\n \"offensiveWS\": 1,\n \"defensiveWS\": 1.3,\n \"winShares\": 2.3,\n \"winSharesPer\": 0.137,\n \"offensiveBox\": 0,\n \"defensiveBox\": 0.3,\n \"box\": 0.3,\n \"vorp\": 0.5,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"brookdi01\",\n \"playerName\": \"Dillon Brooks\",\n \"position\": \"SF\",\n \"age\": 29,\n \"team\": \"HOU\",\n \"games\": 75,\n \"minutesPlayed\": 2388,\n \"per\": 11,\n \"tsPercent\": 0.555,\n \"threePAR\": 0.524,\n \"ftr\": 0.135,\n \"offensiveRBPercent\": 3.3,\n \"defensiveRBPercent\": 9.1,\n \"totalRBPercent\": 6.1,\n \"assistPercent\": 7.4,\n \"stealPercent\": 1.2,\n \"blockPercent\": 0.6,\n \"turnoverPercent\": 7.4,\n \"usagePercent\": 17.7,\n \"offensiveWS\": 2.7,\n \"defensiveWS\": 2.5,\n \"winShares\": 5.1,\n \"winSharesPer\": 0.103,\n \"offensiveBox\": -1.4,\n \"defensiveBox\": 0,\n \"box\": -1.4,\n \"vorp\": 0.4,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"holidaa01\",\n \"playerName\": \"Aaron Holiday\",\n \"position\": \"PG\",\n \"age\": 28,\n \"team\": \"HOU\",\n \"games\": 62,\n \"minutesPlayed\": 792,\n \"per\": 12.2,\n \"tsPercent\": 0.594,\n \"threePAR\": 0.675,\n \"ftr\": 0.153,\n \"offensiveRBPercent\": 1.7,\n \"defensiveRBPercent\": 8.9,\n \"totalRBPercent\": 5.2,\n \"assistPercent\": 14.3,\n \"stealPercent\": 1.2,\n \"blockPercent\": 1.2,\n \"turnoverPercent\": 11.5,\n \"usagePercent\": 16.8,\n \"offensiveWS\": 1.2,\n \"defensiveWS\": 0.8,\n \"winShares\": 2,\n \"winSharesPer\": 0.122,\n \"offensiveBox\": -0.4,\n \"defensiveBox\": 0.1,\n \"box\": -0.2,\n \"vorp\": 0.3,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"landajo01\",\n \"playerName\": \"Jock Landale\",\n \"position\": \"C\",\n \"age\": 29,\n \"team\": \"HOU\",\n \"games\": 42,\n \"minutesPlayed\": 500,\n \"per\": 16,\n \"tsPercent\": 0.59,\n \"threePAR\": 0.171,\n \"ftr\": 0.263,\n \"offensiveRBPercent\": 11.7,\n \"defensiveRBPercent\": 17.6,\n \"totalRBPercent\": 14.6,\n \"assistPercent\": 10.3,\n \"stealPercent\": 1.3,\n \"blockPercent\": 1.8,\n \"turnoverPercent\": 11,\n \"usagePercent\": 15.7,\n \"offensiveWS\": 1,\n \"defensiveWS\": 0.7,\n \"winShares\": 1.7,\n \"winSharesPer\": 0.159,\n \"offensiveBox\": 0,\n \"defensiveBox\": 0.4,\n \"box\": 0.4,\n \"vorp\": 0.3,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"tateja01\",\n \"playerName\": \"Jae'Sean Tate\",\n \"position\": \"SF\",\n \"age\": 29,\n \"team\": \"HOU\",\n \"games\": 52,\n \"minutesPlayed\": 588,\n \"per\": 12.3,\n \"tsPercent\": 0.557,\n \"threePAR\": 0.311,\n \"ftr\": 0.318,\n \"offensiveRBPercent\": 8.9,\n \"defensiveRBPercent\": 12.4,\n \"totalRBPercent\": 10.6,\n \"assistPercent\": 10.5,\n \"stealPercent\": 2.2,\n \"blockPercent\": 1.1,\n \"turnoverPercent\": 11.5,\n \"usagePercent\": 13.3,\n \"offensiveWS\": 0.8,\n \"defensiveWS\": 0.8,\n \"winShares\": 1.6,\n \"winSharesPer\": 0.133,\n \"offensiveBox\": -2.1,\n \"defensiveBox\": 1.4,\n \"box\": -0.7,\n \"vorp\": 0.2,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"greenje02\",\n \"playerName\": \"Jeff Green\",\n \"position\": \"PF\",\n \"age\": 38,\n \"team\": \"HOU\",\n \"games\": 32,\n \"minutesPlayed\": 396,\n \"per\": 13.6,\n \"tsPercent\": 0.649,\n \"threePAR\": 0.653,\n \"ftr\": 0.215,\n \"offensiveRBPercent\": 2.9,\n \"defensiveRBPercent\": 12.9,\n \"totalRBPercent\": 7.8,\n \"assistPercent\": 7,\n \"stealPercent\": 0.7,\n \"blockPercent\": 0.9,\n \"turnoverPercent\": 6.4,\n \"usagePercent\": 14.7,\n \"offensiveWS\": 0.9,\n \"defensiveWS\": 0.4,\n \"winShares\": 1.3,\n \"winSharesPer\": 0.159,\n \"offensiveBox\": 0.3,\n \"defensiveBox\": 0,\n \"box\": 0.4,\n \"vorp\": 0.2,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"sheppre01\",\n \"playerName\": \"Reed Sheppard\",\n \"position\": \"PG\",\n \"age\": 20,\n \"team\": \"HOU\",\n \"games\": 52,\n \"minutesPlayed\": 654,\n \"per\": 9.7,\n \"tsPercent\": 0.465,\n \"threePAR\": 0.594,\n \"ftr\": 0.067,\n \"offensiveRBPercent\": 2.6,\n \"defensiveRBPercent\": 10.3,\n \"totalRBPercent\": 6.4,\n \"assistPercent\": 15.2,\n \"stealPercent\": 2.6,\n \"blockPercent\": 2.3,\n \"turnoverPercent\": 13.1,\n \"usagePercent\": 17.8,\n \"offensiveWS\": -0.3,\n \"defensiveWS\": 1,\n \"winShares\": 0.8,\n \"winSharesPer\": 0.055,\n \"offensiveBox\": -3,\n \"defensiveBox\": 1.3,\n \"box\": -1.7,\n \"vorp\": 0.1,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"nfalyda01\",\n \"playerName\": \"N'Faly Dante\",\n \"position\": \"C\",\n \"age\": 23,\n \"team\": \"HOU\",\n \"games\": 4,\n \"minutesPlayed\": 51,\n \"per\": 24,\n \"tsPercent\": 0.789,\n \"threePAR\": 0,\n \"ftr\": 0.385,\n \"offensiveRBPercent\": 12.3,\n \"defensiveRBPercent\": 32,\n \"totalRBPercent\": 21.9,\n \"assistPercent\": 5.7,\n \"stealPercent\": 1,\n \"blockPercent\": 8.8,\n \"turnoverPercent\": 11.6,\n \"usagePercent\": 13.9,\n \"offensiveWS\": 0.2,\n \"defensiveWS\": 0.1,\n \"winShares\": 0.3,\n \"winSharesPer\": 0.283,\n \"offensiveBox\": 0.7,\n \"defensiveBox\": 1.7,\n \"box\": 2.4,\n \"vorp\": 0.1,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"willije02\",\n \"playerName\": \"Jeenathan Williams\",\n \"position\": \"SG\",\n \"age\": 25,\n \"team\": \"HOU\",\n \"games\": 20,\n \"minutesPlayed\": 147,\n \"per\": 8.6,\n \"tsPercent\": 0.496,\n \"threePAR\": 0.419,\n \"ftr\": 0.129,\n \"offensiveRBPercent\": 3.6,\n \"defensiveRBPercent\": 5.9,\n \"totalRBPercent\": 4.7,\n \"assistPercent\": 8.8,\n \"stealPercent\": 2.6,\n \"blockPercent\": 2.4,\n \"turnoverPercent\": 17.6,\n \"usagePercent\": 22.3,\n \"offensiveWS\": -0.2,\n \"defensiveWS\": 0.2,\n \"winShares\": 0,\n \"winSharesPer\": -0.007,\n \"offensiveBox\": -5.5,\n \"defensiveBox\": -0.2,\n \"box\": -5.7,\n \"vorp\": -0.1,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"mcveija01\",\n \"playerName\": \"Jack McVeigh\",\n \"position\": \"PF\",\n \"age\": 28,\n \"team\": \"HOU\",\n \"games\": 9,\n \"minutesPlayed\": 43,\n \"per\": 4,\n \"tsPercent\": 0.412,\n \"threePAR\": 0.765,\n \"ftr\": 0,\n \"offensiveRBPercent\": 4.9,\n \"defensiveRBPercent\": 7.6,\n \"totalRBPercent\": 6.2,\n \"assistPercent\": 3,\n \"stealPercent\": 0,\n \"blockPercent\": 4.2,\n \"turnoverPercent\": 10.5,\n \"usagePercent\": 18.2,\n \"offensiveWS\": -0.1,\n \"defensiveWS\": 0,\n \"winShares\": 0,\n \"winSharesPer\": -0.031,\n \"offensiveBox\": -4.8,\n \"defensiveBox\": -3,\n \"box\": -7.7,\n \"vorp\": -0.1,\n \"season\": 2025,\n \"isPlayoff\": false\n },\n {\n \"playerId\": \"roddyda01\",\n \"playerName\": \"David Roddy\",\n \"position\": \"PF\",\n \"age\": 23,\n \"team\": \"HOU\",\n \"games\": 3,\n \"minutesPlayed\": 35,\n \"per\": 7.2,\n \"tsPercent\": 0.44,\n \"threePAR\": 0.538,\n \"ftr\": 0.308,\n \"offensiveRBPercent\": 0,\n \"defensiveRBPercent\": 15.5,\n \"totalRBPercent\": 7.6,\n \"assistPercent\": 7.7,\n \"stealPercent\": 0,\n \"blockPercent\": 2.6,\n \"turnoverPercent\": 6.3,\n \"usagePercent\": 18.5,\n \"offensiveWS\": 0,\n \"defensiveWS\": 0,\n \"winShares\": 0,\n \"winSharesPer\": 0.007,\n \"offensiveBox\": -5.1,\n \"defensiveBox\": -3.2,\n \"box\": -8.3,\n \"vorp\": -0.1,\n \"season\": 2025,\n \"isPlayoff\": false\n }\n ],\n \"pagination\": {\n \"total\": 18,\n \"page\": 1,\n \"pageSize\": 35,\n \"pages\": 1\n }\n}" } ] }, @@ -859,62 +2609,127 @@ "listen": "test", "script": { "exec": [ - "pm.test(\"Response status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "", - "pm.test(\"Response time is within acceptable range\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(200);", - "});", - "", - "", - "pm.test(\"Response schema matches the expected structure\", function () {", - " const responseData = pm.response.json();", - " ", - " pm.expect(responseData).to.be.an('object');", - " pm.expect(responseData.data).to.be.an('array').that.is.not.empty;", - " ", - " responseData.data.forEach(function(playerStats) {", - " pm.expect(playerStats).to.have.property('ID');", - " pm.expect(playerStats).to.have.property('CreatedAt');", - " pm.expect(playerStats).to.have.property('UpdatedAt');", - " pm.expect(playerStats).to.have.property('playerId');", - " pm.expect(playerStats).to.have.property('playerName');", - " pm.expect(playerStats).to.have.property('position');", - " pm.expect(playerStats).to.have.property('age');", - " pm.expect(playerStats).to.have.property('games');", - " pm.expect(playerStats).to.have.property('minutesPlayed');", - " pm.expect(playerStats).to.have.property('per');", - " pm.expect(playerStats).to.have.property('tsPercent');", - " pm.expect(playerStats).to.have.property('threePAR');", - " pm.expect(playerStats).to.have.property('ftr');", - " pm.expect(playerStats).to.have.property('offensiveRBPercent');", - " pm.expect(playerStats).to.have.property('defensiveRBPercent');", - " pm.expect(playerStats).to.have.property('totalRBPercent');", - " pm.expect(playerStats).to.have.property('assistPercent');", - " pm.expect(playerStats).to.have.property('stealPercent');", - " pm.expect(playerStats).to.have.property('blockPercent');", - " pm.expect(playerStats).to.have.property('turnoverPercent');", - " pm.expect(playerStats).to.have.property('usagePercent');", - " pm.expect(playerStats).to.have.property('offensiveWS');", - " pm.expect(playerStats).to.have.property('defensiveWS');", - " pm.expect(playerStats).to.have.property('winShares');", - " pm.expect(playerStats).to.have.property('winSharesPer');", - " pm.expect(playerStats).to.have.property('offensiveBox');", - " pm.expect(playerStats).to.have.property('defensiveBox');", - " pm.expect(playerStats).to.have.property('box');", - " pm.expect(playerStats).to.have.property('vorp');", - " pm.expect(playerStats).to.have.property('team');", - " pm.expect(playerStats).to.have.property('season');", + "// Visualization Script", + "// Visualization Script", + "var template = `", + "

Player Advanced Playoff Stats - Win Shares Comparison

", + "", + "", + "", + "`;", + "", + "function createPayload() {", + " var response = pm.response.json();", + " var data = response.data || [];", + " ", + " // Sort players by win shares descending for better visualization", + " var sortedPlayers = data.slice().sort(function(a, b) {", + " return b.winShares - a.winShares;", + " });", + " ", + " var players = sortedPlayers.map(function(player) {", + " // Get last name for shorter labels", + " var nameParts = player.playerName.split(' ');", + " var shortName = nameParts.length > 1 ? nameParts[nameParts.length - 1] : player.playerName;", + " ", + " return {", + " name: shortName,", + " fullName: player.playerName,", + " winShares: player.winShares || 0,", + " per: player.per || 0,", + " box: player.box || 0,", + " vorp: player.vorp || 0,", + " team: player.team || 'N/A',", + " position: player.position || 'N/A'", + " };", + " });", + " ", + " return { players: players };", + "}", + "", + "pm.visualizer.set(template, createPayload());" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } }, { @@ -924,7 +2739,8 @@ "" ], "type": "text/javascript", - "packages": {} + "packages": {}, + "requests": {} } } ], @@ -939,7 +2755,7 @@ } ], "url": { - "raw": "{{base_url}}/api/playeradvancedstats?season=2025&team=OKC&page=1&pageSize=35&sortBy=defensiveBox&ascending=false&isPlayoff=true", + "raw": "{{base_url}}/api/playeradvancedstats?season=2025&team=HOU&page=1&pageSize=4&sortBy=defensiveBox&ascending=false&isPlayoff=true", "host": [ "{{base_url}}" ], @@ -955,7 +2771,7 @@ }, { "key": "team", - "value": "OKC", + "value": "HOU", "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL)." }, { @@ -965,7 +2781,7 @@ }, { "key": "pageSize", - "value": "35", + "value": "4", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { @@ -1001,7 +2817,7 @@ } ], "url": { - "raw": "{{base_url}}/api/playeradvancedstats?season=2025&team=OKC&page=1&pageSize=35&sortBy=defensiveBox&ascending=false&isPlayoff=true", + "raw": "{{base_url}}/api/playeradvancedstats?season=2025&team=HOU&page=1&pageSize=4&sortBy=defensiveBox&ascending=false&isPlayoff=true", "host": [ "{{base_url}}" ], @@ -1017,7 +2833,7 @@ }, { "key": "team", - "value": "OKC", + "value": "HOU", "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL)." }, { @@ -1027,7 +2843,7 @@ }, { "key": "pageSize", - "value": "35", + "value": "4", "description": "(Optional) The number of results to return per page. Defaults to 20." }, { @@ -1050,7 +2866,7 @@ }, "status": "OK", "code": 200, - "_postman_previewlanguage": "json", + "_postman_previewlanguage": null, "header": [ { "key": "Alt-Svc", @@ -1066,7 +2882,7 @@ }, { "key": "Date", - "value": "Wed, 02 Jul 2025 01:18:52 GMT" + "value": "Tue, 16 Dec 2025 07:38:58 GMT" }, { "key": "Server", @@ -1078,11 +2894,11 @@ }, { "key": "Content-Length", - "value": "1692" + "value": "611" } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"ID\": 2612,\n \"id\": 32,\n \"playerId\": \"carusal01\",\n \"playerName\": \"Alex Caruso\",\n \"position\": \"SG\",\n \"age\": 30,\n \"games\": 23,\n \"minutesPlayed\": 562,\n \"per\": 15.1,\n \"tsPercent\": 0.598,\n \"threePAR\": 0.563,\n \"ftr\": 0.244,\n \"offensiveRBPercent\": 3.3,\n \"defensiveRBPercent\": 8.8,\n \"totalRBPercent\": 6,\n \"assistPercent\": 12.6,\n \"stealPercent\": 3.9,\n \"blockPercent\": 2.3,\n \"turnoverPercent\": 9.7,\n \"usagePercent\": 14.8,\n \"offensiveWS\": 0.9,\n \"defensiveWS\": 1.1,\n \"winShares\": 2,\n \"winSharesPer\": 0.169,\n \"offensiveBox\": 0.4,\n \"defensiveBox\": 4.7,\n \"box\": 5,\n \"vorp\": 1,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:02:53.068472Z\",\n \"UpdatedAt\": \"2025-06-20T01:02:53.068472Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2794,\n \"id\": 214,\n \"playerId\": \"willija07\",\n \"playerName\": \"Jaylin Williams\",\n \"position\": \"PF\",\n \"age\": 22,\n \"games\": 17,\n \"minutesPlayed\": 141,\n \"per\": 9.7,\n \"tsPercent\": 0.565,\n \"threePAR\": 0.714,\n \"ftr\": 0.314,\n \"offensiveRBPercent\": 3.1,\n \"defensiveRBPercent\": 21.8,\n \"totalRBPercent\": 12.3,\n \"assistPercent\": 16.2,\n \"stealPercent\": 2.8,\n \"blockPercent\": 1.4,\n \"turnoverPercent\": 23.1,\n \"usagePercent\": 15.6,\n \"offensiveWS\": 0,\n \"defensiveWS\": 0.3,\n \"winShares\": 0.3,\n \"winSharesPer\": 0.091,\n \"offensiveBox\": -4,\n \"defensiveBox\": 4.4,\n \"box\": 0.4,\n \"vorp\": 0.1,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:19.343959Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:19.343959Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2683,\n \"id\": 103,\n \"playerId\": \"jonesdi01\",\n \"playerName\": \"Dillon Jones\",\n \"position\": \"SF\",\n \"age\": 23,\n \"games\": 10,\n \"minutesPlayed\": 46,\n \"per\": 19.2,\n \"tsPercent\": 0.968,\n \"threePAR\": 0.364,\n \"ftr\": 0.182,\n \"offensiveRBPercent\": 7,\n \"defensiveRBPercent\": 14.3,\n \"totalRBPercent\": 10.6,\n \"assistPercent\": 16.6,\n \"stealPercent\": 1.1,\n \"blockPercent\": 2.2,\n \"turnoverPercent\": 33.6,\n \"usagePercent\": 16.5,\n \"offensiveWS\": 0.1,\n \"defensiveWS\": 0.1,\n \"winShares\": 0.2,\n \"winSharesPer\": 0.179,\n \"offensiveBox\": 3.4,\n \"defensiveBox\": 4,\n \"box\": 7.5,\n \"vorp\": 0.1,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:03.218018Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:03.218018Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2784,\n \"id\": 204,\n \"playerId\": \"wallaca01\",\n \"playerName\": \"Cason Wallace\",\n \"position\": \"SG\",\n \"age\": 21,\n \"games\": 23,\n \"minutesPlayed\": 516,\n \"per\": 10.8,\n \"tsPercent\": 0.52,\n \"threePAR\": 0.521,\n \"ftr\": 0.076,\n \"offensiveRBPercent\": 4.8,\n \"defensiveRBPercent\": 8.1,\n \"totalRBPercent\": 6.4,\n \"assistPercent\": 12.4,\n \"stealPercent\": 3,\n \"blockPercent\": 1.9,\n \"turnoverPercent\": 11.5,\n \"usagePercent\": 11.4,\n \"offensiveWS\": 0.3,\n \"defensiveWS\": 0.8,\n \"winShares\": 1.2,\n \"winSharesPer\": 0.111,\n \"offensiveBox\": -1.7,\n \"defensiveBox\": 3.7,\n \"box\": 2,\n \"vorp\": 0.5,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:17.911668Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:17.911668Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2638,\n \"id\": 58,\n \"playerId\": \"gilgesh01\",\n \"playerName\": \"Shai Gilgeous-Alexander\",\n \"position\": \"PG\",\n \"age\": 26,\n \"games\": 23,\n \"minutesPlayed\": 851,\n \"per\": 25.3,\n \"tsPercent\": 0.574,\n \"threePAR\": 0.224,\n \"ftr\": 0.431,\n \"offensiveRBPercent\": 2.9,\n \"defensiveRBPercent\": 12.9,\n \"totalRBPercent\": 7.9,\n \"assistPercent\": 30.6,\n \"stealPercent\": 2.2,\n \"blockPercent\": 2.4,\n \"turnoverPercent\": 9.1,\n \"usagePercent\": 32.9,\n \"offensiveWS\": 2.6,\n \"defensiveWS\": 1.4,\n \"winShares\": 3.9,\n \"winSharesPer\": 0.222,\n \"offensiveBox\": 5.7,\n \"defensiveBox\": 2.6,\n \"box\": 8.3,\n \"vorp\": 2.2,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:02:56.768423Z\",\n \"UpdatedAt\": \"2025-06-20T01:02:56.768423Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2654,\n \"id\": 74,\n \"playerId\": \"harteis01\",\n \"playerName\": \"Isaiah Hartenstein\",\n \"position\": \"C\",\n \"age\": 26,\n \"games\": 23,\n \"minutesPlayed\": 516,\n \"per\": 18.3,\n \"tsPercent\": 0.632,\n \"threePAR\": 0,\n \"ftr\": 0.224,\n \"offensiveRBPercent\": 13.2,\n \"defensiveRBPercent\": 23.4,\n \"totalRBPercent\": 18.2,\n \"assistPercent\": 14.3,\n \"stealPercent\": 1.8,\n \"blockPercent\": 2.3,\n \"turnoverPercent\": 15.5,\n \"usagePercent\": 14.3,\n \"offensiveWS\": 1.1,\n \"defensiveWS\": 1,\n \"winShares\": 2.1,\n \"winSharesPer\": 0.199,\n \"offensiveBox\": 0.9,\n \"defensiveBox\": 2.6,\n \"box\": 3.5,\n \"vorp\": 0.7,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:02:59.067598Z\",\n \"UpdatedAt\": \"2025-06-20T01:02:59.067598Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2678,\n \"id\": 98,\n \"playerId\": \"joeis01\",\n \"playerName\": \"Isaiah Joe\",\n \"position\": \"SG\",\n \"age\": 25,\n \"games\": 21,\n \"minutesPlayed\": 211,\n \"per\": 17.4,\n \"tsPercent\": 0.676,\n \"threePAR\": 0.767,\n \"ftr\": 0.192,\n \"offensiveRBPercent\": 3.6,\n \"defensiveRBPercent\": 11.4,\n \"totalRBPercent\": 7.5,\n \"assistPercent\": 9.8,\n \"stealPercent\": 1.6,\n \"blockPercent\": 0.9,\n \"turnoverPercent\": 8.1,\n \"usagePercent\": 17.3,\n \"offensiveWS\": 0.6,\n \"defensiveWS\": 0.3,\n \"winShares\": 0.8,\n \"winSharesPer\": 0.192,\n \"offensiveBox\": 3.5,\n \"defensiveBox\": 2.1,\n \"box\": 5.6,\n \"vorp\": 0.4,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:02.486429Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:02.486429Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2793,\n \"id\": 213,\n \"playerId\": \"willija06\",\n \"playerName\": \"Jalen Williams\",\n \"position\": \"SG\",\n \"age\": 23,\n \"games\": 23,\n \"minutesPlayed\": 796,\n \"per\": 19.1,\n \"tsPercent\": 0.544,\n \"threePAR\": 0.29,\n \"ftr\": 0.323,\n \"offensiveRBPercent\": 3.2,\n \"defensiveRBPercent\": 14.2,\n \"totalRBPercent\": 8.7,\n \"assistPercent\": 22.3,\n \"stealPercent\": 2,\n \"blockPercent\": 1.1,\n \"turnoverPercent\": 8.3,\n \"usagePercent\": 26.3,\n \"offensiveWS\": 1.3,\n \"defensiveWS\": 1.2,\n \"winShares\": 2.5,\n \"winSharesPer\": 0.153,\n \"offensiveBox\": 2.5,\n \"defensiveBox\": 1.7,\n \"box\": 4.2,\n \"vorp\": 1.2,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:19.204511Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:19.204511Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2663,\n \"id\": 83,\n \"playerId\": \"holmgch01\",\n \"playerName\": \"Chet Holmgren\",\n \"position\": \"C\",\n \"age\": 22,\n \"games\": 23,\n \"minutesPlayed\": 686,\n \"per\": 18.1,\n \"tsPercent\": 0.565,\n \"threePAR\": 0.342,\n \"ftr\": 0.365,\n \"offensiveRBPercent\": 6.6,\n \"defensiveRBPercent\": 25.1,\n \"totalRBPercent\": 15.8,\n \"assistPercent\": 4.8,\n \"stealPercent\": 1.2,\n \"blockPercent\": 6.3,\n \"turnoverPercent\": 8.3,\n \"usagePercent\": 20.8,\n \"offensiveWS\": 0.9,\n \"defensiveWS\": 1.4,\n \"winShares\": 2.3,\n \"winSharesPer\": 0.161,\n \"offensiveBox\": 0.9,\n \"defensiveBox\": 1.5,\n \"box\": 2.4,\n \"vorp\": 0.8,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:00.356697Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:00.356697Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2627,\n \"id\": 47,\n \"playerId\": \"dortlu01\",\n \"playerName\": \"Luguentz Dort\",\n \"position\": \"SF\",\n \"age\": 25,\n \"games\": 23,\n \"minutesPlayed\": 666,\n \"per\": 8.1,\n \"tsPercent\": 0.524,\n \"threePAR\": 0.854,\n \"ftr\": 0.134,\n \"offensiveRBPercent\": 5.2,\n \"defensiveRBPercent\": 9.4,\n \"totalRBPercent\": 7.3,\n \"assistPercent\": 4,\n \"stealPercent\": 2.1,\n \"blockPercent\": 1.5,\n \"turnoverPercent\": 10.3,\n \"usagePercent\": 12.3,\n \"offensiveWS\": 0.2,\n \"defensiveWS\": 1,\n \"winShares\": 1.1,\n \"winSharesPer\": 0.081,\n \"offensiveBox\": -2.3,\n \"defensiveBox\": 1.4,\n \"box\": -0.9,\n \"vorp\": 0.2,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:02:55.202425Z\",\n \"UpdatedAt\": \"2025-06-20T01:02:55.202425Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2623,\n \"id\": 43,\n \"playerId\": \"diengou01\",\n \"playerName\": \"Ousmane Dieng\",\n \"position\": \"C\",\n \"age\": 21,\n \"games\": 9,\n \"minutesPlayed\": 32,\n \"per\": 16.2,\n \"tsPercent\": 0.643,\n \"threePAR\": 0.7,\n \"ftr\": 0.2,\n \"offensiveRBPercent\": 0,\n \"defensiveRBPercent\": 13.7,\n \"totalRBPercent\": 6.8,\n \"assistPercent\": 12.9,\n \"stealPercent\": 0,\n \"blockPercent\": 3.1,\n \"turnoverPercent\": 0,\n \"usagePercent\": 14.4,\n \"offensiveWS\": 0.1,\n \"defensiveWS\": 0,\n \"winShares\": 0.1,\n \"winSharesPer\": 0.202,\n \"offensiveBox\": 4.9,\n \"defensiveBox\": 1.3,\n \"box\": 6.3,\n \"vorp\": 0.1,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:02:54.622461Z\",\n \"UpdatedAt\": \"2025-06-20T01:02:54.622461Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2796,\n \"id\": 216,\n \"playerId\": \"willike04\",\n \"playerName\": \"Kenrich Williams\",\n \"position\": \"PF\",\n \"age\": 30,\n \"games\": 16,\n \"minutesPlayed\": 137,\n \"per\": 9.9,\n \"tsPercent\": 0.457,\n \"threePAR\": 0.5,\n \"ftr\": 0.15,\n \"offensiveRBPercent\": 6.3,\n \"defensiveRBPercent\": 21.6,\n \"totalRBPercent\": 13.9,\n \"assistPercent\": 7,\n \"stealPercent\": 2.5,\n \"blockPercent\": 0.7,\n \"turnoverPercent\": 14.1,\n \"usagePercent\": 15.4,\n \"offensiveWS\": -0.1,\n \"defensiveWS\": 0.3,\n \"winShares\": 0.1,\n \"winSharesPer\": 0.052,\n \"offensiveBox\": -2.6,\n \"defensiveBox\": 0.8,\n \"box\": -1.8,\n \"vorp\": 0,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:19.635894Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:19.635894Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2791,\n \"id\": 211,\n \"playerId\": \"wiggiaa01\",\n \"playerName\": \"Aaron Wiggins\",\n \"position\": \"SG\",\n \"age\": 26,\n \"games\": 22,\n \"minutesPlayed\": 303,\n \"per\": 11.8,\n \"tsPercent\": 0.522,\n \"threePAR\": 0.58,\n \"ftr\": 0.143,\n \"offensiveRBPercent\": 5,\n \"defensiveRBPercent\": 13,\n \"totalRBPercent\": 9,\n \"assistPercent\": 9.5,\n \"stealPercent\": 1.6,\n \"blockPercent\": 2,\n \"turnoverPercent\": 11.8,\n \"usagePercent\": 20.1,\n \"offensiveWS\": 0,\n \"defensiveWS\": 0.4,\n \"winShares\": 0.4,\n \"winSharesPer\": 0.071,\n \"offensiveBox\": -0.5,\n \"defensiveBox\": 0.6,\n \"box\": 0.1,\n \"vorp\": 0.2,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:18.910441Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:18.910441Z\",\n \"DeletedAt\": null\n },\n {\n \"ID\": 2715,\n \"id\": 135,\n \"playerId\": \"mitchaj01\",\n \"playerName\": \"Ajay Mitchell\",\n \"position\": \"SG\",\n \"age\": 22,\n \"games\": 12,\n \"minutesPlayed\": 84,\n \"per\": 12.2,\n \"tsPercent\": 0.551,\n \"threePAR\": 0.371,\n \"ftr\": 0.143,\n \"offensiveRBPercent\": 3.8,\n \"defensiveRBPercent\": 7.8,\n \"totalRBPercent\": 5.8,\n \"assistPercent\": 16.2,\n \"stealPercent\": 1.2,\n \"blockPercent\": 0,\n \"turnoverPercent\": 13.9,\n \"usagePercent\": 21.8,\n \"offensiveWS\": 0,\n \"defensiveWS\": 0.1,\n \"winShares\": 0.1,\n \"winSharesPer\": 0.067,\n \"offensiveBox\": -1.3,\n \"defensiveBox\": -0.1,\n \"box\": -1.4,\n \"vorp\": 0,\n \"team\": \"OKC\",\n \"season\": 2025,\n \"isPlayoff\": true,\n \"CreatedAt\": \"2025-06-20T01:03:07.867398Z\",\n \"UpdatedAt\": \"2025-06-20T01:03:07.867398Z\",\n \"DeletedAt\": null\n }\n ],\n \"pagination\": {\n \"total\": 14,\n \"page\": 1,\n \"pageSize\": 35,\n \"pages\": 1\n }\n}" + "body": "{\n \"data\": [\n {\n \"playerId\": \"sheppre01\",\n \"playerName\": \"Reed Sheppard\",\n \"position\": \"PG\",\n \"age\": 20,\n \"team\": \"HOU\",\n \"games\": 3,\n \"minutesPlayed\": 10,\n \"per\": 4.3,\n \"tsPercent\": 0,\n \"threePAR\": 1,\n \"ftr\": 0,\n \"offensiveRBPercent\": 0,\n \"defensiveRBPercent\": 10.9,\n \"totalRBPercent\": 5.6,\n \"assistPercent\": 13.1,\n \"stealPercent\": 10.3,\n \"blockPercent\": 11,\n \"turnoverPercent\": 33.3,\n \"usagePercent\": 13.3,\n \"offensiveWS\": -0.1,\n \"defensiveWS\": 0,\n \"winShares\": 0,\n \"winSharesPer\": -0.116,\n \"offensiveBox\": -7.8,\n \"defensiveBox\": 9.1,\n \"box\": 1.3,\n \"vorp\": 0,\n \"season\": 2025,\n \"isPlayoff\": true\n },\n {\n \"playerId\": \"easonta01\",\n \"playerName\": \"Tari Eason\",\n \"position\": \"PF\",\n \"age\": 23,\n \"team\": \"HOU\",\n \"games\": 7,\n \"minutesPlayed\": 132,\n \"per\": 14.7,\n \"tsPercent\": 0.558,\n \"threePAR\": 0.432,\n \"ftr\": 0.182,\n \"offensiveRBPercent\": 6,\n \"defensiveRBPercent\": 19.1,\n \"totalRBPercent\": 12.6,\n \"assistPercent\": 6.3,\n \"stealPercent\": 3.1,\n \"blockPercent\": 5.8,\n \"turnoverPercent\": 17.4,\n \"usagePercent\": 19.3,\n \"offensiveWS\": 0,\n \"defensiveWS\": 0.2,\n \"winShares\": 0.2,\n \"winSharesPer\": 0.078,\n \"offensiveBox\": -0.8,\n \"defensiveBox\": 3.1,\n \"box\": 2.3,\n \"vorp\": 0.1,\n \"season\": 2025,\n \"isPlayoff\": true\n },\n {\n \"playerId\": \"sengual01\",\n \"playerName\": \"Alperen Şengün\",\n \"position\": \"C\",\n \"age\": 22,\n \"team\": \"HOU\",\n \"games\": 7,\n \"minutesPlayed\": 256,\n \"per\": 20.8,\n \"tsPercent\": 0.491,\n \"threePAR\": 0.061,\n \"ftr\": 0.305,\n \"offensiveRBPercent\": 9.2,\n \"defensiveRBPercent\": 26.5,\n \"totalRBPercent\": 18,\n \"assistPercent\": 27,\n \"stealPercent\": 2.6,\n \"blockPercent\": 1.3,\n \"turnoverPercent\": 9.2,\n \"usagePercent\": 28.3,\n \"offensiveWS\": 0.3,\n \"defensiveWS\": 0.4,\n \"winShares\": 0.7,\n \"winSharesPer\": 0.139,\n \"offensiveBox\": 2.3,\n \"defensiveBox\": 2.4,\n \"box\": 4.7,\n \"vorp\": 0.4,\n \"season\": 2025,\n \"isPlayoff\": true\n },\n {\n \"playerId\": \"thompam01\",\n \"playerName\": \"Amen Thompson\",\n \"position\": \"SF\",\n \"age\": 22,\n \"team\": \"HOU\",\n \"games\": 7,\n \"minutesPlayed\": 231,\n \"per\": 19.3,\n \"tsPercent\": 0.545,\n \"threePAR\": 0.047,\n \"ftr\": 0.424,\n \"offensiveRBPercent\": 9.3,\n \"defensiveRBPercent\": 13.7,\n \"totalRBPercent\": 11.5,\n \"assistPercent\": 17.1,\n \"stealPercent\": 2.7,\n \"blockPercent\": 2.9,\n \"turnoverPercent\": 10.6,\n \"usagePercent\": 21.6,\n \"offensiveWS\": 0.4,\n \"defensiveWS\": 0.3,\n \"winShares\": 0.7,\n \"winSharesPer\": 0.148,\n \"offensiveBox\": 1.5,\n \"defensiveBox\": 2.2,\n \"box\": 3.7,\n \"vorp\": 0.3,\n \"season\": 2025,\n \"isPlayoff\": true\n }\n ],\n \"pagination\": {\n \"total\": 14,\n \"page\": 1,\n \"pageSize\": 4,\n \"pages\": 4\n }\n}" } ] }, @@ -1541,6 +3357,403 @@ "body": "[\n {\n \"id\": 4,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 17,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"4:12\",\n \"top\": 284,\n \"left\": 121,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": false,\n \"teamScore\": 18,\n \"opponentTeamScore\": 22,\n \"opponent\": \"NOP\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 12,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 17,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"6:18\",\n \"top\": 288,\n \"left\": 318,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 95,\n \"opponentTeamScore\": 113,\n \"opponent\": \"NOP\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 15,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 17,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"3:27\",\n \"top\": 284,\n \"left\": 343,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 102,\n \"opponentTeamScore\": 121,\n \"opponent\": \"NOP\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 17,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 20,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"7:48\",\n \"top\": 316,\n \"left\": 332,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": true,\n \"teamScore\": 14,\n \"opponentTeamScore\": 10,\n \"opponent\": \"LAL\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 23,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 20,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"6:25\",\n \"top\": 293,\n \"left\": 147,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": true,\n \"teamScore\": 47,\n \"opponentTeamScore\": 44,\n \"opponent\": \"LAL\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 28,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 20,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"0:45\",\n \"top\": 321,\n \"left\": 199,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 63,\n \"opponentTeamScore\": 62,\n \"opponent\": \"LAL\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 32,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 20,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"6:24\",\n \"top\": 253,\n \"left\": 409,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": true,\n \"teamScore\": 109,\n \"opponentTeamScore\": 104,\n \"opponent\": \"LAL\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 33,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 20,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"1:12\",\n \"top\": 270,\n \"left\": 404,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 120,\n \"opponentTeamScore\": 113,\n \"opponent\": \"LAL\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 43,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 21,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"6:11\",\n \"top\": 327,\n \"left\": 170,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": true,\n \"teamScore\": 42,\n \"opponentTeamScore\": 39,\n \"opponent\": \"LAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 47,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 21,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"1:44\",\n \"top\": 232,\n \"left\": 418,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 51,\n \"opponentTeamScore\": 50,\n \"opponent\": \"LAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 55,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 21,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"2:47\",\n \"top\": 241,\n \"left\": 407,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 106,\n \"opponentTeamScore\": 110,\n \"opponent\": \"LAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 59,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 21,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"0:29\",\n \"top\": 288,\n \"left\": 162,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 111,\n \"opponentTeamScore\": 115,\n \"opponent\": \"LAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 62,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 24,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"9:53\",\n \"top\": 271,\n \"left\": 395,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 7,\n \"opponentTeamScore\": 2,\n \"opponent\": \"UTA\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 64,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 24,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"0:51\",\n \"top\": 253,\n \"left\": 95,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 29,\n \"opponentTeamScore\": 24,\n \"opponent\": \"UTA\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 76,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Oct 24,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"5:50\",\n \"top\": 328,\n \"left\": 285,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": false,\n \"teamScore\": 52,\n \"opponentTeamScore\": 64,\n \"opponent\": \"UTA\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 84,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 3,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"3:34\",\n \"top\": 303,\n \"left\": 150,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": false,\n \"teamScore\": 47,\n \"opponentTeamScore\": 47,\n \"opponent\": \"CHI\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 85,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 3,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"2:52\",\n \"top\": 138,\n \"left\": 471,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 50,\n \"opponentTeamScore\": 47,\n \"opponent\": \"CHI\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 89,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 3,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"5:57\",\n \"top\": 313,\n \"left\": 238,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": true,\n \"teamScore\": 63,\n \"opponentTeamScore\": 59,\n \"opponent\": \"CHI\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 90,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 3,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"4:47\",\n \"top\": 307,\n \"left\": 323,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 66,\n \"opponentTeamScore\": 59,\n \"opponent\": \"CHI\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 91,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 3,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"3:59\",\n \"top\": 299,\n \"left\": 182,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 71,\n \"opponentTeamScore\": 59,\n \"opponent\": \"CHI\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 98,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 5,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"9:13\",\n \"top\": 321,\n \"left\": 262,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 11,\n \"opponentTeamScore\": 6,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 99,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 5,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"7:27\",\n \"top\": 282,\n \"left\": 104,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 16,\n \"opponentTeamScore\": 10,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 101,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 5,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"4:06\",\n \"top\": 78,\n \"left\": 477,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 24,\n \"lead\": true,\n \"teamScore\": 24,\n \"opponentTeamScore\": 18,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 106,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 5,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"0:09\",\n \"top\": 328,\n \"left\": 309,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": false,\n \"teamScore\": 53,\n \"opponentTeamScore\": 55,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 111,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 5,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"0:36\",\n \"top\": 267,\n \"left\": 77,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 93,\n \"opponentTeamScore\": 90,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 114,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 8,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"6:32\",\n \"top\": 252,\n \"left\": 390,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 12,\n \"opponentTeamScore\": 15,\n \"opponent\": \"OKC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 120,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 8,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"3:14\",\n \"top\": 292,\n \"left\": 337,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": false,\n \"teamScore\": 43,\n \"opponentTeamScore\": 47,\n \"opponent\": \"OKC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 123,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 8,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"7:03\",\n \"top\": 202,\n \"left\": 445,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 55,\n \"opponentTeamScore\": 66,\n \"opponent\": \"OKC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 125,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 8,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"8:24\",\n \"top\": 287,\n \"left\": 331,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": false,\n \"teamScore\": 67,\n \"opponentTeamScore\": 86,\n \"opponent\": \"OKC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 140,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 10,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"1:35\",\n \"top\": 313,\n \"left\": 234,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": true,\n \"teamScore\": 48,\n \"opponentTeamScore\": 47,\n \"opponent\": \"SAS\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 160,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"5:13\",\n \"top\": 277,\n \"left\": 88,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 20,\n \"opponentTeamScore\": 16,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 163,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"6:26\",\n \"top\": 305,\n \"left\": 151,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 49,\n \"opponentTeamScore\": 39,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 164,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"5:00\",\n \"top\": 289,\n \"left\": 120,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 55,\n \"opponentTeamScore\": 44,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 165,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"2:29\",\n \"top\": 297,\n \"left\": 348,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 67,\n \"opponentTeamScore\": 50,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 166,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"2:07\",\n \"top\": 344,\n \"left\": 238,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 29,\n \"lead\": true,\n \"teamScore\": 70,\n \"opponentTeamScore\": 50,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 170,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"4:27\",\n \"top\": 289,\n \"left\": 105,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 87,\n \"opponentTeamScore\": 74,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 172,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"3:35\",\n \"top\": 310,\n \"left\": 132,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": true,\n \"teamScore\": 91,\n \"opponentTeamScore\": 75,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 174,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 11,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"7:04\",\n \"top\": 313,\n \"left\": 298,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 107,\n \"opponentTeamScore\": 92,\n \"opponent\": \"IND\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 186,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 13,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"3:40\",\n \"top\": 277,\n \"left\": 348,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 79,\n \"opponentTeamScore\": 74,\n \"opponent\": \"DEN\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 190,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 13,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"4:50\",\n \"top\": 248,\n \"left\": 397,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 102,\n \"opponentTeamScore\": 91,\n \"opponent\": \"DEN\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 199,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 15,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"2:50\",\n \"top\": 264,\n \"left\": 376,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 16,\n \"opponentTeamScore\": 15,\n \"opponent\": \"GSW\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 208,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 15,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"0:29\",\n \"top\": 330,\n \"left\": 204,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": true,\n \"teamScore\": 47,\n \"opponentTeamScore\": 39,\n \"opponent\": \"GSW\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 210,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 15,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"11:37\",\n \"top\": 274,\n \"left\": 64,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 28,\n \"lead\": true,\n \"teamScore\": 50,\n \"opponentTeamScore\": 41,\n \"opponent\": \"GSW\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 213,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 15,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"5:30\",\n \"top\": 231,\n \"left\": 38,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 63,\n \"opponentTeamScore\": 47,\n \"opponent\": \"GSW\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 227,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 17,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"7:44\",\n \"top\": 313,\n \"left\": 213,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": true,\n \"teamScore\": 83,\n \"opponentTeamScore\": 69,\n \"opponent\": \"SAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 229,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 17,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"4:24\",\n \"top\": 313,\n \"left\": 299,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 95,\n \"opponentTeamScore\": 74,\n \"opponent\": \"SAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 230,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 17,2018\",\n \"qtr\": \"3rd Qtr\",\n \"timeRemaining\": \"4:06\",\n \"top\": 295,\n \"left\": 369,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 27,\n \"lead\": true,\n \"teamScore\": 98,\n \"opponentTeamScore\": 74,\n \"opponent\": \"SAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 233,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 17,2018\",\n \"qtr\": \"4th Qtr\",\n \"timeRemaining\": \"3:46\",\n \"top\": 154,\n \"left\": 7,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 126,\n \"opponentTeamScore\": 103,\n \"opponent\": \"SAC\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 238,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 21,2018\",\n \"qtr\": \"1st Qtr\",\n \"timeRemaining\": \"4:40\",\n \"top\": 261,\n \"left\": 384,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 25,\n \"lead\": true,\n \"teamScore\": 15,\n \"opponentTeamScore\": 14,\n \"opponent\": \"DET\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n },\n {\n \"id\": 241,\n \"playerId\": \"hardeja01\",\n \"season\": 2019,\n \"date\": \"Nov 21,2018\",\n \"qtr\": \"2nd Qtr\",\n \"timeRemaining\": \"6:38\",\n \"top\": 243,\n \"left\": 415,\n \"playerName\": \"hardeja01\",\n \"result\": true,\n \"shotType\": \"3-pointer\",\n \"distanceFt\": 26,\n \"lead\": true,\n \"teamScore\": 45,\n \"opponentTeamScore\": 44,\n \"opponent\": \"DET\",\n \"team\": \"HOU\",\n \"ID\": 0,\n \"CreatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"UpdatedAt\": \"2025-06-20T22:48:34.764255Z\",\n \"DeletedAt\": null\n }\n]" } ] + }, + { + "name": "Player Advanced Playoff Stats", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Tests", + "pm.test(\"Response time is less than 200ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(200);", + "});", + "", + "pm.test(\"Response status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response has data array with at least one element\", function () {", + " const jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('data');", + " pm.expect(jsonData.data).to.be.an('array').that.is.not.empty;", + "});", + "", + "pm.test(\"Validate the schema of the objects in the array\", function () {", + " const jsonData = pm.response.json();", + " jsonData.data.forEach(function(item) {", + " pm.expect(item).to.have.property('playerId');", + " pm.expect(item).to.have.property('playerName');", + " pm.expect(item).to.have.property('position');", + " pm.expect(item).to.have.property('defensiveBox');", + " pm.expect(item).to.have.property('offensiveBox');", + " pm.expect(item).to.have.property('winShares');", + " });", + "});", + "", + "pm.test(\"Player ID is a non-empty string\", function () {", + " const jsonData = pm.response.json();", + " jsonData.data.forEach(function(item) {", + " pm.expect(item.playerId).to.be.a('string').that.is.not.empty;", + " });", + "});", + "", + "pm.test(\"Season is a positive integer\", function () {", + " const jsonData = pm.response.json();", + " jsonData.data.forEach(function(item) {", + " pm.expect(item.season).to.be.a('number').that.is.above(0);", + " });", + "});", + "", + "// Player Advanced Stats Chart Visualization", + "var template = `", + "", + "", + "
", + "

Player Advanced Stats Comparison

", + "

{{team}} - {{season}} {{playoffLabel}}

", + " ", + "
", + "
", + "
{{totalPlayers}}
", + "
Players
", + "
", + "
", + "
{{avgWinShares}}
", + "
Avg Win Shares
", + "
", + "
", + "
{{avgBox}}
", + "
Avg Box +/-
", + "
", + "
", + "
{{topPlayer}}
", + "
Top Performer
", + "
", + "
", + " ", + "
", + " ", + "
", + " ", + "
", + " ", + "
", + " ", + "

Data sorted by Defensive Box +/- (descending)

", + "
", + "", + "", + "", + "`;", + "", + "function constructVisualizerPayload() {", + " var response = pm.response.json();", + " var data = response.data || [];", + " ", + " var players = data.map(function(player) {", + " return {", + " name: player.playerName,", + " defensiveBox: player.defensiveBox,", + " offensiveBox: player.offensiveBox,", + " box: player.box,", + " winShares: player.winShares,", + " vorp: player.vorp", + " };", + " });", + " ", + " var totalWinShares = data.reduce(function(sum, p) { return sum + p.winShares; }, 0);", + " var totalBox = data.reduce(function(sum, p) { return sum + p.box; }, 0);", + " var avgWinShares = data.length > 0 ? (totalWinShares / data.length).toFixed(2) : \"0\";", + " var avgBox = data.length > 0 ? (totalBox / data.length).toFixed(1) : \"0\";", + " ", + " var topPlayer = data.length > 0 ? data.reduce(function(top, p) {", + " return p.box > top.box ? p : top;", + " }, data[0]).playerName : \"N/A\";", + " ", + " var team = data.length > 0 ? data[0].team : \"N/A\";", + " var season = data.length > 0 ? data[0].season : \"N/A\";", + " var isPlayoff = data.length > 0 && data[0].isPlayoff;", + " ", + " return {", + " players: players,", + " totalPlayers: data.length,", + " avgWinShares: avgWinShares,", + " avgBox: avgBox,", + " topPlayer: topPlayer,", + " team: team,", + " season: season,", + " playoffLabel: isPlayoff ? \"Playoffs\" : \"Regular Season\"", + " };", + "}", + "", + "pm.visualizer.set(template, constructVisualizerPayload());" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {}, + "requests": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [ + { + "key": "x-api-key", + "value": "{{api-key}}", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "{{base_url}}/api/playeradvancedstats?season=2025&team=NYK&page=1&pageSize=4&sortBy=defensiveBox&ascending=false&isPlayoff=true", + "host": [ + "{{base_url}}" + ], + "path": [ + "api", + "playeradvancedstats" + ], + "query": [ + { + "key": "season", + "value": "2025", + "description": "(Optional) The NBA season year (e.g., 2025 for the 2024-25 season)." + }, + { + "key": "team", + "value": "NYK", + "description": "(Optional) The three-letter team abbreviation (e.g., LAL, HOU, MIL)." + }, + { + "key": "page", + "value": "1", + "description": "(Optional) The page number for pagination. Defaults to 1." + }, + { + "key": "pageSize", + "value": "4", + "description": "(Optional) The number of results to return per page. Defaults to 20." + }, + { + "key": "sortBy", + "value": "defensiveBox", + "description": "(Optional) The field to sort the results by. Defaults to 'winShares'." + }, + { + "key": "ascending", + "value": "false", + "description": "(Optional) If true, sorts the results in ascending order. Defaults to false (descending)." + }, + { + "key": "isPlayoff", + "value": "true", + "description": "(Optional) Set to 'true' to retrieve playoff stats, or 'false' for regular season stats." + } + ] + } + }, + "response": [] } ], "event": [ @@ -1591,6 +3804,10 @@ "key": "base_url_2", "value": "https://nbago.server.nbaapi.com", "type": "string" + }, + { + "key": "season", + "value": "2019" } ] } \ No newline at end of file diff --git a/docs/postman/performance/NBA-Statistics-Go-performance-report-15.html b/docs/postman/performance/NBA-Statistics-Go-performance-report-15.html new file mode 100644 index 0000000..0873e15 --- /dev/null +++ b/docs/postman/performance/NBA-Statistics-Go-performance-report-15.html @@ -0,0 +1,1122 @@ + + + + Performance test report - 1f0daf04-fc14-4dc0-9155-2bf370cc976d : 15 + + + + + + + + + + + + + + + + + + + +
+
+
+
+

+ - + + (#15) +

+
+ +
+
+
+ Postman collection: + NBA Statistics Go +
+
+ Report exported on: + +
+
+
+ +
+

Test setup

+
+
+
+
Virtual users
+
45 VU
+
+
+ Duration + + 10 minutes + +
+
+
+
+
Start time
+
+
+
+
End time
+
+
+
+
+
+
Load profile
+
Ramp up (4 minutes 50 seconds)
+
+
+
Environment
+
-
+
+
+
+
+

1. Summary

+ +
+
+ + 50,826 +
+
+ + 83.78 requests/second +
+
+ + + 276 ms + +
+
+ + + 0.00 % + +
+
+ +
+

1.1 Response time

+ Response time trends during the test duration. +
+
+ +
+
+ + +
+

1.2 Throughput

+ Rate of requests sent per second during the test duration. +
+
+ +
+
+ + +
+
+

1.3 Requests with slowest response times

+ Top 5 slowest requests based on their average response times. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RequestResp. time (Avg ms)90th (ms)95th (ms)99th (ms)Min (ms)Max (ms)
+
+ GET + Games Detail +
+ +
https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=3&sortBy=date&ascending=false&include=lineScores%2C%20playerGameBasicStats
+
5331,2151,4892,637579,117
+
+ GET + Games +
+ +
https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=3&sortBy=date&ascending=false
+
3988771,1061,919498,940
+
+ GET + Player Totals Stats +
+ +
{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=12&isPlayoff=False
+
2696688551,535488,321
+
+ GET + Player Totals Stats +
+ +
{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=20&isPlayoff=False
+
2686758501,285488,278
+
+ GET + Player Totals Playoffs Stats +
+ +
{{base_url}}/api/playertotals?team=HOU&page=1&pageSize=10&sortBy=assists&isPlayoff=true&season=2019
+
2666438561,429488,715
+
+ + + +
+
+

2. Metrics for each request

+ The requests are shown in the order they were sent by virtual users. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RequestTotal requestsRequests/sMin (ms)Avg (ms)90th (ms)Max (ms)Error %
+
+ GET + Games +
+
https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=3&sortBy=date&ascending=false
+
4,2497.00493988778,9400
+
+ GET + Games Copy +
+
https://api.server.nbaapi.com/api/games?isPlayoff=true&page=1&pageSize=15&sortBy=date&ascending=true
+
4,2487.00441975188,1190
+
+ GET + Games Detail +
+
https://api.server.nbaapi.com/api/games?isPlayoff=false&page=1&pageSize=3&sortBy=date&ascending=false&include=lineScores%2C%20playerGameBasicStats
+
4,2426.99575331,2159,1170
+
+ GET + Player Totals Stats +
+
{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=12&isPlayoff=False
+
4,2406.99482696688,3210
+
+ GET + Player Totals Playoffs Stats +
+
{{base_url}}/api/playertotals?team=HOU&page=1&pageSize=10&sortBy=assists&isPlayoff=true&season=2019
+
4,2396.99482666438,7150
+
+ GET + Player Advanced Stats +
+
{{base_url}}/api/playeradvancedstats?season=2026&team=HOU&page=1&pageSize=4&ascending=false&isPlayoff=false
+
4,2386.99462606692,7420
+
+ GET + Player Advanced Stats Copy +
+
{{base_url}}/api/playeradvancedstats?season=2025&team=HOU&page=1&pageSize=3&ascending=false&isPlayoff=true
+
4,2346.98472636708,4920
+
+ GET + Player Advanced Playoff Stats +
+
{{base_url}}/api/playeradvancedstats?season=2025&team=BOS&page=1&pageSize=4&sortBy=winShares&ascending=false&isPlayoff=true
+
4,2336.98482486443,4540
+
+ GET + Shot Chart +
+
{{base_url}}/api/playershotchart?page=1&playerId=duranke01&date=Dec%2017%2C2018
+
4,2326.98451884778,4000
+
+ GET + Shot Chart 2 +
+
{{base_url}}/api/playershotchart?page=1&playerId={{shot_player}}&season=2018&result=true&shot_type=3-pointer
+
4,2286.97441554153,3010
+
+ GET + Player Advanced Stats +
+
{{base_url}}/api/playeradvancedstats?season=2025&team=NYK&page=1&pageSize=4&sortBy=vorp&ascending=false&isPlayoff=true
+
4,2226.96472616488,5370
+
+ GET + Player Totals Stats +
+
{{base_url}}/api/playertotals?season=2026&team=HOU&page=1&pageSize=20&isPlayoff=False
+
4,2216.96482686758,2780
+
+ +
+

3. Errors

+
+

This run has no errors

+ All requests were sent successfully and returned a 2xx response code. +
+
+ +
+
+ +
+
+

Testing API performance on Postman

+
+ Postman enables you to simulate user traffic and observe how your API behaves under load. It also helps you identify any issues or bottlenecks that affect performance. +
+ Learn more about + + testing API performance. + +
+
+ + + + +
+ + diff --git a/docs/postman/performance/restore_dump_remote.md b/docs/postman/performance/restore_dump_remote.md new file mode 100644 index 0000000..00139b4 Binary files /dev/null and b/docs/postman/performance/restore_dump_remote.md differ diff --git a/docs/postman/postman_docs.md b/docs/postman/postman_docs.md new file mode 100644 index 0000000..6ebacb2 --- /dev/null +++ b/docs/postman/postman_docs.md @@ -0,0 +1,24 @@ +# Run Collection Button Code + +## HTML + +```html +
+ +``` + +## Markdown + +[Run In Postman](https://god.gw.postman.com/run-collection/25652688-f0cb3c13-063b-490a-aa7f-5af135aacbe6?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D25652688-f0cb3c13-063b-490a-aa7f-5af135aacbe6%26entityType%3Dcollection%26workspaceId%3Dbb6fcb02-8388-4ce0-8623-63480a6dc153) diff --git a/docs/restore_dump_local.md b/docs/restore_dump_local.md new file mode 100644 index 0000000..481de39 --- /dev/null +++ b/docs/restore_dump_local.md @@ -0,0 +1,13 @@ +# Restore to local container + +```bash +docker exec nba_go-postgres-1 pg_dump -U nbago -Fc nba_db > ./2025.12.05_nba_backup.dump +``` + +Copy file into target DB container + +```bash +docker exec nba_postgres psql -U nba_admin -d nba_analytics -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" + +pg_restore -U nba_admin -d nba_analytics --no-owner --no-acl ./2025.12.05_nba_backup.dump +``` diff --git a/import.go b/import.go index 5ff1a3d..63c19a2 100644 --- a/import.go +++ b/import.go @@ -3,32 +3,33 @@ package main import ( "log" "time" + "fmt" "github.com/nprasad2077/NBA_Go/services" "github.com/nprasad2077/NBA_Go/utils" "gorm.io/gorm" ) -// importPlayerAdvanced fetches and stores advanced stats for seasons 2017–2025 +// importPlayerAdvanced fetches and stores advanced stats for seasons func importPlayerAdvanced(db *gorm.DB) { for season := 2026; season <= 2026; season++ { if err := services.FetchAndStorePlayerAdvancedScrapedStats(db, season, false); err != nil { log.Printf("advanced import failed for %d: %v", season, err) } log.Printf("Advanced import for season: %d", season) - time.Sleep(1100 * time.Millisecond) + time.Sleep(1300 * time.Millisecond) utils.SleepWithJitter(1000 * time.Millisecond) } } -// importPlayerAdvancedPlayoffs fetches and stores advanced stats for playoffs seasons 2023–2025 +// importPlayerAdvancedPlayoffs fetches and stores advanced stats for playoffs seasons func importPlayerAdvancedPlayoffs(db *gorm.DB) { for season := 2026; season <= 2026; season++ { if err := services.FetchAndStorePlayerAdvancedScrapedStats(db, season, true); err != nil { log.Printf("advanced import failed for %d: %v", season, err) } log.Printf("Advanced Playoffs import for season: %d", season) - time.Sleep(1100 * time.Millisecond) + time.Sleep(1300 * time.Millisecond) utils.SleepWithJitter(1500 * time.Millisecond) } } @@ -40,7 +41,7 @@ func importPlayerTotalsScrape(db *gorm.DB) { log.Printf("scraped totals import failed for %d: %v", season, err) } log.Printf("Player Totals import for season: %d", season) - time.Sleep(1100 * time.Millisecond) + time.Sleep(1300 * time.Millisecond) utils.SleepWithJitter(1250 * time.Millisecond) } } @@ -52,7 +53,7 @@ func importPlayerTotalsPlayoffsScrape(db *gorm.DB) { log.Printf("scraped playoffs import failed for %d: %v", season, err) } log.Printf("Player Playoffs Totals import for season: %d", season) - time.Sleep(1100 * time.Millisecond) + time.Sleep(1300 * time.Millisecond) utils.SleepWithJitter(1700 * time.Millisecond) } } @@ -61,12 +62,11 @@ func importPlayerTotalsPlayoffsScrape(db *gorm.DB) { func importGameSchedules(db *gorm.DB) { // An NBA season typically runs from October to June months := []string{ - // "october", "november", "december", "january", + // "september", "october", "november", "december", "january", // "february", "march", "april", "may", "june", - - "february", - + "january", "february", // "february", "march", "april", "may", "june", + // "october", "november", "december", } for season := 2025; season <= 2026; season++ { @@ -79,7 +79,7 @@ func importGameSchedules(db *gorm.DB) { } log.Printf("Game schedule import for %s, %d complete.", month, season) // Respectful delay between requests - time.Sleep(1100 * time.Millisecond) + time.Sleep(1400 * time.Millisecond) utils.SleepWithJitter(1800 * time.Millisecond) } log.Printf("--- Finished Game Schedule Import for Season: %d ---", season) @@ -89,20 +89,27 @@ func importGameSchedules(db *gorm.DB) { // importBoxScores fetches and stores all box score data (line scores, player/team stats) // for games within a recent date range. func importBoxScores(db *gorm.DB) { - // Define the date range for the 2023-2024 NBA season. - // The regular season typically starts in October and playoffs end in June. - from := time.Date(2026, time.February, 1, 0, 0, 0, 0, time.UTC) - to := time.Date(2026, time.February, 10, 0, 0, 0, 0, time.UTC) + // now := time.Now() - log.Printf("--- Starting Box Score Data Import for the 2023-2024 Season ---") + from := time.Date(2026, time.January, 27, 0, 0, 0, 0, time.UTC) + // from := time.Date(now.Year(), now.Month(), now.Day()-1, 5, 30, 0, 0, time.UTC) + to := time.Date(2026, time.February, 28, 5, 30, 0, 0, time.UTC) + + dateRangeComment := fmt.Sprintf("--- Starting Box Score Data Import for games between %s and %s ---", + from.Format("January 2, 2006"), + to.Format("January 2, 2006")) + + log.Println(dateRangeComment) if err := services.FetchAndStoreBoxScoreDataForDateRange(db, from, to); err != nil { log.Fatalf("Box score import failed: %v", err) } - log.Printf("--- Finished Box Score Data Import ---") + log.Println("--- Finished Box Score Data Import ---") } + + // importPlayerShotCharts fetches shot charts for a PREDEFINED list of players for a given range of seasons. func importPlayerShotCharts(db *gorm.DB) { log.Println("--- Starting Player Shot Chart Import from Predefined List ---") @@ -126,14 +133,22 @@ func importPlayerShotCharts(db *gorm.DB) { "hardeja01", "irvinky01", "duranke01", - // "youngtr01", + "youngtr01", // "lillada01", - // "gilgesh01", - // "brunsja01", - // "edwaran01", + "gilgesh01", + "brunsja01", + "edwaran01", // "mitchdo01", // "bookede01", - // "derozde01", + "derozde01", + // "aldrila01", + "westbru01", + // "paulch01", + "butleji01", + "davisan02", + "leonaka01", + // "youngtr01", + "tatumja01", // Add more player IDs here as needed } @@ -160,4 +175,4 @@ func importPlayerShotCharts(db *gorm.DB) { } log.Println("--- Finished Player Shot Chart Import from Predefined List ---") -} \ No newline at end of file +} diff --git a/main.go b/main.go index 2e5c4da..646c148 100644 --- a/main.go +++ b/main.go @@ -39,9 +39,9 @@ import ( "github.com/nprasad2077/NBA_Go/config" "github.com/nprasad2077/NBA_Go/controllers" + _"github.com/nprasad2077/NBA_Go/docs" "github.com/nprasad2077/NBA_Go/routes" "github.com/nprasad2077/NBA_Go/utils/middleware" - _ "github.com/nprasad2077/NBA_Go/docs" ) func main() { @@ -53,8 +53,8 @@ func main() { importPlayerAdvanced(db) log.Println("πŸŽ‰ Player Advanced Import completed successfully") - // importPlayerAdvancedPlayoffs(db) - // log.Println("πŸŽ‰ Player Advanced Playoffs Import completed successfully") + // // importPlayerAdvancedPlayoffs(db) + // // log.Println("πŸŽ‰ Player Advanced Playoffs Import completed successfully") importPlayerTotalsScrape(db) log.Println("πŸŽ‰ Player Totals (scraped) Import completed successfully") @@ -71,7 +71,6 @@ func main() { // importPlayerShotCharts(db) // log.Println("πŸŽ‰ Player Shot Chart Import completed successfully 🎯") - log.Println("πŸ€ ALL Imports completed successfully βœ… πŸ™Œ") return } @@ -132,4 +131,4 @@ func main() { log.Println("shutting down…") _ = app.Shutdown() log.Println("bye") -} \ No newline at end of file +} diff --git a/services/box_score_scrape_service.go b/services/box_score_scrape_service.go index 67be818..2a453fd 100644 --- a/services/box_score_scrape_service.go +++ b/services/box_score_scrape_service.go @@ -16,7 +16,8 @@ import ( ) const boxScoreURLBase = "https://www.basketball-reference.com" -const numWorkers = 5 // Number of concurrent scrapers. Adjust based on your machine and network. +const numWorkers = 2 // Number of concurrent scrapers. Adjust based on your machine and network. +const baseDelay = 2500 * time.Millisecond // ScrapedResult holds all the parsed stats from a single game. type ScrapedResult struct { @@ -119,11 +120,23 @@ func FetchAndStoreBoxScoreDataForDateRange(db *gorm.DB, from, to time.Time) erro // scrapeAndParseWorker is a worker goroutine that receives games, scrapes them, and sends back the result. func scrapeAndParseWorker(id int, jobs <-chan models.Game, results chan<- ScrapedResult, wg *sync.WaitGroup) { defer wg.Done() + + // --- Stagger the start of each worker --- + // Calculate an offset based on the worker's ID to spread out the initial requests. + // We divide the base delay by the number of workers to get an even interval. + if numWorkers > 1 { + staggerAmount := time.Duration(int64(baseDelay) / int64(numWorkers)) + initialDelay := time.Duration(id-1) * staggerAmount + log.Printf("Worker %d: Staggering start with an initial delay of %v", id, initialDelay) + time.Sleep(initialDelay) + } + for game := range jobs { - log.Printf("Worker %d: Processing game %s", id, game.GameID) + log.Printf("🐝 Worker %d: Processing game %s", id, game.GameID) fullURL := boxScoreURLBase + game.BoxScoreURL - utils.SleepWithJitter(2300 * time.Millisecond) + utils.SleepWithJitter(baseDelay) + time.Sleep(1500 * time.Millisecond) req, err := http.NewRequest("GET", fullURL, nil) if err != nil { @@ -226,9 +239,9 @@ func parseLineScore(doc *goquery.Document, gameID string) []models.LineScore { Q2: mustAtoi(row.Find(`td[data-stat="2"]`).Text()), Q3: mustAtoi(row.Find(`td[data-stat="3"]`).Text()), Q4: mustAtoi(row.Find(`td[data-stat="4"]`).Text()), - OT1: mustAtoi(row.Find(`td[data-stat="OT1"]`).Text()), - OT2: mustAtoi(row.Find(`td[data-stat="OT2"]`).Text()), - OT3: mustAtoi(row.Find(`td[data-stat="OT3"]`).Text()), + OT1: mustAtoi(row.Find(`td[data-stat="1OT"]`).Text()), + OT2: mustAtoi(row.Find(`td[data-stat="2OT"]`).Text()), + OT3: mustAtoi(row.Find(`td[data-stat="3OT"]`).Text()), Total: mustAtoi(row.Find(`td[data-stat="T"]`).Text()), }) }) @@ -332,38 +345,81 @@ func parseTeamAdvStat(row *goquery.Selection, gameID, team string) models.TeamGa } } + func batchUpsertAll(db *gorm.DB, pbs []models.PlayerGameBasicStat, pas []models.PlayerGameAdvStat, tbs []models.TeamGameBasicStat, tas []models.TeamGameAdvStat) error { + const batchSize = 500 // πŸ’‘ A safe chunk size to stay under the limit. + + // Batch upsert Player Basic Stats if len(pbs) > 0 { - if err := db.Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "game_id"}, {Name: "player_id"}}, - DoUpdates: clause.AssignmentColumns(getModelColumns(&models.PlayerGameBasicStat{})), - }).Create(&pbs).Error; err != nil { - return fmt.Errorf("failed to upsert player basic stats: %w", err) + for i := 0; i < len(pbs); i += batchSize { + end := i + batchSize + if end > len(pbs) { + end = len(pbs) + } + batch := pbs[i:end] + if err := db.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "game_id"}, {Name: "player_id"}}, + DoUpdates: clause.AssignmentColumns(getModelColumns(&models.PlayerGameBasicStat{})), + }).Create(&batch).Error; err != nil { + return fmt.Errorf("failed to upsert player basic stats batch: %w", err) + } } + log.Printf("Successfully upserted %d player basic stats.", len(pbs)) } + + // Batch upsert Player Advanced Stats if len(pas) > 0 { - if err := db.Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "game_id"}, {Name: "player_id"}}, - DoUpdates: clause.AssignmentColumns(getModelColumns(&models.PlayerGameAdvStat{})), - }).Create(&pas).Error; err != nil { - return fmt.Errorf("failed to upsert player advanced stats: %w", err) + for i := 0; i < len(pas); i += batchSize { + end := i + batchSize + if end > len(pas) { + end = len(pas) + } + batch := pas[i:end] + if err := db.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "game_id"}, {Name: "player_id"}}, + DoUpdates: clause.AssignmentColumns(getModelColumns(&models.PlayerGameAdvStat{})), + }).Create(&batch).Error; err != nil { + return fmt.Errorf("failed to upsert player advanced stats batch: %w", err) + } } + log.Printf("Successfully upserted %d player advanced stats.", len(pas)) } + + // Batch upsert Team Basic Stats if len(tbs) > 0 { - if err := db.Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "game_id"}, {Name: "team"}}, - DoUpdates: clause.AssignmentColumns(getModelColumns(&models.TeamGameBasicStat{})), - }).Create(&tbs).Error; err != nil { - return fmt.Errorf("failed to upsert team basic stats: %w", err) + for i := 0; i < len(tbs); i += batchSize { + end := i + batchSize + if end > len(tbs) { + end = len(tbs) + } + batch := tbs[i:end] + if err := db.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "game_id"}, {Name: "team"}}, + DoUpdates: clause.AssignmentColumns(getModelColumns(&models.TeamGameBasicStat{})), + }).Create(&batch).Error; err != nil { + return fmt.Errorf("failed to upsert team basic stats batch: %w", err) + } } + log.Printf("Successfully upserted %d team basic stats.", len(tbs)) } + + // Batch upsert Team Advanced Stats if len(tas) > 0 { - if err := db.Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "game_id"}, {Name: "team"}}, - DoUpdates: clause.AssignmentColumns(getModelColumns(&models.TeamGameAdvStat{})), - }).Create(&tas).Error; err != nil { - return fmt.Errorf("failed to upsert team advanced stats: %w", err) + for i := 0; i < len(tas); i += batchSize { + end := i + batchSize + if end > len(tas) { + end = len(tas) + } + batch := tas[i:end] + if err := db.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "game_id"}, {Name: "team"}}, + DoUpdates: clause.AssignmentColumns(getModelColumns(&models.TeamGameAdvStat{})), + }).Create(&batch).Error; err != nil { + return fmt.Errorf("failed to upsert team advanced stats batch: %w", err) + } } + log.Printf("Successfully upserted %d team advanced stats.", len(tas)) } + return nil } \ No newline at end of file diff --git a/services/line_score_scrape_service.go b/services/line_score_scrape_service.go index 7f6f4a4..0d5b35c 100644 --- a/services/line_score_scrape_service.go +++ b/services/line_score_scrape_service.go @@ -25,14 +25,22 @@ func FetchAndStoreLineScore(db *gorm.DB, doc *goquery.Document, gameID string) e GameID: gameID, Team: teamName, } + + // Regular Quarters - no changes here ls.Q1 = mustAtoi(row.Find(`td[data-stat="1"]`).Text()) ls.Q2 = mustAtoi(row.Find(`td[data-stat="2"]`).Text()) ls.Q3 = mustAtoi(row.Find(`td[data-stat="3"]`).Text()) ls.Q4 = mustAtoi(row.Find(`td[data-stat="4"]`).Text()) - ls.OT1 = mustAtoi(row.Find(`td[data-stat="OT1"]`).Text()) - ls.OT2 = mustAtoi(row.Find(`td[data-stat="OT2"]`).Text()) - ls.OT3 = mustAtoi(row.Find(`td[data-stat="OT3"]`).Text()) + + // --- FIX: Corrected selectors for Overtime periods --- + // The HTML uses "1OT", "2OT", etc., not "OT1", "OT2". + ls.OT1 = mustAtoi(row.Find(`td[data-stat="1OT"]`).Text()) + ls.OT2 = mustAtoi(row.Find(`td[data-stat="2OT"]`).Text()) + ls.OT3 = mustAtoi(row.Find(`td[data-stat="3OT"]`).Text()) + + // Total score ls.Total = mustAtoi(row.Find(`td[data-stat="T"]`).Text()) + lineScores = append(lineScores, ls) }) @@ -42,13 +50,20 @@ func FetchAndStoreLineScore(db *gorm.DB, doc *goquery.Document, gameID string) e } // Upsert the data into the database. - if err := db.Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "game_id"}, {Name: "team"}}, - DoUpdates: clause.AssignmentColumns([]string{"q1", "q2", "q3", "q4", "ot1", "ot2", "ot3", "total"}), - }).Create(&lineScores).Error; err != nil { + // Using a transaction is a good practice for atomicity. + err := db.Transaction(func(tx *gorm.DB) error { + return tx.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "game_id"}, {Name: "team"}}, + DoUpdates: clause.AssignmentColumns([]string{"q1", "q2", "q3", "q4", "ot1", "ot2", "ot3", "total"}), + }).Create(&lineScores).Error + }) + + if err != nil { + log.Printf("Error upserting line scores for game %s: %v", gameID, err) return err } log.Printf("Successfully processed line scores for game %s.", gameID) return nil -} \ No newline at end of file +} +