asyncapi: '2.6.0'
id: 'urn:com:betfair:exchange:stream-api'
info:
title: Betfair Exchange Stream API (SSL/TCP)
version: '1.0.0'
description: |
AsyncAPI 2.6 description of the Betfair **Exchange Stream API** - Betfair's
low-latency, subscription-based push channel for market and order changes.
IMPORTANT TRANSPORT NOTE: this is **NOT a WebSocket API**. The Exchange
Stream API is a persistent **raw SSL/TCP socket** to
`stream-api.betfair.com` on **port 443**, over which messages are exchanged
as **CRLF-delimited JSON** - one complete JSON object per line, terminated
by `\r\n`, with JSON pretty-printing turned off. Betfair's own
documentation states that any attempted WebSocket connection will be
refused. `secure-tcp` is used as the AsyncAPI server protocol; the exact
socket semantics are documented here and in `info.x-transport-notes`.
Flow: open the SSL socket, read the initial `connection` message, send an
`authentication` request (appKey + session token), then send
`marketSubscription` and/or `orderSubscription` requests. The server then
pushes `mcm` (market change) and `ocm` (order change) messages plus periodic
`status` and `heartbeat` frames. A `heartbeat` request may be sent to keep
the socket alive; a message must be sent within 15 seconds of connecting or
the server returns a TIMEOUT status.
Every RequestMessage carries a client-supplied integer `id`, echoed back on
the corresponding `status` ResponseMessage. The `op` field on every message
identifies its type for correct (de)serialization.
contact:
name: API Evangelist
email: kin@apievangelist.com
url: https://apievangelist.com
license:
name: API documentation - Betfair Developer Program Terms
url: https://developer.betfair.com/
x-transport-notes:
transport: Raw SSL/TCP socket (persistent)
host: stream-api.betfair.com
integrationHost: stream-api-integration.betfair.com
port: 443
framing: CRLF-delimited JSON (one JSON object per line, terminated by \r\n)
prettyPrint: must be disabled
isWebSocket: false
webSocketRefused: true
connectTimeoutSeconds: 15
source: https://github.com/betfair/stream-api-sample-code
defaultContentType: application/json
servers:
production:
url: stream-api.betfair.com:443
protocol: secure-tcp
description: |
Production Exchange Stream endpoint. Establish an SSL/TLS socket to this
host:port and exchange CRLF-delimited JSON messages. This is a raw TCP
socket over SSL - not WebSocket and not HTTP.
integration:
url: stream-api-integration.betfair.com:443
protocol: secure-tcp
description: Integration/test Exchange Stream endpoint with the same protocol.
channels:
authentication:
description: |
Client -> server request that authenticates the socket using the
Application Key and the session token (ssoid) from identity SSO login.
Must be sent before any subscription. The server replies with a `status`
message on the response stream.
publish:
operationId: sendAuthentication
summary: Authenticate the stream connection.
message:
$ref: '#/components/messages/AuthenticationMessage'
marketSubscription:
description: |
Client -> server request subscribing to market changes for a set of
markets (via a marketFilter) at a chosen priceData/ladder level (via a
marketDataFilter). The server then pushes `mcm` messages on the change
stream.
publish:
operationId: sendMarketSubscription
summary: Subscribe to market changes.
message:
$ref: '#/components/messages/MarketSubscriptionMessage'
orderSubscription:
description: |
Client -> server request subscribing to the customer's order changes. The
server then pushes `ocm` messages on the change stream.
publish:
operationId: sendOrderSubscription
summary: Subscribe to order changes.
message:
$ref: '#/components/messages/OrderSubscriptionMessage'
heartbeatRequest:
description: |
Client -> server keep-alive request (op=heartbeat). Used to keep the
socket active and detect a broken connection; the server replies with a
`status` message.
publish:
operationId: sendHeartbeat
summary: Send a keep-alive heartbeat request.
message:
$ref: '#/components/messages/HeartbeatRequestMessage'
connectionStream:
description: Server -> client initial `connection` message sent on socket open, carrying the connectionId.
subscribe:
operationId: receiveConnection
summary: Receive the initial connection frame.
message:
$ref: '#/components/messages/ConnectionMessage'
statusStream:
description: |
Server -> client `status` messages - the acknowledgement/response to a
request `id`, plus connection health (connectionsAvailable) and error
details (statusCode, errorCode, errorMessage).
subscribe:
operationId: receiveStatus
summary: Receive status / acknowledgement frames.
message:
$ref: '#/components/messages/StatusMessage'
marketChangeStream:
description: Server -> client `mcm` (Market Change Message) frames pushing price/status deltas for subscribed markets.
subscribe:
operationId: receiveMarketChange
summary: Receive market change messages.
message:
$ref: '#/components/messages/MarketChangeMessage'
orderChangeStream:
description: Server -> client `ocm` (Order Change Message) frames pushing order/matched deltas for the customer.
subscribe:
operationId: receiveOrderChange
summary: Receive order change messages.
message:
$ref: '#/components/messages/OrderChangeMessage'
components:
messages:
AuthenticationMessage:
name: authentication
title: Authentication request
summary: Authenticates the socket with appKey + session token.
contentType: application/json
payload:
type: object
required: [op, id, appKey, session]
properties:
op:
type: string
enum: [authentication]
id:
type: integer
description: Client-supplied request id, echoed on the status response.
appKey:
type: string
session:
type: string
description: Session token (ssoid) from identity SSO login.
examples:
- name: auth
payload:
op: authentication
id: 1
appKey: 'YOUR_APP_KEY'
session: 'YOUR_SESSION_TOKEN'
MarketSubscriptionMessage:
name: marketSubscription
title: Market subscription request
contentType: application/json
payload:
type: object
required: [op, id]
properties:
op:
type: string
enum: [marketSubscription]
id:
type: integer
marketFilter:
type: object
properties:
marketIds:
type: array
items:
type: string
eventTypeIds:
type: array
items:
type: string
countryCodes:
type: array
items:
type: string
marketTypes:
type: array
items:
type: string
marketDataFilter:
type: object
properties:
ladderLevels:
type: integer
maximum: 10
fields:
type: array
items:
type: string
enum: [EX_BEST_OFFERS, EX_ALL_OFFERS, EX_TRADED, EX_TRADED_VOL, EX_LTP, EX_MARKET_DEF, SP_TRADED, SP_PROJECTED, EX_BEST_OFFERS_DISP]
conflateMs:
type: integer
heartbeatMs:
type: integer
examples:
- name: marketSub
payload:
op: marketSubscription
id: 2
marketFilter:
marketIds: ['1.234567890']
marketDataFilter:
ladderLevels: 3
fields: [EX_BEST_OFFERS, EX_LTP]
OrderSubscriptionMessage:
name: orderSubscription
title: Order subscription request
contentType: application/json
payload:
type: object
required: [op, id]
properties:
op:
type: string
enum: [orderSubscription]
id:
type: integer
orderFilter:
type: object
properties:
includeOverallPosition:
type: boolean
partitionMatchedByStrategyRef:
type: boolean
conflateMs:
type: integer
heartbeatMs:
type: integer
HeartbeatRequestMessage:
name: heartbeatRequest
title: Heartbeat request
contentType: application/json
payload:
type: object
required: [op, id]
properties:
op:
type: string
enum: [heartbeat]
id:
type: integer
ConnectionMessage:
name: connection
title: Connection frame
contentType: application/json
payload:
type: object
properties:
op:
type: string
enum: [connection]
connectionId:
type: string
examples:
- name: connection
payload:
op: connection
connectionId: '206-221216154618-94060'
StatusMessage:
name: status
title: Status / acknowledgement frame
contentType: application/json
payload:
type: object
properties:
op:
type: string
enum: [status]
id:
type: integer
description: Echoes the request id being acknowledged.
statusCode:
type: string
enum: [SUCCESS, FAILURE]
errorCode:
type: string
enum:
- NO_APP_KEY
- INVALID_APP_KEY
- NO_SESSION
- INVALID_SESSION_INFORMATION
- NOT_AUTHORIZED
- INVALID_INPUT
- INVALID_CLOCK
- UNEXPECTED_ERROR
- TIMEOUT
- SUBSCRIPTION_LIMIT_EXCEEDED
- INVALID_REQUEST
- CONNECTION_FAILED
- MAX_CONNECTION_LIMIT_EXCEEDED
- TOO_MANY_REQUESTS
errorMessage:
type: string
connectionClosed:
type: boolean
connectionsAvailable:
type: integer
examples:
- name: ok
payload:
op: status
id: 1
statusCode: SUCCESS
connectionClosed: false
MarketChangeMessage:
name: mcm
title: Market Change Message
summary: Push of market price/status deltas.
contentType: application/json
payload:
type: object
properties:
op:
type: string
enum: [mcm]
id:
type: integer
ct:
type: string
enum: [SUB_IMAGE, RESUB_DELTA, HEARTBEAT]
description: Change type; absent for a normal delta.
clk:
type: string
description: Sequence token for this stream position.
initialClk:
type: string
conflateMs:
type: integer
heartbeatMs:
type: integer
pt:
type: integer
format: int64
description: Publish time (epoch millis).
mc:
type: array
description: Array of market changes.
items:
type: object
properties:
id:
type: string
description: Market id.
con:
type: boolean
description: Whether the data is conflated.
img:
type: boolean
description: Whether this is a full image (replace) vs delta.
tv:
type: number
description: Total value/volume matched.
marketDefinition:
type: object
rc:
type: array
description: Runner changes.
items:
type: object
properties:
id:
type: integer
format: int64
description: selectionId.
ltp:
type: number
description: Last traded price.
tv:
type: number
batb:
type: array
description: Best available to back [level, price, size].
items:
type: array
items:
type: number
batl:
type: array
description: Best available to lay [level, price, size].
items:
type: array
items:
type: number
examples:
- name: heartbeatFrame
payload:
op: mcm
id: 2
ct: HEARTBEAT
clk: 'AAAAAAAA'
pt: 1671205578000
- name: delta
payload:
op: mcm
id: 2
clk: 'ABAQAB'
pt: 1671205579000
mc:
- id: '1.234567890'
tv: 12345.67
rc:
- id: 47972
ltp: 3.4
batb: [[0, 3.35, 120.0]]
batl: [[0, 3.45, 90.0]]
OrderChangeMessage:
name: ocm
title: Order Change Message
summary: Push of the customer's order/matched deltas.
contentType: application/json
payload:
type: object
properties:
op:
type: string
enum: [ocm]
id:
type: integer
ct:
type: string
enum: [SUB_IMAGE, RESUB_DELTA, HEARTBEAT]
clk:
type: string
pt:
type: integer
format: int64
oc:
type: array
description: Order changes by market.
items:
type: object
properties:
id:
type: string
description: Market id.
orc:
type: array
description: Order runner changes.
items:
type: object
properties:
id:
type: integer
format: int64
description: selectionId.
uo:
type: array
description: Unmatched orders.
items:
type: object
mb:
type: array
description: Matched backs [price, size].
items:
type: array
items:
type: number
ml:
type: array
description: Matched lays [price, size].
items:
type: array
items:
type: number
ⓘ
Where this information came from
This is an independent, third-party profile of Betfair Exchange Stream API, published by
API Evangelist. We do not operate, host, resell, or
support these APIs, and we are not affiliated with or endorsed by the company unless stated above.
Everything here is built from publicly available information — the company's own site,
developer portal, documentation, public repositories, and the specifications it publishes for public use.
Nothing is obtained by breaching a system, defeating an access control, or using credentials.
The Kin Score and Agent Readiness rating are independently calculated assessments of a company's
public API artifacts, scored against a published rubric. They are not certifications,
endorsements, security assessments, or audits.
Corrections, re-scores, and removal are free — no partnership or purchase required, and
you do not need to justify the request. A removed company is recorded as unrated, never scored
zero for having asked. Acknowledgement within one business day; removal within two.
info@apievangelist.com
·
Read the full data-sourcing policy →
On a security or compliance team? Put security in the subject line and
you will get a person, not a form — we will tell you exactly which public URLs this profile was built from.