Service availability: Operational Data quality: 1 dataset degraded
Last check: 31 Oct 23:10 UTC · checks run every ~10 min · page refreshes every 5 min
Bookmaker feeds with no recent price while races ran: BoostBet (no price for 117.8 h); BetGold (no price for 117.8 h).
Primary indicator, the customer path: 99.61% of external, authenticated runs passed since 13 Oct 2026 — 5376 runs over 18.7 days, with the probe running for 100.0% of that period. A run passes only when the edge check and an authenticated request both pass.
| Measurement | Record | Result |
|---|---|---|
| Internal service health On-host probes of the site and the API's /health answer with the expected status. They run inside the production host, so they cannot see a DNS, TLS, nginx or key failure. |
from 2 Aug 2026 | API 100.00%, 30 days 7 of 7 surfaces up now |
| External API reachability From outside the host, the API's edge health check answers HTTP 200 inside three seconds, with no key. |
from 18 Oct 2026 | 99.63% (3733 of 3747) |
| Authenticated request success A real /v1/racing/next-to-go request with a monitoring key returns HTTP 200. |
from 18 Oct 2026 | 100.00% (3747 of 3747) |
| Response validity That 200 carries a request id and a well-formed race list. Measured over the requests that were answered. |
from 18 Oct 2026 | 100.00% (3747 of 3747) |
| Fresh prices during racing hours From 09:00 to midnight Sydney time, at least one race carries three or more bookmakers with a quote under five minutes old. Per-book read ages are on data quality. |
from 18 Oct 2026, racing-day runs only | 99.96% (2344 of 2345) |
| Results completeness Placings and dividends settle a bet; the full field (every runner placed) comes from a separate source per code. |
2026-10-26 to 2026-11-01 | full field 99.64% where a source exists measured 31 Oct 2026 22:49 UTC by code |
The per-measure record starts 18 Oct 2026; earlier external runs kept one pass or fail per run, which is the run-level figure above. None of these is a contractual SLA, and passing all six does not prove every endpoint answers correctly — each row says what it checks.
A dataset is degraded when at least a quarter of its collectable races are overdue, when its source refuses our collector and placings or dividends are missing too, when a served bookmaker has gone dark, or when two consecutive racing-day external runs find no fresh prices. A refusing full-field source with placings and dividends intact is a scoped limitation, named with its tracks in its own notice. Partial, limited and not-assessed rows do not change the headline; a row whose measurement is older than its cadence is not current, never OK. Also in /status.json under datasets.
Runs from outside the production host with a dedicated monitoring key; asserts the response structure and, during the Australian racing day, that fresh prices are present. Latency is from the runner's location.
The API answered an authenticated request from outside. Last run 31 Oct 23:10 UTC (17s ago) from runner home-au; counted as stale after 30 min.
External record since 13 Oct 2026 · 5376 runs recorded · probe running for 100.0% of that period. Uptime here counts the edge health check and the authenticated request; a run is up only if both passed. Windows longer than this record are omitted rather than assumed.
GET https://puntersedge.online → expects HTTP 200
Monitoring since 2 Aug 2026 · 15003 checks recorded · monitor running for 100.0% of that period.
GET https://puntersedge.online/api → expects HTTP 200
Monitoring since 16 Aug 2026 · 11154 checks recorded · monitor running for 100.0% of that period. Windows longer than that record are omitted rather than assumed.
GET https://puntersedge.online/api-platform → expects HTTP 200
Monitoring since 30 Aug 2026 · 8932 checks recorded · monitor running for 100.0% of that period. Windows longer than that record are omitted rather than assumed.
GET https://puntersedge.online/api/pricing → expects HTTP 200
Monitoring since 16 Aug 2026 · 11154 checks recorded · monitor running for 100.0% of that period. Windows longer than that record are omitted rather than assumed.
GET bot health endpoint → expects HTTP 200
Monitoring since 2 Aug 2026 · 15003 checks recorded · monitor running for 100.0% of that period.
GET /health on the odds API service → expects HTTP 200 · loopback: this probe does not traverse DNS, TLS or nginx
Monitoring since 2 Aug 2026 · 15003 checks recorded · monitor running for 100.0% of that period.
GET webhook listener endpoint (POST-only; 405 on GET proves it answers) → expects HTTP 405 · loopback: this probe does not traverse DNS, TLS or nginx
Monitoring since 2 Aug 2026 · 15003 checks recorded · monitor running for 100.0% of that period.
Outbound email is sending.
Checked 6 min ago. The transport answered a reachability probe. Last successful send 31 Oct 22:31 UTC (39 min ago).
Measured by a separate monitor that reads the delivery result of every message the API sends and probes whether the configured transport is reachable — it never sends a test message to anyone. This page only reads what that monitor last wrote, which is why the time of its last run is published above: if the monitor stops, that timestamp stops moving, and no figure here can quietly go on looking healthy. Recipient addresses are masked and no message subject is published. Also available as JSON at /status.json.
2026-10-30 · external callers, successful responses, measured at the application (excludes edge time).
| Path | Requests | p50 | p95 | p99 | 5xx | 4xx |
|---|---|---|---|---|---|---|
/v1/racing/changes | 33,418 | 54.6 ms | 449.9 ms | 1474.6 ms | 00.00% | 310.09% |
/v1/racing/next-to-go | 30,509 | 218.8 ms | 1768.3 ms | 3083.7 ms | 00.00% | 2,8248.10% |
/v1/racing/results | 15,663 | 111.0 ms | 855.9 ms | 2236.6 ms | 00.00% | 3402.12% |
/v1/racing/horses/runs | 9,341 | 23.1 ms | 335.1 ms | 1187.0 ms | 00.00% | 1361.44% |
/v1/racing/horses/form | 6,814 | 734.8 ms | 4307.1 ms | 7430.5 ms | 180.26% | 10.01% |
/v1/sports/{k}/odds | 6,536 | 743.1 ms | 2772.0 ms | 5099.3 ms | 00.00% | 410.62% |
All 165 /v1 paths | 151,294all responses | 180.01% | 9,5406.31% |
On a narrow screen, swipe the table sideways for p99, 5xx and 4xx.
The hourly roll-up keeps percentiles, not raw timings, so the day's figures are combined from the hourly ones with each hour's requests counted at the top of their percentile band. They lean high rather than low. Requests and latency count successful responses only; the six busiest paths by that count, plus any other path that returned a server error. Errors are counted over every response the same external callers got on that path that day, from the same hourly roll-up. 5xx is a server error. 4xx is a client error: 402 is out of credits, 429 is rate limited, and the roll-up keeps 401, 403, 404 and other 4xx together as one class. Client errors include customers' own mistakes and exhausted credits, so they are not a measure of our availability; server errors are. Also in /status.json under latency.
A separate process on the API host polls https://puntersedge.online/ping on its own
schedule. It is a useful cross-check because it shares no scheduler and no code path with the
monitor above. Note what it reaches: the public host's nginx routes /ping to
the API process, so this probe exercises DNS, TLS, nginx routing and the API process itself
— but it carries no key and makes no database or data assertion. A pass means the API
process answers, not that prices are flowing. The /v1/uptime endpoint is backed
by this same file.
100.00% over the last 30 days (8640 checks, monitor running for 100.0% of the window). Buffer holds the most recent 8640 checks, spanning 30.0 days from 1 Oct 2026; last check 31 Oct 23:09 UTC.
A process on the same DigitalOcean droplet as the services issues one HTTP request per surface and records the response code and whether it matched the expected code. The measured interval between checks over the last 24 hours is 10 minutes — measured from the history file rather than read off the scheduler, because the two have disagreed before. Each service card shows the exact URL probed and the code it expects.
The exception is API — external, authenticated: it runs on a machine outside the production host, presents a dedicated monitoring key, and checks what a customer's request gets back. Its card is grey whenever no result newer than 30 minutes exists — a missing check is never shown as a passing one.
2 of the 7 probes are loopback requests on the box itself. They confirm the application process is answering; they cannot detect a DNS, TLS, nginx or network failure that would take the service down for every customer. They are labelled Internal probe above and you should read them as narrower evidence than the external ones.
The headline answers two questions separately. Service availability is whether the site, the API and outbound email answer, from the checks on this page. Data quality is whether each dataset those answers carry is complete and current: race results with full fields per code, the bookmaker feeds, and fresh prices on a customer request. A degraded dataset is named in its own notice, with the date it began, what still works and what is missing, and it never marks the whole service degraded. A source we do not control that refuses one part of a dataset while the rest is intact, such as a full-field source while placings and dividends still arrive, is a scoped limitation: it gets its own notice listing the tracks, and the headline stays operational. A check whose last measurement is older than its expected cadence is shown as not current, never as healthy.
How fresh the odds inside a response are is published with its own p50/p90/max figures on the coverage page under “Data refresh rates”. Those numbers live in one place so they cannot drift apart; they are not restated here.
Every quote the API returns carries its own age. On sports responses the quality
object gives score, status, age_seconds and
stale_after_seconds, and a market flips to stale once its
age_seconds passes that threshold, currently 30 minutes.
Racing quotes carry a per-book age_seconds, and each race carries
data_age_seconds — deliberately the age of the worst contributing
book, not the best — alongside freshest_age_seconds. Read those rather than
assuming a fixed panel of bookmakers is always quoting: overnight, when the Australian card
has finished, far fewer books are.
There is no contractual uptime SLA. Everything on this page is observed measurement of what has happened, published so you can judge it yourself. It is not a commitment about what will happen, there is no credit or refund schedule attached to it, and nothing here should be read as one. If you need a contractual availability commitment, ask — it is a conversation, not a published number.
This is not real-time tick data, and it is not suitable for latency-sensitive trading. Refresh rates depend on upstream bookmaker availability and rate limits.
/uptime.json — availability per surface, each figure with its window, check count and coverage. /status.json — current up/down per service. Both carry the same caveats as fields, so a consumer that never reads this page still gets them.