Types the compiler can actually trust
Most odds API wrappers hand-type their response interfaces. That guarantees drift the first time the API ships a field, and a TypeScript type that lies is worse than no type at all — it type-checks the wrong thing, confidently, and the mismatch surfaces at runtime in production rather than in your editor.
The official PuntersEdge client generates its types from the API's own OpenAPI document. A race carries twenty-odd fields plus nested runners, per-bookmaker quotes and scratchings, and every one of them is described by the schema the server publishes. A field marked optional in the types is a field the API declares optional — because some bookmakers genuinely do not report a barrier, not because the typing was rushed.
Errors are typed too, one class per status, because they need different answers. A 402 means the month's credits are spent and backing off will never clear it. A 429 means wait the stated seconds and repeat the identical call. A 422 means the request is wrong and will fail the same way forever. Collapsing those into one Error pushes the branch into a regex over the message.
- Types generated from the live OpenAPI schema
- A typed error class per status code
- Credit balance read off every response
- Zero dependencies, ESM and CommonJS
- Free tier, no credit card
Example API calls
npm install puntersedge
import { PuntersEdge, RateLimitError } from "puntersedge";
const pe = new PuntersEdge({ apiKey: process.env.PUNTERSEDGE_API_KEY });
// Racing is its own endpoint family — there is NO sport_key of "horse-racing".
const races = await pe.racing.nextToGo({ numRaces: 5, categories: "horse" });
for (const race of races) {
const best = race.runners
.flatMap(r => r.bookmakers.map(b => ({ runner: r.name, book: b.key, price: b.win_price })))
.filter(q => q.price)
.sort((a, b) => b.price - a.price)[0];
console.log(`${race.venue} R${race.race_number}: ${best.runner} @ ${best.price} (${best.book})`);
}
// The balance came back on the response above — checking it costs nothing.
console.log(pe.credits?.remaining, "credits left");
curl "https://api.puntersedge.online/v1/racing/next-to-go?num_races=5" \
-H "X-API-Key: YOUR_API_KEY"