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_ID
ws
ParameterDescription
roleMust be club_page.
apiKeyYour partner API key.
customerIDYour internal club/venue ID.
sessionIdA 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

Request
{
  "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
Response
{
  "messageType": "partnerStartMatchResult",
  "success": true,
  "matchID": "your_internal_match_id",
  "courtNumber": "1",
  "requestId": "1"
}
json

partnerGetScore

Request
{
  "messageType": "partnerGetScore",
  "requestId": "2",
  "matchID": "your_internal_match_id"
}
json
Response
{
  "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"
}
json

partnerGetDeviceStatus

Request
{
  "messageType": "partnerGetDeviceStatus",
  "requestId": "3",
  "courtNumber": "1"
}
json
Response
{
  "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"
}
json

See 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.

Request
{
  "messageType": "partnerCallPager",
  "requestId": "4",
  "pagerNumber": 7
}
json
Response
{
  "messageType": "partnerCallPagerResult",
  "success": true,
  "status": "sent",
  "pagerReaderID": "AABBCCDDEEFF",
  "pagerNumber": 7,
  "requestId": "4"
}
json

status 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.

Request
{
  "messageType": "partnerStartYoutubeStream",
  "requestId": "5",
  "courtNumber": "1",
  "unlisted": false,
  "timer": 90,
  "freshMatch": true
}
json
Response
{
  "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.

Request
{
  "messageType": "partnerStopYoutubeStream",
  "requestId": "6",
  "courtNumber": "1"
}
json
Response
{
  "messageType": "partnerStopYoutubeStreamResult",
  "success": true,
  "courtNumber": "1",
  "requestId": "6"
}
json

Receiving 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.

Event
{
  "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 }
    ]
  }
}
json

Note 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.

Event
{
  "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.

Event
{
  "messageType": "partnerStreamStatus",
  "clubID": "ledscount_club_id",
  "deviceID": "24EC4A463394",
  "courtNumber": "1",
  "encoderActive": true,
  "youtubeStream": true,
  "youtubeStreamStartedAt": "2026-04-25T14:32:11.123Z"
}
json

Field meanings match getDeviceStatus.