Performance
Pickleball API Performance and Reliability: Building a Better Live-Score Integration
20 June 2026 · 8 min read

When you build with live sports data, a fast API response is only part of the story.
Your application also needs to know whether the score is current, whether an update has arrived out of order and what to do when a live connection is interrupted. These details matter whether you are building a scoreboard, an alerting service, a trading dashboard or a second-screen experience for fans.
Pickleball-API.com is designed around both REST and WebSockets. REST gives you a dependable way to retrieve current state and historical data. WebSockets send live changes without requiring your application to poll constantly.
Here is how to use both effectively—and how to make your integration more resilient when live sport does not go perfectly to plan.
API response time and data freshness are different things
It is easy to describe an API as “fast” without being clear about what that means.
There are really two separate questions:
- How quickly does the API respond to your request?
- How recently did the underlying match data change?
The first is about request performance. The second is about data freshness.
A REST endpoint could respond immediately while returning the most recent score received from a delayed source feed. The request itself was fast, but the score may not be fully current.
That is why Pickleball API exposes the condition of the feed rather than asking your application to infer it.
The main match-state object includes a data_status value:
livemeans the feed is updating normallydelayedmeans updates appear to be arriving later than expectedstalemeans the feed has not updated recently enough to be treated as current
This gives your application something concrete to work with. A scoreboard can show an “updates delayed” message, while a trading tool can pause an automated action until the feed returns to live.
Start with the REST API
REST is the simplest way to begin an integration.
The main match endpoints include:
GET /v1/matchesto list matchesGET /v1/matches/{id}for match detailsGET /v1/matches/{id}/statefor the current scoreboardGET /v1/matches/{id}/timelinefor ordered score eventsGET /v1/matches/{id}/gamesfor the game-by-game breakdown
You can filter the match list using options such as live=true and status, then use the returned match ID to request more detailed information.
All authenticated REST requests use your API key as a Bearer token:
Authorization: Bearer pbl_live_YOUR_KEY
Keep that key on your server or in a secure environment variable. Do not commit it to a public repository or include it directly in client-side code.
Do not request everything on every page view
The quickest way to waste API requests is to connect every visitor directly to the upstream service.
A better architecture is:
- Your server requests the latest data from Pickleball API.
- It stores that response in a cache or database.
- Your website or app serves users from the cached copy.
- The server refreshes the data when appropriate.
This means one API request can support many users.
It also improves the experience for your visitors. A response served from your own cache will often reach them more quickly than a new request travelling through the full upstream chain each time a page loads.
Some resources can be cached for longer than others. Tournament details, player information and completed matches will generally change less frequently than an active scoreboard.
The API helps with this by returning caching information on list responses. Match-state requests also support conditional requests, which are particularly useful for live scores.
Use ETags to avoid downloading the same score twice
A pickleball score does not change every second.
There may be time between rallies, during timeouts or while players change ends. If your application polls the score regularly, many requests may return exactly the same state.
The match-state endpoint returns an ETag. Store it alongside your cached response and send it back on the next request:
If-None-Match: "previous-etag-value"
When the score has not changed, the API can respond with:
304 Not Modified
Your application can continue using its existing copy instead of downloading the full response again.
This is especially valuable for applications using the Basic plan. Polling an actively followed match every 10–15 seconds, combined with ETags and server-side caching, gives you a sensible balance between responsiveness and usage.
The live-match list normally needs to be checked less frequently. Requesting GET /v1/matches?live=true approximately once per minute during an event is a reasonable starting point for many products.
Use WebSockets when polling is no longer enough
Polling is perfectly suitable for many applications. But if your product needs updates to appear automatically, the WebSocket feed is a better fit.
The live feed is included with Pro and during the free trial.
A typical WebSocket session follows this pattern:
- Connect to the live endpoint.
- Wait for
connection.ready. - Send a subscription request for one or more topics.
- Receive
subscription.ack. - Receive an initial snapshot.
- Apply subsequent
match.scoreupdates.
Two useful topic formats are:
matches.live— follows all matches currently in progress.match.<match_id>.state— follows the scoreboard for one particular match.
The initial snapshot is important. It gives your application a complete starting state before smaller updates begin arriving. Your client does not have to reconstruct the match from an incomplete set of events.
Authenticating a WebSocket connection
Server-side applications can authenticate the WebSocket upgrade request with the same Bearer API key used for REST.
Browsers are different because browser WebSocket clients cannot normally attach a custom Authorization header to the upgrade request.
For browser-based connections, use:
POST /v1/realtime/tickets
This creates a short-lived, single-use ticket. The browser can pass that ticket when opening the WebSocket connection without exposing the permanent API key.
Tickets expire after 60 seconds and are consumed when used.
This makes it possible to support browser-based live experiences while keeping the main account credential on your server.
Keep updates in the correct order
Every match state includes a resource_version.
This is a number that increases as the resource changes. It gives your application a straightforward way to decide whether an incoming update is newer than the state it already holds.
For example, suppose your cached state is version 148.
If the next update is version 149, your application can apply it. If it later receives version 147, it should ignore it rather than moving the scoreboard backwards.
You can use resource_version to:
- Order incoming updates
- Ignore duplicate messages
- Reject older updates
- Detect gaps in the sequence
- Compare WebSocket updates with REST responses
This is more dependable than relying only on the order in which messages happen to reach your application.
Recover cleanly when state becomes uncertain
A live connection can be interrupted for ordinary reasons. A server may restart, a network may change or the client may briefly lose connectivity.
Your integration should expect this rather than treating every disconnection as an exceptional event.
The WebSocket feed may also send:
resync_required
This means your local copy may no longer contain a complete or reliable sequence of updates.
When that happens:
- Request the current state from
GET /v1/matches/{id}/state. - Replace the locally cached state.
- Record its latest
resource_version. - Resume processing WebSocket updates.
Do not try to guess the missing score events. Fetching the complete current state is safer and simpler.
After a full disconnection, reconnect, subscribe again and use the new snapshot as the source of truth.
Respond to WebSocket heartbeats
The WebSocket service uses heartbeats to check that connections are still active.
The server sends a ping approximately every 25 seconds. Your client should respond with a message in this form:
{
"type": "pong",
"at": "..."
}
If the connection does not respond within roughly 60 seconds, it may be closed.
Make heartbeat handling part of your WebSocket client from the beginning. Otherwise, a connection may appear to work during a short test and then close unexpectedly when left running.
Documented close codes include:
4401— unauthorised4403— forbidden4408— quota exceeded1012— service restart1013— try again later
Your reconnect behaviour should take the close reason into account. A service restart may justify reconnecting after a short delay. An authentication or entitlement error usually requires a configuration or account change instead.
Handle REST errors by their codes
REST errors use the application/problem+json format and include a stable machine-readable code.
Common responses include:
400 invalid_request— the parameters or request body are invalid401 unauthorized— the API key is missing or invalid403 websocket_not_entitled— the requested feature is not included in the plan404 not_found— the requested resource does not exist429 quota_exceeded— a rate or monthly allowance has been reached
Your code should branch on the machine-readable error code rather than matching the human-readable message.
Every response also includes a request ID. Log meta.request_id for successful calls and the corresponding request ID from error responses.
If you need to contact support, that identifier makes it much easier to trace the individual request.
Understand the two kinds of usage limit
Each plan has both a per-minute rate limit and a monthly allowance.
Basic includes:
- 25,000 REST requests per month
- Up to 60 REST requests per minute
- No WebSocket access
Pro includes:
- 100,000 REST requests per month
- Up to 120 REST requests per minute
- Up to 3 WebSocket connections
- Up to 25 topics per connection
- 100,000 outbound WebSocket messages per month
- 15 minutes of live-message replay
The limits are hard caps. When one is reached, the API returns 429 quota_exceeded rather than creating an automatic overage charge.
You can monitor current usage through:
GET /v1/usage
Checking usage inside your own dashboard or monitoring system can help you spot inefficient polling before it becomes a problem.
A sensible REST-only request pattern
For a small REST integration, a good starting pattern is:
- Request
GET /v1/matches?live=trueonce every 60 seconds while an event is active. - Fetch match metadata once when a match first appears.
- Poll
/stateevery 10–15 seconds only for matches users are actively following. - Send
If-None-Matchwith the last ETag. - Fetch
/timelineor/gameswhen the relevant view is opened or when the match finishes. - Cache responses on your server and share them with your own users.
There is rarely a good reason to fetch player details, tournament information and the complete timeline on every score poll.
Request the changing resource frequently and the supporting resources only when needed.
A sensible WebSocket request pattern
For a live Pro integration:
- Retrieve the current live-match list through REST.
- Fetch the full initial state for matches you want to follow.
- Open a WebSocket connection.
- Subscribe to
matches.liveor the required match topics. - Receive and store each snapshot.
- Apply score updates in
resource_versionorder. - Respond to heartbeat pings.
- Fetch the current state through REST whenever
resync_requiredis received. - Distribute the resulting state to your own users.
REST and WebSockets are not competing approaches. The most resilient applications use REST for complete state and recovery, then WebSockets for efficient live changes.
Be careful when making performance promises
Pickleball API does not publish a universal “court-to-screen” latency figure.
The time between a rally taking place and a score appearing in your application may include several stages:
- The event is recorded at the venue
- The upstream source publishes the change
- Pickleball API receives and validates it
- The API updates the canonical match state
- The message travels to your application
- Your own software processes and displays it
Those stages may vary by event and source.
For that reason, your product should use data_status, timestamps and local monitoring rather than presenting every successful response as proof that a score is live.
If you publish performance figures of your own, make sure they describe something you actually measure.
What should users see when data is delayed?
Reliability is not only a backend concern. Your interface needs to communicate uncertainty clearly.
When data_status is delayed or stale, you might:
- Show the last known score with a status label
- Display the time of the most recent update
- Pause score-dependent alerts
- Disable automated actions
- Offer a manual refresh
- Explain that updates are temporarily delayed
Do not remove the score without explanation, but do not present it as definitely current either.
A simple message such as “Live updates delayed—showing the latest available score” is often enough.
Frequently asked questions
Should I use REST or WebSockets?
Use REST for match lists, initial page loads, current state, timelines, history and reference data.
Use WebSockets when score changes need to arrive automatically while a match is in progress.
Many applications should use both.
How often should I poll a live match?
Every 10–15 seconds is a sensible starting point for an actively followed match on a REST-only integration.
Use ETags so unchanged state can return 304 Not Modified, and avoid polling matches nobody is currently viewing.
Can I connect directly from a browser?
Yes, but do not expose your permanent API key.
Create a short-lived ticket using POST /v1/realtime/tickets, then use that ticket to authenticate the browser’s WebSocket connection.
What happens if I miss an update?
The service may send resync_required. Fetch the complete current state through REST and continue from the returned resource_version.
How do I know whether a score is current?
Check data_status. It explicitly reports whether the underlying feed is live, delayed or stale.
What should I include in a support request?
Include the endpoint or WebSocket topic, the approximate time of the issue and the relevant request ID. Never send your full API key.
Build for recovery, not just the happy path
A good live-data integration is not one that assumes nothing will ever go wrong. It is one that continues behaving sensibly when a feed is delayed, an update arrives twice or a connection has to restart.
Pickleball API gives you the pieces needed to handle those situations:
data_statusfor feed freshnessresource_versionfor ordering changes- ETags for efficient REST polling
- Snapshots and deltas for live streaming
resync_requiredfor clean recovery- Stable error codes and request IDs for diagnosis
Start with REST, add WebSockets when your product needs them and keep a complete cached state inside your own application.
More from the blog
- What Can You Build With a Pickleball API? 7 Practical Product Ideas
21 July 2026 · 7 min read
- REST or WebSockets for Live Pickleball Data? How to Choose
27 May 2026 · 7 min read
- Getting Started With the Pickleball API in 5 Minutes
18 May 2026 · 5 min read