Get the devlog by email
One email a week, only when an issue is published. Nothing else goes to this list, and every email carries a one-click unsubscribe.
Prefer a reader? JSON Feed · RSS
Issue #3
Issue #2 promised the first full-size Saturday reading of the morning card, whatever it said. It is below, with the two things that went wrong that day. After it: the results meetings we were silently dropping, an account page you can log in to, the referral programme, and two SDK releases. As before, anything half-done says so.
Saturday's card, measured
Asked by the tipping service from the last two issues, and a full-time punter modelling off six books who named the two windows that matter: the 7:45 scratchings through the official morning line, and the hour before race one.
- Saturday 12 September, Australian thoroughbreds, 105 races across 18 meetings. At 08:00 Sydney every race was priced; 98 had a best win and place, Sportsbet covered 95 and Betr 96. At 09:15 all 105 had a best win and place, Sportsbet 104 and Betr 103. At 10:00 the same, with 11 to 14 bookmakers on every race that jumped before 17:00 and 10 to 11 after. The ten races that jumped before 13:00 were all priced by both books at 08:00.
- Per bookmaker at 10:00: eight books (BetDeluxe, Betright, Ladbrokes, Neds, Sportsbet, TAB, TABtouch, Betr) carried 104 of the 105; Palmerbet 102; BetGold and BoostBet 90; PointsBet 82; Unibet 10. Unibet's number is its 20-races-per-code listing cap, which is on the open list.
- New morning tier. Between 07:45 and 09:30 Sydney, Ladbrokes, TAB and Betr re-price their whole day card every two to three minutes and PointsBet every minute, instead of the 15-minute cadence the far card normally gets. Outside that window nothing changes. Opt-in per book because each rate limit is its own.
- New placeholder guard on the best line. A quote of $21 or more that is at least four times the median of three or more other books for the same runner ($101 on a dog TAB had at $4.40 that morning, from a customer report) is kept out of
best_win, best_place, market_percentage and price_spread_pct, and listed on the runner as suspect_win / suspect_place so nothing is hidden. - What went wrong on the day. BetGold and BoostBet prices ran about 14 minutes stale until 10:05 Saturday morning: the second outbound route they use had been quietly refusing most connections since Tuesday, inside the tolerance of the alarm meant to catch it. Fixed that morning; the route is now the standing one. And from 13:00 to 15:20 Racing Australia refused horse-form reads from our server, so 347
/v1/racing/horses/form calls for horses with no stored copy returned 503 (unbilled) to two customers. Since Sunday those reads go out through the same second route, which Racing Australia serves normally.
Results: the meetings we were dropping
Asked by a customer migrating a historical runner database, who counted the gaps himself, and a customer commissioning the results feed for a betting app.
- Seven of 49 thoroughbred finals on 9 September came back with no starters. The cause was ours: Racing Australia files that card as Kensington, the settling bookmaker calls it Randwick, and the collector matched the two on the bookmaker's spelling, so seven parsed fields were discarded inside the process that had just fetched them. It now joins through the venue registry as well, re-asks when a meeting is published late, and a null field says why it is null. Fannie Bay, which Racing Australia had filed as Darwin (six races, empty for five days), is aliased the same way.
- The racing code is now part of the result-to-race match. Ballarat, Geelong and Bendigo run two codes on one night and number both cards from 1, and seven stored results had attached to the other code's race at the same track. Those rows are corrected and it cannot recur.
race_id on a result now links through the venue registry when the results feed and the bookmakers spell a track differently (Riccarton against Riccarton Park, Sandown Hillside against Sandown). 27 of the 73 unlinked results in the last 45 days linked on the re-run; the other 46 have no priced race on file and stay null, honestly.abnormal on a result runner is Racing Australia's own finish cell, passed through unchanged, and the docs no longer read as a closed list. Codes seen so far: Fell 101, TailedOff 32, SB 25, PulledUp 8, FF 1, LP 1. Only SB, a barrier scratching, flips status to scratched; anything else stays ran, because misreading a starter as a non-starter turns a losing bet into a refund.- The acceptances card now names every runner Racing Australia served that we did not publish. On 10 September it had lost 30 of 305 rows and said nothing about five of them, four of them emergencies, because Racing Australia numbers emergencies at the top of the saddlecloth sequence and the completeness check stopped at the highest number still held.
completeness.known_missing_runners is now exact, and the response note says plainly that a meeting's rows stop advancing once it is underway. /v1/racing/track-conditions was returning the same meeting twice (Seymour from Racing Australia and from a bookmaker, Warwick likewise), and ?venue=warwick returned only the bookmaker's empty shell. One meeting, one entry.- Open, and it is about Saturday. Of the 104 Australian thoroughbred finals resulted on 12 September, 55 carry the full field as of Monday morning. The rest are Belmont, Morphettville, Doomben, Mackay, Toowoomba, Carnarvon, Thangool and Alice Springs. All 104 are linked to their priced race and carry placings and dividends; the collector keeps re-asking Racing Australia for the fields, and this issue's open list holds it until they land.
An account page you can log in to
Asked by several customers who arrived looking for a login and found a box asking them to paste a key.
- New email login on the account page and on
/login. Enter the address your key is registered to and a one-time link arrives; it works once, expires in 15 minutes, and opens the page signed in on that device for 30 days. No password, and your key is not changed. - Signed in, the page shows plan, credits used and remaining, burn rate, month-end projection, where the credits went, and the upgrade panel. There is a log-out link.
- Your key on the page. Keys are stored hashed, so the one you were originally issued cannot be displayed. One click issues a fresh key, shows it, fills the code samples with it and emails a copy; the previous key keeps working for 24 hours so anything running has time to roll over. Once per 24 hours per account, so a key we just promised is never cut off early.
- Paying now lands you on the page that shows your key and a first request, instead of back on the pricing page. That old landing had no success state, and half the expired checkout sessions in the last month were people buying a second time from it. A checkout error, including the already-subscribed 409, is now shown in full rather than as "try again".
Refer a developer, earn 10% for 12 months
Asked by nobody in particular; it is how the next customers are most likely to arrive.
- If someone you send to PuntersEdge subscribes, you earn 10% of every invoice they pay us for 12 months from their first payment, as cash (paid by transfer once it passes A$50) or as API credits at 5,000 per A$1. A free signup earns nothing; the commission is a share of what someone actually pays. Terms on the programme page.
- Your code and your link are on the account page, minted on first visit and permanent. A friend types the code into the referral box on the signup form or uses the link, which carries it. The programme was click-only for its first two days, which loses a code said out loud or pasted without the query string; the typed box fixes that, and a clicked link always beats a typed code so nobody can take a referral off the partner who earned it.
- Built with PuntersEdge is a showcase for what people have built on the API, with a submission form. A human reads every entry and an approved one is a real link back to you. It is empty. Someone has to go first.
- Every active account was told about both on 14 September. Six referral codes exist so far and nobody has converted through one yet, which is what you would expect three days in.
SDKs: a TypeScript client and MCP 0.2
Asked by a Node developer who found the old npm package pointed at a page that no longer exists, and the people using the MCP server from Claude and Cursor.
puntersedge on npm is now generated from the live OpenAPI document. The docs are at /developers/typescript: install, the endpoint families, credits read off the response headers, an error class per status, the change feed instead of polling, staleness, and webhook verification against raw bytes. The 0.1.0 package from June predated the current response shapes and is superseded.puntersedge-mcp 0.2.0 has 26 tools where 0.1.0 had ten, and corrects three understated costs: best_odds is 3 credits, racing_price_history is 5, and sports_odds is one per market. A num_races filter on racing_movers that the endpoint never had, so it had silently done nothing since 0.1.0, is removed. 0.2.1 fixes a README link. A contract test now checks every tool's path, parameters and cost against the API before a release. The MCP page lists all 26.
Missed from last issue, and plumbing
- Rugby union went from one bookmaker to six on 8 September, and TAB's competition mapping no longer hard-codes a season, which is how a whole sport goes quietly empty at season's end.
- The sports odds endpoints are pre-match only, and the docs now say so: there is no in-play feed, and history and movements keep the last pre-match prices.
- Payment failures on API plans now get an email with a link to fix the card, and the plan stays on while Stripe retries. Before this the first anyone heard was a 402 in their own code.
- NSW moves to daylight time on 4 October. Thirteen places in the code dated races into Sydney days with a fixed +10 hours, which from that morning would have filed any race jumping just after Sydney midnight under the previous day, and half the code already used the proper zone, so the two halves would have disagreed for an hour a day. One helper now, three weeks early.
- The premiership state tables have filled: all eight states plus the national tables, jockeys and trainers, read through to 13 September in the small bursts issue #2 described.
- Comped trial keys carry an expiry that nothing was reading. A nightly job now drops a lapsed trial back to the free allowance, keeps the key working, and reports a trial with no date rather than guessing one.
Still open
- Saturday's result fields. 49 of the 104 thoroughbred finals from 12 September are still without the full field (Belmont, Morphettville, Doomben, Mackay, Toowoomba, Carnarvon, Thangool, Alice Springs). Placings, dividends and the link to the priced race are there; the runner rows are not, and the collector keeps asking.
- TAB betslip deep links. The daily check has failed on TAB every day since 8 September: the slip opens but arrives empty. Unibet passes. Until a run passes, TAB rows carry null betslip fields rather than a link that does not work. Not yet diagnosed.
- Unibet's day card. Unibet lists only the nearest 20 races per code, so it covered 10 of Saturday's 105 at 10:00. A day-card lane is built and switched off until its listing cap is understood.
- Greyhound results from our own collection. Still measuring parity, Victoria only; the interim feed remains the published source. Three results-collector findings from the same review are planned: a partially published field can be frozen, a horse engaged twice in one day can be given the wrong race's acceptance data, and dead-heat placings are unhandled.
- Hong Kong racing: unchanged, prices only.
- The showcase has no entries.
- BSP and traded volume. Betfair data licence.
Reply with anything you want on the list. The three results findings and the Unibet cap came from customers reading their own data closely, which is the most useful kind of report there is. Write to hamish@punters-edge.com or use the feature request form.