18+ Only  |  Gambling can be addictive — please gamble responsibly  |  Gambling Help: 1800 858 858  |  GambleAware

Developers / Affiliate links

Your affiliate links on every price

Store your tracking link for each bookmaker once. Every racing price then comes back with your link already built, ready to put on your page.

The short answer

One PUT /v1/link-templates stores a template for each bookmaker: your affiliate tracking link, with {url} where the bookmaker's page for the race goes.

From your next request, every price on next-to-go, best-odds and markets carries source_link beside source_url: your tracking link with that race already inside it. Betslip links get the same.

Available on Plus and above. Storing, reading and removing templates costs no credits.

Before you start

1. Write a template for each bookmaker

A template is your tracking link with a placeholder where the bookmaker's own page for the race goes. When a price is served, the placeholder is replaced with that price's source_url.

Placeholder Inserts
{url}The bookmaker's URL, percent-encoded. Use this when the URL goes inside a query parameter of your tracking link, which is almost always.
{url_raw}The bookmaker's URL exactly as it is, for a tracker that expects it unencoded.

A template must start with https://, contain one of the two placeholders, and be 500 characters or fewer. Nothing of ours is added to it: no tracking parameters and no redirect through our servers.

The templates go in one document:

{
  "mode": "source",
  "per_bookmaker": {
    "ladbrokes_au": "https://your-tracker.example/click?aff=YOUR_ID&dest={url}",
    "unibet": "https://your-tracker.example/go?pid=YOUR_ID&url={url}",
    "playup": "none"
  }
}

Here Ladbrokes and Unibet prices link through your tracking links, PlayUp prices carry no link, and every other bookmaker links straight to its own race page.

2. Store them

curl -X PUT "https://api.puntersedge.online/v1/link-templates" \
  -H "X-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "source",
    "per_bookmaker": {
      "ladbrokes_au": "https://your-tracker.example/click?aff=YOUR_ID&dest={url}",
      "unibet": "https://your-tracker.example/go?pid=YOUR_ID&url={url}",
      "playup": "none"
    }
  }'

The response returns what was stored, and a preview of each rule built against an example address, so you can check the encoding before anything reaches your page:

"preview": [
  {"bookmaker": "ladbrokes_au",
   "source_url": "https://www.bookmaker.example/racing/race/1",
   "source_link": "https://your-tracker.example/click?aff=YOUR_ID&dest=https%3A%2F%2Fwww.bookmaker.example%2Fracing%2Frace%2F1"},
  {"bookmaker": "playup", "source_url": "https://www.bookmaker.example/racing/race/1",
   "source_link": null},
  {"bookmaker": "unibet", ...},
  {"bookmaker": "(every other book)",
   "source_url": "https://www.bookmaker.example/racing/race/1",
   "source_link": "https://www.bookmaker.example/racing/race/1"}
]

The same from Python, with requests:

import requests

API = "https://api.puntersedge.online"
HEADERS = {"X-API-Key": "YOUR_KEY"}

templates = {
    "mode": "source",
    "per_bookmaker": {
        "ladbrokes_au": "https://your-tracker.example/click?aff=YOUR_ID&dest={url}",
        "unibet": "https://your-tracker.example/go?pid=YOUR_ID&url={url}",
        "playup": "none",
    },
}
r = requests.put(f"{API}/v1/link-templates", json=templates, headers=HEADERS, timeout=20)
r.raise_for_status()
for p in r.json()["preview"]:
    print(p["bookmaker"], "->", p["source_link"])

A PUT replaces the whole document, so send every rule each time. It takes effect on your next request.

3. Put the link on your page

Use the *_link field as the link for the price. It is present when there is something to link. When it is absent, the bookmaker gave no race link or your rule for that book is "none": show the price without a link.

The *_url fields are unchanged, so code that already reads them keeps working. From Python, every price on the next three Australian horse races with its link:

import requests

API = "https://api.puntersedge.online"
HEADERS = {"X-API-Key": "YOUR_KEY"}

races = requests.get(f"{API}/v1/racing/next-to-go", headers=HEADERS, timeout=20,
                     params={"country": "AU", "categories": "horse", "num_races": 3}).json()
for race in races:
    for runner in race["runners"]:
        for leg in runner["bookmakers"]:
            link = leg.get("source_link")   # absent: show the price without a link
            print(race["venue"], race["race_number"], runner["name"], leg["key"],
                  leg.get("win_price"), link or "(no link)")

From JavaScript on your server, the win market for the next horse race as price cells, each linked through your template where it has a link:

// Node 18+ (fetch is built in). Run it on your server: never put your API key in browser code.
const API = "https://api.puntersedge.online";
const headers = { "X-API-Key": process.env.PE_API_KEY };

const races = await (await fetch(
  `${API}/v1/racing/next-to-go?country=AU&categories=horse&num_races=1`, { headers })).json();
const { markets } = await (await fetch(
  `${API}/v1/racing/markets?race_id=${races[0].race_id}`, { headers })).json();

const win = markets.find((m) => m.market === "win");
for (const book of win.bookmakers) {
  for (const r of book.runners) {
    const price = r.price.toFixed(2);
    const cell = r.source_link
      ? `<a href="${r.source_link}" rel="sponsored noopener" target="_blank">${price}</a>`
      : price;
    console.log(book.key, r.number, r.name, cell);
  }
}

Mark affiliate links rel="sponsored", which is how Google asks for paid links to be labelled.

Betslip links

Some bookmakers also return a betslip link that opens with the runner already selected: Unibet and TAB in a web browser, Ladbrokes and Neds in their apps. Your templates apply to these as well. Ladbrokes and Neds betslip links carry betslip_app_only: true. In a desktop browser they go to the app download page, so on desktop use source_link for those two.

Check, change or remove

Three things to check with each affiliate programme

The credit on your page

Templates change where a price links, not what your licence asks of the page. From section 8.3 of the terms:

Wherever the Display or Commercial licence lets you show our prices to other people, every surface that displays them must carry a visible Prices by PuntersEdge credit linking to puntersedge.online, legible at the size it is shown.

Where our responses name the bookmaker a price came from, you must not attribute it to a different bookmaker or imply that any bookmaker supplies or endorses you.

Because each template belongs to one bookmaker, every link already goes to the book that quoted the price. The white-label widget on Platform is the version without the credit.

This site contains wagering-related analysis and is intended for Australian users aged 18+. Gambling involves risk. Please gamble responsibly.