Every PaddlePal broadcast is a public, read-only JSON endpoint. Embed it on your club website, a livestream, or a Facebook overlay — no account, no SDK.
When a player taps Broadcast in PaddlePal, they get a share link that ends in ?id=<MATCH_ID>. That UUID is all you need.
https://getpaddlepal.com/live.html?id=3f8a…d2
Poll this read-only REST URL (the apikey is the public anon key — it can only read live matches).
GET https://mbnyqrxpylvayqaqlddl.supabase.co/rest/v1/live_matches ?id=eq.<MATCH_ID>&select=* Headers: apikey: <public-anon-key> Authorization: Bearer <public-anon-key>
live_matches read-only for everyone except the match's host. Grab it from the source of live.html.| Field | Type | Meaning |
|---|---|---|
team_a / team_b | text | Team or player names |
score_a / score_b | int | Current points |
serving | "A" / "B" | Which side is serving |
server_number | int | Server 1 or 2 (doubles) |
is_doubles | bool | Doubles vs singles |
status | "live" / "final" | Match state |
winner_name | text? | Set when status = final |
updated_at | timestamp | Last point time |
Don't want to write anything? Use the built-in transparent overlay — perfect as an OBS / Streamlabs Browser Source or an iframe on Facebook/your site.
https://getpaddlepal.com/live.html?id=<MATCH_ID>&overlay=1
&overlay=1 for the full-screen scoreboard instead.A 30-line vanilla-JS scoreboard you can paste into any page:
<div id="pp"></div> <script> const URL = "https://mbnyqrxpylvayqaqlddl.supabase.co/rest/v1/live_matches"; const KEY = "<public-anon-key>"; const ID = "<MATCH_ID>"; async function poll(){ const r = await fetch(`${URL}?id=eq.${ID}&select=*`, { headers:{ apikey:KEY, authorization:"Bearer "+KEY } }); const m = (await r.json())[0]; if(m) pp.textContent = `${m.team_a} ${m.score_a} – ${m.score_b} ${m.team_b}`; } poll(); setInterval(poll, 3000); // be kind: 3s is plenty </script>