Partner API
WebSocket reference
Persistent WSS connection. Real-time score push, lower latency, bidirectional. Same API key as REST.
Connect
Connect to wss://webservices.ledscount.com/device with your API key and customer ID as query parameters:
wss://webservices.ledscount.com/device/?role=club_page&apiKey=YOUR_API_KEY&customerID=YOUR_CUSTOMER_ID&sessionId=UNIQUE_SESSION_IDws| Parameter | Description |
|---|---|
| role | Must be club_page. |
| apiKey | Your partner API key. |
| customerID | Your internal club/venue ID. |
| sessionId | A unique string per connection (e.g. random ID or timestamp). |
Keep-alive
Send ping as a text message every ~25 seconds to keep the connection alive. The server responds with pong.
Sending requests
Send JSON messages with a messageType and a requestId (used to match the response). Each request type is documented below with its full JSON payload and example response.
partnerStartMatch
{
"messageType": "partnerStartMatch",
"requestId": "1",
"matchID": "your_internal_match_id",
"courtNumber": "1",
"teamRed": { "player1": "John Smith", "player2": "Jane Doe" },
"teamBlue": { "player1": "Carlos Garcia", "player2": "Maria Lopez" },
"formatId": "A1",
"category": "Men's Singles",
"round": 4,
"bracket": "Main Draw",
"scheduledTime": "2026-03-25T10:30:00.000Z"
}json{
"messageType": "partnerStartMatchResult",
"success": true,
"matchID": "your_internal_match_id",
"courtNumber": "1",
"requestId": "1"
}jsonpartnerGetScore
{
"messageType": "partnerGetScore",
"requestId": "2",
"matchID": "your_internal_match_id"
}json{
"messageType": "partnerGetScoreResult",
"success": true,
"matchID": "your_internal_match_id",
"courtNumber": "1",
"playing": true,
"score": {
"teamRed": { "sets": [6, 4, 0], "points": 30 },
"teamBlue": { "sets": [3, 6, 0], "points": 15 }
},
"requestId": "2"
}jsonpartnerGetDeviceStatus
{
"messageType": "partnerGetDeviceStatus",
"requestId": "3",
"courtNumber": "1"
}json{
"messageType": "partnerGetDeviceStatusResult",
"success": true,
"courtNumber": "1",
"deviceID": "24EC4A463394",
"lastSettingsRequest": "2026-03-25T09:45:12.000Z",
"encoderActive": true,
"encoderMac": "88A29E48E7B6",
"youtubeStream": false,
"youtubeStreamStartedAt": null,
"requestId": "3"
}jsonSee REST getDeviceStatus for the meaning of each field.
partnerCallPager
Calls a pager on the venue's pager-reader with delivery confirmation. The result is sent only after the pager-reader confirms the RF burst (or the request times out), so the response may take up to 10 s.
{
"messageType": "partnerCallPager",
"requestId": "4",
"pagerNumber": 7
}json{
"messageType": "partnerCallPagerResult",
"success": true,
"status": "sent",
"pagerReaderID": "AABBCCDDEEFF",
"pagerNumber": 7,
"requestId": "4"
}jsonstatus is one of:
"sent"— RF burst transmitted by the pager-reader."rejected"— pagerNumber outside 0–999."timeout"— no confirmation from the pager-reader within 10 s.
partnerStartYoutubeStream
Starts a YouTube live broadcast for a court. Same semantics as the REST endpoint.
{
"messageType": "partnerStartYoutubeStream",
"requestId": "5",
"courtNumber": "1",
"unlisted": false,
"timer": 90,
"freshMatch": true
}json{
"messageType": "partnerStartYoutubeStreamResult",
"success": true,
"courtNumber": "1",
"broadcastId": "WB0OW-cwigM",
"requestId": "5"
}json
On error, success is false and an error field describes the cause (e.g. "No encoder paired with this court", "Encoder is not currently connected", "No YouTube refresh token configured for this club").
partnerStopYoutubeStream
Stops the YouTube broadcast for a court. Same semantics as the REST endpoint — wipes all stream-side state so the next start allocates a fresh YouTube resource.
{
"messageType": "partnerStopYoutubeStream",
"requestId": "6",
"courtNumber": "1"
}json{
"messageType": "partnerStopYoutubeStreamResult",
"success": true,
"courtNumber": "1",
"requestId": "6"
}jsonReceiving push events
While connected, the server automatically pushes events as they happen. No request is needed — they arrive on the open connection.
scoreResponse
Pushed whenever a score changes on any scoreboard at the venue.
{
"messageType": "scoreResponse",
"deviceID": "24EC4A463394",
"courtNumber": "1",
"matchID": "your_internal_match_id",
"matchScore": {
"playing": true,
"score": [
{ "s1": 6, "s2": 4, "s3": 0, "p": 30 },
{ "s1": 3, "s2": 6, "s3": 0, "p": 15 }
]
}
}jsonNote on format: the matchScore in push updates uses the internal compact format — score[0] = teamRed, score[1] = teamBlue, with s1/s2/s3 for sets and p for points. This differs from partnerGetScore, which uses the structured teamRed/teamBlue
shape.
partnerPagerScanned
Pushed whenever a pager is scanned at the venue's pager-reader. Use this to track issuance and return events in your booking system without polling. There is no equivalent REST endpoint — pager scans are WebSocket-only.
{
"messageType": "partnerPagerScanned",
"clubID": "ledscount_club_id",
"pagerReaderID": "AABBCCDDEEFF",
"pagerNumber": 7,
"timestamp": "2026-04-25T14:32:11.123Z"
}json
The same physical scan generates one event regardless of whether your business logic interprets it as an issuance or a return — that distinction is owned by your system based on its own state for the pagerNumber.
partnerStreamStatus
Pushed whenever a YouTube broadcast starts, stops, hits its auto-stop timer, or whenever the encoder connects or disconnects. Use this to keep your UI's "live" indicator accurate without polling. Pushed only to partners scoped to the same club as the affected device.
{
"messageType": "partnerStreamStatus",
"clubID": "ledscount_club_id",
"deviceID": "24EC4A463394",
"courtNumber": "1",
"encoderActive": true,
"youtubeStream": true,
"youtubeStreamStartedAt": "2026-04-25T14:32:11.123Z"
}jsonField meanings match getDeviceStatus.