Pinnacle odds API latency, measured

Most API speed pages quote a number with no method behind it. Here is ours, split into the part we control and the part physics controls — and a one-line command so you never have to take our word for it.

Our test, measured 26 August 2026: Amsterdam origin, 20 server-processing samples, 25 cold-request samples and 11 warm-request samples.

1.3ms
Server-side processing
Median at the origin, /v1/health, 20 samples. Worst case 5.4ms.
1.5ms
Warm request, at the origin
Reused connection, network distance removed. This is the floor you add your round trip to.
41ms
Cold request, at the origin
Same request, new connection: the TLS handshake is ~39ms of it.

The only formula that matters

what you observe = ~1.5ms of ours + your round trip to Amsterdam

Odds are served from a single origin in Amsterdam. Our share of the response is small and steady; the variable is the distance between you and that origin, and whether your client reuses its connection. That is why we publish a formula instead of one headline number — a flat "sub-100ms everywhere" claim would only be true for clients close enough to make it true, and you would find that out in your first test anyway.

Measured at the origin, network distance removed

MeasurementResultWhat it is
Server processing1.3msApplication time only, 20 samples
TCP connect2.3msMedian, 25 samples
TLS handshake complete39msMedian — the real cost of a cold start
Cold request (TTFB)41msMedian, 25 samples — handshakes included
Warm request (TTFB)1.5msReused connection, 11 samples

Two things fall out of that table. First, on a connection that is already open we answer in about a millisecond and a half — there is almost nothing between your request and the odds. Second, the expensive part of a cold request is not our code, it is the TLS handshake, and you pay it once per connection rather than once per request. Add your own round trip to Amsterdam to both figures and you have your number; run the command below from wherever your bots actually live and you will have it in about five seconds.

Verify it yourself — no signup

The public demo key is literally key=demo. Time a real response:

curl -o /dev/null -s -w "total: %{time_starttransfer}s\n" \
  "https://pinnwire.com/v1/health?key=demo"

That single request pays the handshakes. To see the warm number — what a well-written client actually experiences — send a few on one reused connection. Five is plenty, and stays well inside the demo allowance:

curl -o /dev/null -s -w "%{time_starttransfer}\n" \
  $(printf '%s ' $(yes "https://pinnwire.com/kit/v1/markets?sport_id=1&key=demo" | head -5))

The first line includes the handshakes. The rest are warm, and they are the number to judge us on.

Before you loop it

The demo key allows 10 requests per minute in total — that allowance is shared by everyone using it, not granted per person. Keep test runs to a handful and you leave room for the next person; loop it and you will hit a 429 with a Retry-After header partway through, which hands you numbers measuring our rate limiter rather than our speed.

For a real benchmark, take a free trial key from the homepage — 100 requests a day, no card — or run against a paid plan, where the ceiling is 10 to 30 requests per second.

How to make it fast on your side

Reuse the connection

This is the single biggest thing you control. A fresh connection pays a TCP handshake and a TLS handshake before a single byte of odds moves; an open one pays neither. Measured at the origin, that is the difference between 41ms and 1.5ms for the identical request — roughly thirtyfold. Any HTTP client with keep-alive enabled pays it once at startup. Further from Amsterdam the absolute numbers rise, but the gap only widens, because a cold start costs you several round trips instead of one.

Stop polling, start streaming

REST provides current snapshots on demand. SSE pushes detected drop alerts, while the optional raw WebSocket streams live and prematch market updates. Each long-lived stream pays the handshake once at startup instead of on every REST poll.

Ask for less

Narrow the request and the response gets smaller and faster to parse: filter by sport_id, use since= for incremental polling, and prefer /kit/v1/prematch/lines over full fixture payloads when you only need the main lines.

Method, stated plainly

Server processing was measured on the origin host against localhost:8080, 20 samples of /v1/health, reporting median and maximum — that isolates application time from every network effect. The connect, handshake, cold and warm figures were measured at the origin over its public HTTPS interface, 25 cold samples and 11 warm ones, reporting time_starttransfer (time to first byte). Because network distance is effectively zero there, these are a floor, not a promise: they are what remains when you subtract the internet, and we label them that way deliberately. Your own number is that floor plus your round trip, which is why the command above matters more than this table.

View PinnWire’s current service status and rolling 24-hour availability.