Link WPPR: Errors
Three places things go wrong, and you catch each one somewhere different. This page owns every duration and failure code in the flow; the build steps point here rather than repeating them.
From the API
Returned to your backend, on the calls it makes with your key.
| You get | Means | Do |
|---|---|---|
401 unauthorized | The key is missing, wrong, or revoked | Fix the credential. The same key fails the same way every time |
400 invalid_code | The exchange couldn't match what you sent: unknown or malformed code, a code issued by a different session than the session_id you named, or a code that belongs to another API key | Check you stored the right session_id for this callback. If it happens with correct pairing, treat it as a failed attempt and log it |
403 redirect_uri_not_allowed | The redirect URL's scheme and host don't equal your registered origin, or you sent one with no origin registered | Register the origin via the API, then retry |
404 not_found | The session doesn't exist for your key. Sessions and codes are visible only to the API key that created them; any other key gets this same answer, never a partial one | Check the session_id. If you run several keys, make sure the poll uses the key that opened the session |
410 code_expired | More than 5 minutes since the code was issued. Within those 5 minutes you can present it again | Start the flow again |
429 rate_limited | Too many calls for your key: the budget is 100 session creations, 100 exchanges, and 20 origin registrations per minute. Status polling is budgeted per session instead, sized for a check every half second sustained, so the 3 to 5 seconds we recommend always fits | Back off and retry |
On the player's return
The ?error= forms only exist if you sent a redirect_uri. Poll the session status instead and you get the right-hand form of the same failure.
| You get | Means | Do |
|---|---|---|
?error=access_denied, or status cancelled | The player cancelled. Every exit reports the same way, whichever step they were on | Reset the UI and offer to retry |
?error=session_expired, or status expired | The hour ran out while they were on our page | Open a new session |
a state that doesn't match what you stored | We hand it back on the callback and you verify it. Someone is replaying a callback | Never link. Treat it as a failed attempt and log it |
When nothing comes back
The player can just stop: close the tab, kill your app, never read the code. Nothing fires. Time out at an hour on your side, whichever return mode you use.
Walking away is not access_denied. We can only tell you a player left when they leave through a control we serve, so treat silence as the normal way an attempt dies, not the rare one.
Silence doesn't always mean nothing happened. A player who signs up during the link finishes on a WeCourts confirmation screen and taps a button there to come back to you. In redirect mode that means the link can be completed on our side while your callback never fires, because they closed the screen instead of tapping it. So before you reset the UI, poll the session once: a completed session returns the same payload the exchange would have, and it is the only recovery there is. A link URL is single use, and re-opening it after completion yields a used-link screen and no code.