Skip to main content

How Players Are Matched

This guide explains how POST /api/v1/matches/verified decides which WPPR player each submitted player object resolves to — and how to avoid creating duplicate profiles.

When you submit a match, every player object is resolved independently. The API either links the player to an existing WPPR profile or creates a new one. Understanding the order lets you predict the outcome and send the right fields the first time.

Resolution Order​

For each player, the API tries these in order and stops at the first that resolves:

#SignalWhen it resolvesNotes
1wppr_idAlways, if presentAuthoritative. If you know the WPPR ID, send it.
2source_player_idOnly if this ID was recorded on a previous successful submission from your sourceThe mapping is built the first time; a brand-new source_player_id resolves no one on its own.
3phone_numberIf the number matches an existing profile that can be safely reusedFallback, to avoid duplicates. Only reached when 1 and 2 don't resolve. If the number is instead tied to a different, already-claimed player, the request is rejected with 400 (see below).
4Create newNone of the above matchedA new external / unclaimed profile is created.

Names are never used to auto-match a player. Two players with the same name are still two different players unless a signal above links them.

The First-Submission Rule​

This is the most common source of confusion.

Sending a source_player_id does not, by itself, resolve an existing player. It resolves a player only after a previous successful submission has recorded the link. That link is created the first time you send the player — usually via their wppr_id, or by matching their phone, or by creating a new profile.

Rule of thumb

The first time you submit a player who already exists in WPPR, include their wppr_id. That establishes the source_player_id → player link. From your next submission onward, source_player_id alone resolves them — no wppr_id or phone_number needed.

Example​

First submission — you know the player already exists in WPPR, so you send the wppr_id:

{
"first_name": "Alex",
"last_name": "Example",
"wppr_id": "PTEST01",
"source_player_id": "[email protected]"
}

This creates the mapping [email protected] → PTEST01.

Every later submission — the mapping now exists, so this is enough:

{
"first_name": "Alex",
"last_name": "Example",
"source_player_id": "[email protected]"
}

Why Phone Number Is a Fallback, Not a Key​

phone_number is optional and is only used at step 3 — when a player has no wppr_id and no previously-recorded source_player_id. It exists to catch the case where you re-send a known player under a new identifier, so the API reuses their profile instead of creating a duplicate. In most cases a matching number links the player to that existing profile.

A phone number belongs to only one player. In the narrower case where the number is tied to a different, already-claimed player that can't be safely auto-linked, the request is rejected instead. This is what stops two profiles from ending up with the same number.

Conflicts are rejected, not silently merged

If a source_player_id maps to a different player, or a phone_number is tied to a different already-claimed player that can't be safely auto-linked, the API returns a 400 that names the blocking wppr_id so you can fix the submission. It never merges two distinct players automatically.

Conflicts and How to Resolve Them​

phone_number already linked to another player​

You sent a phone_number tied to a different, already-claimed player that couldn't be safely auto-linked, and that player wasn't matched by wppr_id or a known source_player_id.

{
"error": true,
"message": "The submitted phone_number (447700900123) is already linked to PTEST01 (Alex Example). Send wppr_id PTEST01 for this player if it is the same person, or omit phone_number to create a separate player.",
"statusCode": 400
}

Fix:

  • Same person? Send wppr_id: PTEST01 for that player.
  • Different person? Omit or change phone_number.

source_player_id already linked to another player​

You sent a source_player_id that is already mapped to a different player than the wppr_id in the same 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
}

Fix:

  • Same person? Send the wppr_id the message names, with that source_player_id.
  • Different person? Use a different source_player_id.
  • Mapping is wrong? Ask support to merge or correct it before retrying.

Best Practices​

  • Send wppr_id whenever you know it — it's the only signal that never depends on prior state.
  • Give every player a stable source_player_id (email, internal user ID, UUID) and always reuse the same value for the same person. This is what keeps your players consistent over time.
  • Include wppr_id on the first submission of a player who already exists in WPPR, so the source_player_id link is established from the start.
  • Treat a 400 conflict as actionable: read the blocking wppr_id in the message and correct the submitted identity — don't retry the same payload unchanged.