On the wire · 05:10:51 UTC Live 585 · Prematch 14,343 · Markets 57,146 Vol. I · No. 5 · Friday 13 November 2026 wss://pinnfeed.io/v1/stream
PinnFeed
チュートリアル · Kotlin · WebSocket

Kotlin(OkHttp)でピナクルオッズWebSocket

更新日 · PinnFeed · 約1分で読めます

回答: OkHttpで wss://pinnfeed.io/v1/stream へ x-api-key 付き Request を作り、newWebSocket を呼び、onOpen で JSON subscribe を送り、サーバーの ping(20秒ごと)に {"type":"pong"} で返します。フレームは welcome、subscribed、snapshot 分割、その後 delta。Builder(99€/月)または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€/月)。3日間トライアル、カード必須。無料REST:signup。

よくある質問#

なぜBuilder?#

/v1/stream はBuilderまたはProが必要。Free/Hobbyは 403 plan_lacks_ws。

公式SDKは必要?#

不要。OkHttp + JSONで十分です。

成人向けの教育コンテンツですか?#

はい(18+)。

18歳以上の方を対象とした教育目的のコンテンツです。予想や利益の約束ではありません。日本では刑法により賭博は原則として禁止されています。

WebSocketプラン:Builder、月額99ユーロ

ピナクルのオッズを1本のWebSocketでリアルタイムに。全13競技、全マーケット、マージンなしのフェアオッズとクロージングオッズ。3日間無料、ワンクリックで解約できます。

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.