On the wire · 05:05:24 UTC Live 584 · Prematch 14,345 · Markets 56,976 Vol. I · No. 5 · Friday 13 November 2026 wss://pinnfeed.io/v1/stream
PinnFeed
Tutorial · Kotlin · WebSocket

WebSocket de odds Pinnacle em Kotlin (OkHttp)

Atualizado em · PinnFeed · 1 min de leitura

Resposta: com OkHttp, construa um Request para wss://pinnfeed.io/v1/stream com cabeçalho x-api-key, chame newWebSocket, envie um JSON subscribe em onOpen, e responda {"type":"pong"} a cada ping do servidor (a cada 20 s). Frames: welcome, subscribed, partes snapshot, depois delta. Builder (99 €/mês) 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/mês). Teste de 3 dias; cartão obrigatório. REST gratis: signup.

Perguntas frequentes#

Porquê Builder?#

/v1/stream exige Builder ou Pro. Free/Hobby recebem 403 plan_lacks_ws.

Preciso de SDK oficial?#

Não — OkHttp + JSON bastam.

Conteúdo educativo para adultos?#

Sim (18+).

Conteúdo educativo para maiores de 18 anos. Sem palpites nem lucro garantido. No Brasil, aposte apenas em operadores autorizados pela SPA/MF.

O plano WebSocket: Builder, €99/mês.

Odds da Pinnacle em tempo real por um único WebSocket: os 13 esportes, todos os mercados, odds justas sem margem e odds de fechamento. 3 dias grátis, cancele com um clique.

Form K-1 · Free API key

Get your free API key.

One field. No password, no card: enter your email, click the link we send, and your key is on screen.

By continuing you agree to the Terms and Privacy Policy.

One free key per email. Link valid for 20 minutes.