WebSocket de cotes Pinnacle en Kotlin (OkHttp)
Réponse : avec OkHttp, construisez une Request vers wss://pinnfeed.io/v1/stream avec l'en-tête x-api-key, appelez newWebSocket, envoyez un JSON subscribe dans onOpen, et répondez {"type":"pong"} à chaque ping serveur (toutes les 20 s). Frames : welcome, subscribed, parties snapshot, puis delta. Builder (99 €/mois) ou Pro.
Gradle#
dependencies {
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("org.json:json:20240303")
}
Client#
import okhttp3.*
import org.json.JSONObject
import java.util.concurrent.TimeUnit
fun main() {
val key = System.getenv("PINNFEED_KEY") ?: error("set PINNFEED_KEY") // ps_live_...
val client = OkHttpClient.Builder().readTimeout(0, TimeUnit.MILLISECONDS).build()
fun connect(delayMs: Long = 0) {
Thread.sleep(delayMs)
val req = Request.Builder().url("wss://pinnfeed.io/v1/stream").header("x-api-key", key).build()
client.newWebSocket(req, object : WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) {
ws.send("""{"type":"subscribe","sports":["soccer"],"markets":["moneyline"],"main":true}""")
}
override fun onMessage(ws: WebSocket, text: String) {
val msg = JSONObject(text)
when (msg.getString("type")) {
"ping" -> ws.send("""{"type":"pong"}""")
"delta" -> {
val changes = msg.getJSONArray("changes")
for (i in 0 until changes.length()) {
val ch = changes.getJSONObject(i)
if (ch.getString("kind") == "market" && ch.getString("op") == "upsert") {
val m = ch.getJSONObject("market")
if (m.optDouble("maxStake", 0.0) >= 100) println("${m.getLong("eventId")} ${m.getJSONArray("outcomes")}")
}
}
}
"error" -> println("error ${msg.optString("code")}: ${msg.optString("message")}")
}
}
override fun onClosed(ws: WebSocket, code: Int, reason: String) {
println("closed $code $reason")
if (code != 4001) connect(2000) // 4001 = key revoked
}
override fun onFailure(ws: WebSocket, t: Throwable, response: Response?) {
println("failure ${response?.code} ${t.message}")
connect(5000)
}
})
}
connect()
}
CTA#
Builder (99 €/mois). Essai 3 jours ; carte requise. REST gratuit : inscription.
Questions fréquentes#
Pourquoi Builder ?#
/v1/stream exige Builder ou Pro. Free/Hobby reçoivent 403 plan_lacks_ws.
Faut-il un SDK officiel ?#
Non — OkHttp + JSON suffisent.
Contenu éducatif pour adultes ?#
Oui (18+).
Contenu éducatif pour adultes (18+) : ni pronostics ni promesse de gain. En France, seuls les opérateurs agréés par l'ANJ peuvent proposer des paris en ligne.