curl --request GET \
--url https://api.apinn.io/api/history \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.apinn.io/api/history"
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://api.apinn.io/api/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apinn.io/api/history",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.apinn.io/api/history"
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))
}HttpResponse<String> response = Unirest.get("https://api.apinn.io/api/history")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apinn.io/api/history")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"opening": [
{
"event_id": 123,
"period": 123,
"market": "moneyline",
"line": 123,
"units": "<string>",
"odds1": 123,
"odds0": 123,
"odds2": 123,
"todds1": 123,
"todds0": 123,
"todds2": 123,
"line_id": 123,
"alt_line_id": 123,
"cutoff": "<string>",
"max_win": 123,
"score_home": 123,
"score_away": 123,
"red_cards_home": 123,
"red_cards_away": 123,
"status": 123,
"timestamp": "<string>",
"true_odds_by_model": {}
}
],
"closing": [
{
"event_id": 123,
"period": 123,
"market": "moneyline",
"line": 123,
"units": "<string>",
"odds1": 123,
"odds0": 123,
"odds2": 123,
"todds1": 123,
"todds0": 123,
"todds2": 123,
"line_id": 123,
"alt_line_id": 123,
"cutoff": "<string>",
"max_win": 123,
"score_home": 123,
"score_away": 123,
"red_cards_home": 123,
"red_cards_away": 123,
"status": 123,
"timestamp": "<string>",
"true_odds_by_model": {}
}
],
"history": [
{
"event_id": 123,
"period": 123,
"market": "moneyline",
"line": 123,
"units": "<string>",
"odds1": 123,
"odds0": 123,
"odds2": 123,
"todds1": 123,
"todds0": 123,
"todds2": 123,
"line_id": 123,
"alt_line_id": 123,
"cutoff": "<string>",
"max_win": 123,
"score_home": 123,
"score_away": 123,
"red_cards_home": 123,
"red_cards_away": 123,
"status": 123,
"timestamp": "<string>"
}
]
}Mouvement complet (ouverture + clôture + timeline)
Combine ouverture, clôture et la timeline complète d’un événement en une réponse — pratique pour tracer le graphe de mouvement.
Ce que contient la timeline : un point par CHANGEMENT réel de la ligne, jamais de répétition. Un point est créé dès que l’un de ces champs bouge : les cotes (odds1/odds0/odds2), la limite de mise (max_win) ou le statut (status, ouvert ↔ suspendu). Les valeurs identiques au point précédent ne sont pas stockées : la série est déjà dédoublonnée, un client peut la tracer telle quelle. max_win est donc historisé au même titre que le prix — Pinnacle relève ou abaisse ses limites sans forcément toucher aux cotes, et ce mouvement est un signal de confiance à part entière.
Isoler un seul pari. Sans filtre, la timeline mêle toutes les lignes du match : un match de basket avec ses lignes alternatives dépasse couramment 24 000 points répartis sur plus de 400 paris. Deux façons de n’en demander qu’un — au choix, selon ce que vous avez sous la main :
market+period+line: le filtre descend dans la requête, donc vous ne payez ni la lecture ni le transfert du reste. Pour un marché sans ligne (moneyline), passezline=nullouline=— l’omettre signifie « aucun filtre sur la ligne », ce qui n’est pas la même chose.line_id: l’identifiant renvoyé par /api/odds ou par un appel précédent. Pratique quand vous suivez déjà une ligne, mais le filtre s’applique après lecture (cet entier est un hachage non réversible), donc le gain porte sur la réponse et non sur la base.
Les filtres s’appliquent aussi à opening et closing : vous recevez l’ouverture et la clôture DU pari demandé, pas celles des 414 autres.
curl --request GET \
--url https://api.apinn.io/api/history \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.apinn.io/api/history"
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://api.apinn.io/api/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apinn.io/api/history",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.apinn.io/api/history"
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))
}HttpResponse<String> response = Unirest.get("https://api.apinn.io/api/history")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apinn.io/api/history")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"opening": [
{
"event_id": 123,
"period": 123,
"market": "moneyline",
"line": 123,
"units": "<string>",
"odds1": 123,
"odds0": 123,
"odds2": 123,
"todds1": 123,
"todds0": 123,
"todds2": 123,
"line_id": 123,
"alt_line_id": 123,
"cutoff": "<string>",
"max_win": 123,
"score_home": 123,
"score_away": 123,
"red_cards_home": 123,
"red_cards_away": 123,
"status": 123,
"timestamp": "<string>",
"true_odds_by_model": {}
}
],
"closing": [
{
"event_id": 123,
"period": 123,
"market": "moneyline",
"line": 123,
"units": "<string>",
"odds1": 123,
"odds0": 123,
"odds2": 123,
"todds1": 123,
"todds0": 123,
"todds2": 123,
"line_id": 123,
"alt_line_id": 123,
"cutoff": "<string>",
"max_win": 123,
"score_home": 123,
"score_away": 123,
"red_cards_home": 123,
"red_cards_away": 123,
"status": 123,
"timestamp": "<string>",
"true_odds_by_model": {}
}
],
"history": [
{
"event_id": 123,
"period": 123,
"market": "moneyline",
"line": 123,
"units": "<string>",
"odds1": 123,
"odds0": 123,
"odds2": 123,
"todds1": 123,
"todds0": 123,
"todds2": 123,
"line_id": 123,
"alt_line_id": 123,
"cutoff": "<string>",
"max_win": 123,
"score_home": 123,
"score_away": 123,
"red_cards_home": 123,
"red_cards_away": 123,
"status": 123,
"timestamp": "<string>"
}
]
}Autorisations
Paramètres de requête
Restreint la timeline à un marché : moneyline, spread, totals, team_total…
Période du pari (0 = match entier, 1 = 1re mi-temps/manche…).
Valeur de la ligne (handicap ou total). Pour un marché SANS ligne, passez null ou une valeur vide — omettre le paramètre ne filtre pas.
Identifiant de la ligne, tel que renvoyé par /api/odds ou /api/history. Filtre appliqué après lecture.