curl --request GET \
--url https://magicmarkets.com/v2/offers/ \
--header 'X-Api-Key: <api-key>'import requests
url = "https://magicmarkets.com/v2/offers/"
headers = {"X-Api-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Api-Key': '<api-key>'}};
fetch('https://magicmarkets.com/v2/offers/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://magicmarkets.com/v2/offers/"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Api-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}List offers for an event
Returns the stake available at each price, for each market on the named events. Each entry is the object the stream sends as ["offer", {...}].
A reply can be about 4 seconds behind the live prices: the stream updates every 2 seconds, and a client may cache the response for 2 seconds (Cache-Control: private, max-age=2). For live prices, register the event on the stream with register_event.
sport and event_id are required, with up to 20 events per request. GET /v2/events/ lists them.
bet_type limits the response to the named markets. It takes the same strings as POST /v2/betslips/, so a bet_type from here goes into a betslip unchanged.
market_type keeps the named market families, such as ah, ou or wdw. min_liquidity keeps a market when its max stakes, added up across its price_list, come to at least that many USDT.
Offers come back in event_id order, then bet_type order. Page with limit and after: pass the previous page’s last "{event_id},{bet_type}" as after. A page shorter than limit is the last one. Each page is read when it is requested, so for a consistent view of an event, use the stream.
Markets with no available stake are left out. for and against on one selection are two markets, each with its own bet_type. For a sport your account is not enabled for, the list is empty, as on the stream.
An event that has no prices at the moment, or that the feed does not know, returns no offers. The other events in the request still come back. Each event_id must have the form an event carries, such as 2026-06-15,1001,2002; any other form gets a 400.
curl --request GET \
--url https://magicmarkets.com/v2/offers/ \
--header 'X-Api-Key: <api-key>'import requests
url = "https://magicmarkets.com/v2/offers/"
headers = {"X-Api-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Api-Key': '<api-key>'}};
fetch('https://magicmarkets.com/v2/offers/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://magicmarkets.com/v2/offers/"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Api-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Authorizations
API key created from the magic-markets website
Query Parameters
Sport code. See "Sports & bet types" in the introduction.
Events to price. Repeatable, up to 20 per request. Each value is an event's event_id, such as 2026-06-15,1001,2002; any other form gets a 400.
1 - 20 elements^\d{4}-\d{2}-\d{2},[^,]+,[^,]+$Markets to keep. Repeatable, up to 100 values; omit for every market on the event. See "Sports & bet types" in the introduction.
100Market families to keep, as in an offer's market_type. Repeatable, up to 100 values; omit for every family.
100USDT. Keep markets whose max stakes, added up across the price_list, come to at least this.
x >= 0Offers per page.
1 <= x <= 5000Cursor - the previous page's last "{event_id},{bet_type}".

