Changelog
All notable changes to the WPPR API will be documented here.
[1.3.0] - 2026-04-13β
Documentationβ
Match Set Validation Rules Clarifiedβ
The verified match documentation now explains the score progression rules more explicitly so partners can validate set logic locally before submitting matches.
What is now documented more clearly:
- one-set matches are allowed when
set_1has a winner - two-set matches are allowed only when the same team wins both submitted sets, so the result is
2:0 - three-set matches are allowed only when the first two sets are split
1:1, soset_3is the deciding set set_3must be omitted if one team already won the first two sets- tied set scores such as
6:6are rejected - placeholder
0:0scores for unplayed sets are rejected; unplayed sets must be omitted
Docs updated:
Create Match With AInow includes a dedicated set-rules section and a valid three-set example- new guide:
Match Set Validation
Breaking Changesβ
π¨ Verified Match Submission Uses Source-Based Player Identityβ
Endpoint: POST /v1/matches/verified
The verified match submission endpoint now accepts players without a WPPR ID and identifies them by source + source_player_id when wppr_id is not provided. This replaces the earlier WPPR-only match submission contract.
Before:
- Every submitted player had to include
wppr_id - A player without
wppr_idwas rejected - Business-level duplicate and rejection outcomes could return
200withstatus: "duplicate"orstatus: "rejected"
After:
- Every submitted player must include
first_nameandsource_player_id;last_nameis optional wppr_idandphone_numberare optional- If
wppr_idis present, it is authoritative - Otherwise the player is resolved by
source + source_player_id - If no existing mapping exists, the API may create a new external/unclaimed player profile
- The API never auto-links players by name alone
- If a player with the same name already exists but no mapping exists yet, the API may still create a new external/unclaimed player profile and let duplicate/merge handle it later
- If a submitted
source_player_idis already linked to another player, the request is rejected with400 - Business-level duplicate and validation failures now return
400 - Successful submissions return
200withstatus: "created" - The developer portal now preserves actionable verified-match
400conflict messages even when an upstream error body is missing a top-levelmessage
Before Request Example:
curl -X POST https://developers.wecourts.com/api/v1/matches/verified \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"match_id": "13844",
"team1": {
"player1": { "wppr_id": "P12B41" },
"player2": { "wppr_id": "PCD275" },
"set_1": 4
},
"team2": {
"player1": { "wppr_id": "PB5821" },
"player2": { "wppr_id": "PF0501" },
"set_1": 6
},
"match_details": {
"date": "2026-03-23",
"club_id": "87b2ee5d-1fc6-42be-90bc-ab69d95566a7"
}
}'
After Request Example:
curl -X POST https://developers.wecourts.com/api/v1/matches/verified \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"match_id": "source-match-123",
"team1": {
"player1": {
"first_name": "Alex",
"last_name": "Smith",
"source_player_id": "src-player-1",
"wppr_id": "P12B41"
},
"player2": {
"first_name": "Jamie",
"last_name": "Smith",
"source_player_id": "src-player-2"
},
"set_1": 6
},
"team2": {
"player1": {
"first_name": "Taylor",
"last_name": "Jones",
"source_player_id": "src-player-3"
},
"player2": {
"first_name": "Casey",
"last_name": "Jones",
"source_player_id": "src-player-4"
},
"set_1": 4
},
"match_details": {
"date": "2026-04-08",
"club_id": "87b2ee5d-1fc6-42be-90bc-ab69d95566a7"
}
}'
Before Success and Business Outcomes:
{
"source_match_id": "13845",
"status": "duplicate",
"match_id": "MC123ABC"
}
{
"source_match_id": "14129",
"status": "rejected",
"reason": "missing_wppr_id"
}
After Success Response (200 OK):
{
"source_match_id": "source-match-123",
"status": "created",
"match_id": "MC123ABC"
}
After Business Rejection Response (400 Bad Request):
{
"error": true,
"message": "The submitted source_player_id (partner-player-2) already belongs to P77777 (Mapped Player) for team1.player2 (Player Two), but this request sent wppr_id PCD275. Send wppr_id P77777 with source_player_id partner-player-2, or send a different source_player_id if PCD275 is a different player. If PCD275 should replace P77777, ask support to merge or correct the existing player mapping before retrying.",
"statusCode": 400
}
Migration Steps:
- Update all verified match player objects to send
first_nameandsource_player_id, and includelast_namewhen available - Continue sending
wppr_idwhen you already know it - Stop relying on
200duplicate or200rejected outcomes; handle business-rule failures as400 - Do not send any set as
0:0; omit unplayed optional sets instead - Do not send tied set scores; each submitted set must have a winner
- For two-set matches, the same team must win both sets for a
2:0result - Only send
set_3when the first two sets are split1:1and the third set decides the match - If you receive a
source_player_idconflict, use the returned player slot and message to correct the submitted identity instead of retrying unchanged
[1.2.0] - 2026-03-26β
Addedβ
Create WPPR Profileβ
Endpoint: POST /v1/players/profile
Create new WPPR player profiles via the API. Submit a phone number, name, and optional rating to register a new player in the WPPR system.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
phone_number | string | Yes | Player phone number |
name | string | Yes | Player full name |
rating | number | No | Initial player rating |
Example Request:
curl -X POST https://developers.wecourts.com/api/v1/players/profile \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phone_number": "971501234567", "name": "John Doe", "rating": 3.5}'
Example Response (201 Created):
{
"wppr_id": "P30C1B",
"phone_number": "971501234567",
"name": "John Doe",
"rating": 3.5,
"rating_status": "IR",
"rating_category_name": "C+",
"wppr_profile_url": "https://wecourts.com/wppr/P30C1B"
}
Behavior:
- If a profile with the same phone number already exists, returns the existing profile with HTTP 200
- Phone numbers are normalized automatically (leading
+or00stripped, non-digit characters removed) - Rating values are automatically scaled to WPPR ratings based on your API consumer profile. If no scaling is configured for your account, the value is used directly as a WPPR rating (0β8)
Per-Consumer Rating Scalingβ
When creating WPPR profiles, ratings are automatically converted from your system's scale to WPPR ratings based on your API consumer profile. If no custom scale is configured, ratings are passed through as-is (valid range: 0β8).
Benefits:
- Send ratings in your own system's scale
- Automatic conversion to WPPR ratings
Club Lookup Endpointsβ
Endpoints: GET /v1/clubs/search, GET /v1/clubs/{club_id}
New club lookup endpoints help partners find the correct club before submitting a WPPR verified match, then fetch the canonical club record again by UUID when needed.
Query Parameters (GET /v1/clubs/search):
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Club name to search for similar matches |
limit | number | No | Maximum number of clubs to return. Defaults to 20 and caps at 100 |
Search Response Fields:
idnameaddresscity_namecountry_namecountry_code
Use Case: Partners can enter a club name and receive similar club matches before submitting a WPPR verified match.
Then, if they already know the canonical club UUID, they can fetch the single club record directly with GET /v1/clubs/{club_id}.
Example Request:
curl -X GET "https://developers.wecourts.com/api/v1/clubs/search?name=Padel%20Art" \
-H "Authorization: Bearer YOUR_API_KEY"
Example Response (200 OK):
[
{
"id": "87b2ee5d-1fc6-42be-90bc-ab69d95566a7",
"name": "Padel Art",
"address": "Padel Art, Dubai",
"city_name": "Dubai",
"country_name": "United Arab Emirates",
"country_code": "AE"
}
]
Get By ID Example:
curl -X GET "https://developers.wecourts.com/api/v1/clubs/d62bd044-7dfd-4dc6-991d-9e5d9dc058ca" \
-H "Authorization: Bearer YOUR_API_KEY"
Get By ID Response (200 OK):
{
"id": "d62bd044-7dfd-4dc6-991d-9e5d9dc058ca",
"name": "Padel Art",
"address": "Padel Art",
"city_name": "Dubai",
"country_name": "United Arab Emirates",
"country_code": "AE"
}
Error Responses:
400ifnameis missing onGET /v1/clubs/search401if the bearer token is missing or invalid404ifGET /v1/clubs/{club_id}references a club that does not exist503if the upstream WPPR service is unavailable
Benefits:
- Faster club lookup by name before match submission
- Smaller, cleaner search responses
- Direct retrieval of a canonical club record by UUID
WPPR Verified Match Submissionβ
Endpoint: POST /v1/matches/verified
Partners can now submit one completed WPPR verified match per request through a simplified single-match payload.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
match_id | string | Yes | Your own match ID |
team1 | object | Yes | First team players and set scores |
team2 | object | Yes | Second team players and set scores |
match_details | object | Yes | Match metadata |
Rules:
- Every player must include
first_nameandsource_player_id. wppr_id,last_name, andphone_numberare optional.- If
wppr_idis provided, it is authoritative. - Every match must include
match_details.club_id. match_idis your own match ID.- If
set_2is provided for one team, it must also be provided for the other team. - If
set_3is provided for one team, it must also be provided for the other team, andset_2must also be present for both teams. - Every submitted set must have a winner; tied set scores are rejected.
- A two-set match must finish
2:0, meaning the same team wins both submitted sets. - A three-set match must split the first two sets
1:1, withset_3as the deciding set.
Request Behavior:
- Each player object includes
first_nameandsource_player_id;last_name,wppr_id, andphone_numberare optional - The submitted payload is a single match object, not a batch array
match_detailsincludesdateandclub_idset_1is required for each team;set_2andset_3are optional- Optional sets are paired across teams. Do not send
set_2orset_3for one team and omit it for the other team. - Do not send tied set scores or
0:0placeholder scores. - If only two sets are submitted, one team must win both sets.
- If three sets are submitted, the first two sets must be split and
set_3must decide the match. - Requests with optional sets on only one team are rejected with a
400error
Example Requests: Single set:
curl -X POST https://developers.wecourts.com/api/v1/matches/verified \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"match_id": "13844",
"team1": {
"player1": { "wppr_id": "P12B41", "first_name": "Player", "source_player_id": "partner-player-1" },
"player2": { "wppr_id": "PCD275", "first_name": "Player", "source_player_id": "partner-player-2" },
"set_1": 4
},
"team2": {
"player1": { "wppr_id": "PB5821", "first_name": "Player", "source_player_id": "partner-player-3" },
"player2": { "wppr_id": "PF0501", "first_name": "Player", "source_player_id": "partner-player-4" },
"set_1": 6
},
"match_details": {
"date": "2026-03-23",
"club_id": "87b2ee5d-1fc6-42be-90bc-ab69d95566a7"
}
}'
Two sets:
curl -X POST https://developers.wecourts.com/api/v1/matches/verified \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"match_id": "13845",
"team1": {
"player1": { "wppr_id": "P12B41", "first_name": "Player", "source_player_id": "partner-player-10" },
"player2": { "wppr_id": "PCD275", "first_name": "Player", "source_player_id": "partner-player-11" },
"set_1": 6,
"set_2": 6
},
"team2": {
"player1": { "wppr_id": "PB5821", "first_name": "Player", "source_player_id": "partner-player-12" },
"player2": { "wppr_id": "PF0501", "first_name": "Player", "source_player_id": "partner-player-13" },
"set_1": 4,
"set_2": 2
},
"match_details": {
"date": "2026-03-24",
"club_id": "87b2ee5d-1fc6-42be-90bc-ab69d95566a7"
}
}'
Three sets:
curl -X POST https://developers.wecourts.com/api/v1/matches/verified \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"match_id": "13846",
"team1": {
"player1": { "wppr_id": "P12B41", "first_name": "Player", "source_player_id": "partner-player-21" },
"player2": { "wppr_id": "PCD275", "first_name": "Player", "source_player_id": "partner-player-22" },
"set_1": 4,
"set_2": 6,
"set_3": 6
},
"team2": {
"player1": { "wppr_id": "PB5821", "first_name": "Player", "source_player_id": "partner-player-23" },
"player2": { "wppr_id": "PF0501", "first_name": "Player", "source_player_id": "partner-player-24" },
"set_1": 6,
"set_2": 1,
"set_3": 4
},
"match_details": {
"date": "2026-03-25",
"club_id": "87b2ee5d-1fc6-42be-90bc-ab69d95566a7"
}
}'
Response Outcomes (200 OK): Created:
{
"source_match_id": "13844",
"status": "created",
"match_id": "MC123ABC"
}
Successful submissions return 200 OK with status: "created". Business-rule failures, duplicate source matches, identity conflicts, and invalid score progressions return 400 Bad Request.
Error Responses:
400if submitted scores are invalid, including0:0, tied sets, a two-set1:1split withoutset_3, or an unnecessaryset_3401if theAuthorizationheader is missing401if the bearer token is invalid500for unexpected internal proxy errors503if the upstream WPPR service is unavailable504if the upstream WPPR service times out- Other upstream client/server errors are passed through with the same status code using the standard error envelope. Documented examples include
400,404,422,429, and502.
Benefits:
- Simplified submission flow for partners
- Clear mapping between partner match IDs and WPPR processing
- Cleaner payload structure focused on the required match data
[1.1.1] - 2026-03-25β
Addedβ
Contextual Player Search (Beta)β
Endpoint: GET /v1/players/search/contextual
A new endpoint that helps you find players by name with contextual information about whether they have played at a specific club or in tournaments organized by a specific company.
Use Case: Instead of searching for a player by only their name, if you provide an organizer company that organized a tournament for this player before, or a club where they played, this endpoint will help you find the right player you are looking forβeven if you pass only the player's first name or last name.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Player name to search (min 2 chars, supports fuzzy matching) |
organizer_id | UUID | Conditional | Organizer company ID |
club_id | UUID | Conditional | Club ID |
Note: At least one of
organizer_idorclub_idmust be provided. When both are provided, only players who have played matches in BOTH contexts are returned.
Example Request:
GET /v1/players/search/contextual?name=john&organizer_id=550e8400-e29b-41d4-a716-446655440000
Example Response:
[
{
"id": "P30C1B",
"wppr_id": "P30C1B",
"wppr_profile_url": "https://wecourts.com/wppr/P30C1B",
"display_name": "John Doe",
"rating": 3.791,
"rating_category_name": "C+",
"rating_status": "AR",
"nationality": "AE",
"gender": "M",
"display_gender": "Male",
"display_nationality": "Emirati",
"display_nationality_flag": "π¦πͺ",
"display_location": "Dubai, UAE",
"display_location_flag": "π¦πͺ",
"display_gender_nationality": "Emirati β’ M β’ π¦πͺ",
"image_url": "https://example.com/image.jpg",
"context": {
"matches_with_organizer": 15,
"matches_at_club": 8,
"total_context_matches": 23,
"confidence_score": 0.85
}
}
]
Context Fields:
| Field | Type | Description |
|---|---|---|
matches_with_organizer | number | Count of matches in tournaments by the specified organizer |
matches_at_club | number | Count of matches at the specified club |
total_context_matches | number | Sum of organizer + club matches |
confidence_score | number | Relevance score from 0.0 to 1.0 |
Limits:
- Results are limited to a maximum of 10 players
- Results are sorted by
confidence_scorein descending order
[1.1.0] - 2025-11-27β
Breaking Changesβ
π¨ Pagination Removed from Player Searchβ
Endpoint: GET /v1/players/search/by-name
The page and limit query parameters have been removed. The endpoint now returns all matching results without pagination.
Before:
GET /v1/players/search/by-name?name=john&page=1&limit=20
After:
GET /v1/players/search/by-name?name=john
Migration Steps:
- Remove
pageandlimitparameters from your search requests - Handle the full result set in your application
- Implement client-side pagination if needed
π¨ Categories Response Schema Changedβ
Endpoint: GET /v1/categories/list
The color field has been removed and replaced with a description field.
Old Response:
{
"name": "C+, B-",
"range": "3.750 - 4.749",
"category": "Expert",
"color": "bg-amber-500",
"min": 3.75,
"max": 4.749
}
New Response:
{
"name": "C+",
"range": "3.750 - 4.249",
"category": "Expert",
"description": "Controlled on court, basic tactics",
"min": 3.75,
"max": 4.249
}
Migration Steps:
- Remove any code that depends on the
colorfield - Implement your own color mapping if needed for UI
- Use the new
descriptionfield for enhanced user experience
Addedβ
Enhanced Error Response Documentationβ
All endpoints now return standardized, well-documented error responses:
{
"error": true,
"message": "Descriptive error message",
"statusCode": 401
}
Documented HTTP Status Codes:
400- Bad Request (invalid query parameters)401- Unauthorized (missing or invalid API key)404- Not Found (player or resource not found)500- Internal Server Error503- Service Unavailable (upstream service issues)
Benefits:
- More predictable error handling
- Better debugging with consistent error messages
- Improved client-side error handling logic
Phone Number Format Documentationβ
Endpoint: GET /v1/players/search/by-phone/{phonenumber}
Enhanced documentation for supported phone number formats:
Supported Formats:
971501234567(standard)+971501234567(with plus prefix)00971501234567(with 00 prefix)971-50-123-4567(with dashes)971 50 123 4567(with spaces)
Benefits:
- Clearer documentation of accepted formats
- Reduces integration errors
- Better developer experience
Comprehensive Property Descriptionsβ
All response properties now include detailed descriptions in the OpenAPI specification:
Player Response Properties:
id- "Player WPPR profile ID"wppr_id- "WPPR profile identifier"wppr_profile_url- "URL to the player profile on WeCourts"display_name- "Player display name"rating- "Current WPPR rating"rating_category_name- "Rating category name"rating_status- "Rating status (e.g., AR for Active Rating)"nationality- "Nationality ISO2 country code"gender- "Gender code" (enum: ["M", "F"])- And many more...
Benefits:
- Self-documenting API responses
- Clearer field purposes and formats
- Better TypeScript/type generation support
Schema Requirementsβ
All response schemas now explicitly define required fields using the required array.
Example:
{
"required": ["id", "wppr_id", "wppr_profile_url", "display_name", "rating_status"]
}
Benefits:
- Know which fields are always present
- Better TypeScript/type generation
- More reliable client-side code
Changedβ
Player Rating Endpoint Descriptionβ
Endpoint: GET /v1/players/{wppr_id}/rating
- Old description: "Retrieves the current rating and ranking information for a player from their WPPR profile."
- New description: "Retrieves the current rating and rating status and rating category for a player from their WPPR profile."
This clarifies that the endpoint returns rating, status, and category information (not ranking).
Match Response Documentationβ
Endpoint: GET /v1/players/{wppr_id}/matches
All nested match properties now have detailed descriptions:
Match Properties:
match_id- "Match ID"date- "Match date in ISO format"display_date- "Human-readable match date"
Team Properties:
team_1/team_2- "First team" / "Second team"won- "Whether this team won the match"set_1/set_2/set_3- Score information with nullable indicators
Benefits:
- Better understanding of complex match data structure
- Easier to build match display UI
- Clear indication of nullable fields
[1.0.0] - 2025-11-11β
Addedβ
Players APIβ
GET /v1/players/:wppr_id- Get player informationGET /v1/players/:wppr_id/rating- Get player rating from WPPR profileGET /v1/players/:wppr_id/matches- Get player match historyGET /v1/players/:wppr_id/stats- Get player statistics
Technical Detailsβ
- Base URL:
https://developers.wecourts.com/api - OpenAPI: 3.0
Version Historyβ
| Version | Release Date | Status | Notes |
|---|---|---|---|
| 1.3.0 | 2026-04-13 | β Current | Verified match source-based identity and contract update |
| 1.2.0 | 2026-03-26 | Stable | Create WPPR profile endpoint, rating scaling |
| 1.1.1 | 2026-03-25 | Stable | Contextual player search endpoint |
| 1.1.0 | 2025-11-27 | Stable | Enhanced docs, breaking changes |
| 1.0.0 | 2025-11-11 | Deprecated | Initial release |
Supportβ
If you have questions or encounter issues:
- Email: [email protected]
- Support Portal: WeCourts Support