Hire Me
← All Writing Betfair

Introduction to the Betfair Exchange API — Architecture, Endpoints, and Getting Started in Java

An overview of the Betfair Exchange API — what it offers, how the REST and Streaming APIs compare, how to get credentials, and what a first Java integration looks like.

The Betfair Exchange API is one of the most complete betting market data APIs available. Unlike a traditional bookmaker’s feed, it exposes the underlying exchange: every unmatched order, every matched trade, live price changes in milliseconds, and the ability to place, update, and cancel orders programmatically. For a developer building a trading system, it is both the data source and the execution venue.

What the API offers

The API has two primary interfaces:

REST API (api.betfair.com): Request/response. Catalogue data (markets, events, runners), market books (current prices), account information, and order operations. You poll for updates.

Streaming API (stream-api.betfair.com): Persistent TCP connection. Push-based price and order updates. Millisecond latency. The right choice for any system that needs to act on price movement.

Most production systems use both: the REST API to catalogue and set up markets, the Streaming API to receive live data.

Getting credentials

You need three things to call the API:

  1. Betfair account with API access enabled (requires a request to Betfair)
  2. Application key — a string that identifies your application, assigned when you register an API application in your account settings
  3. Session token — obtained by authenticating at the start of each session; expires after 4 hours of inactivity

For interactive use (scripts, one-off tools), interactive login via username + password is sufficient. For server-side applications that run unattended, certificate-based non-interactive login is required — the certificate replaces the password and enables login without human interaction.

A minimal Java client

Add the necessary HTTP dependencies:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

A simple REST call to list UK horse racing markets:

public class BetfairApiExample {

    private static final String API_URL =
        "https://api.betfair.com/exchange/betting/rest/v1.0/";

    private final HttpClient httpClient = HttpClient.newHttpClient();
    private final ObjectMapper mapper    = new ObjectMapper()
        .registerModule(new JavaTimeModule());

    public List<MarketCatalogue> listUkHorseRacingMarkets(
        String sessionToken, String appKey) throws Exception {

        String requestBody = """
            {
              "filter": {
                "eventTypeIds": ["7"],
                "marketCountries": ["GB"],
                "marketTypes": ["WIN"]
              },
              "maxResults": 10,
              "marketProjection": ["MARKET_DESCRIPTION", "RUNNER_DESCRIPTION", "EVENT"]
            }
            """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(API_URL + "listMarketCatalogue/"))
            .header("X-Authentication", sessionToken)
            .header("X-Application",    appKey)
            .header("Content-Type",     "application/json")
            .header("Accept",           "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();

        HttpResponse<String> response =
            httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        return mapper.readValue(response.body(),
            mapper.getTypeFactory().constructCollectionType(List.class, MarketCatalogue.class));
    }
}

Response structure

The API returns JSON. A MarketCatalogue entry contains:

The selectionId (long integer) is the stable identifier for a runner across markets. The same horse has the same selection ID in all markets for that race.

Key API operations

Operation Purpose
listMarketCatalogue Browse available markets with metadata
listMarketBook Current prices and matched volumes
placeOrders Place back or lay bets
updateOrders Change price or size of an open order
cancelOrders Cancel open orders
listCurrentOrders View your open orders
listClearedOrders View settled bets
getAccountFunds Check available balance

Rate limits

Betfair imposes rate limits on the REST API — both request counts per second and data weight (each market request has a data cost). Exceeding limits results in TOO_MANY_REQUESTS or REQUEST_SIZE_EXCEEDS_LIMIT errors. The Streaming API has no equivalent rate limit — it pushes updates to you.

The application key: demo vs production

Betfair issues two application keys per application: a delayed key (free, with ~60-second price delays) and a live key (requires a minimum trading history). Development and backtesting can use the delayed key; live trading requires the live key.

Both keys are obtained from your account settings → API Access → Developer App Keys.

With credentials in hand and the basic HTTP structure understood, the next steps are certificate-based authentication for production use, and streaming API subscription for live price data.

If you’re starting a Betfair Exchange API integration in Java and want help with the architecture, get in touch.

Samuel Jackson

Samuel Jackson

Senior Java Back End Developer & Contractor

Senior Java Back End Developer — Betfair Exchange API specialist, Spring Boot, AWS, and event-driven architecture. 20+ years delivering high-performance systems across betting, finance, energy, retail, and government. Available for Java contracting.