Quickstart
Obtén tu primer feed emparejado por REST con una clave gratuita y luego conecta el stream en tiempo real.
Esto te lleva de cero a datos en vivo en unos dos minutos. La primera mitad funciona con una clave gratuita. La segunda mitad conecta el stream en tiempo real y necesita un plan Basic o Pro.
Primero, crea una clave de API. Abre el panel de control, inicia sesión con GitHub o Google, y crea una clave. Se muestra una sola vez, así que cópiala en un lugar seguro. Toda clave nueva empieza en Free, que es todo lo que necesitas para la primera mitad.
El feed emparejado por REST
La instantánea REST te da el feed emparejado, con precio en la vista de arb cuando la pides. Pide un solo deporte para mantener la respuesta pequeña. Envía tu clave como token bearer.
curl -s "https://api.dino.markets/v2/markets?signal=arb&sport=baseball" \
-H "Authorization: Bearer sk_live_..."Recibes la instantánea de ese deporte. Aquí hay un arb confirmado:
{
"count": 1,
"sport": "baseball",
"has_more": false,
"markets": [
{
"id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2",
"slug": null,
"sport": "baseball",
"league": "MLB",
"title": "Nyy vs Bos",
"home": null,
"away": null,
"start_time": "2026-07-01T23:05:00+00:00",
"status": "open",
"match": "high_confidence",
"signal": "arb",
"spread_pts": 2.0,
"potential_arb_pct": 1.83,
"coverage": { "kalshi": true, "polymarket": true },
"outcomes": [
{ "key": "NYY", "name": "NYY", "kalshi": 0.52, "polymarket": 0.54, "cheaper": "kalshi" },
{ "key": "BOS", "name": "BOS", "kalshi": 0.50, "polymarket": 0.46, "cheaper": "polymarket" }
],
"result": null,
"updated_at": "2026-07-01T22:55:00+00:00",
"priced_at": "2026-07-01T22:55:00+00:00",
"links": { "kalshi": "https://kalshi.com/markets/KXMLBGAME-26JUL01NYYBOS", "polymarket": null }
}
]
}
GET /v2/markets?signal=arb devuelve el objeto de mercado canónico, con precio. potential_arb_pct es el retorno bruto ask-to-ask, antes de las comisiones de la plataforma. outcomes lista cada resultado del mercado con su precio en ambas plataformas y cuál de ellas tiene el ask más bajo (cheaper). signal es "arb" cuando el motor de coincidencia ha confirmado la paridad de resolución entre plataformas en el resultado decidido; cualquier otra cosa, incluida una brecha emparejada con riesgo de resolución divulgado, vuelve como "spread". En cualquier caso, lee settlement.risks antes de actuar. Añade include=settlement o llama al endpoint de detalle de abajo.
Para el detalle completo (identificadores de plataforma, confianza, divulgación de resolución), llama a GET /v2/pairs/{market_id} usando el id de la fila. Ese detalle solo cambia cuando el motor de coincidencia vuelve a analizar el texto en vivo, así que puedes cachearlo.
Cuando no hay nada abierto, markets es un array vacío y count es 0. Ese es el estado de reposo normal entre arbs, no un error. Puedes acotar aún más la instantánea con sport y limit.
El stream en tiempo real
La instantánea REST va unos dos minutos por detrás, así que es para explorar. Para actuar sobre un arb en el instante en que se abre, lee el stream de WebSocket. Esto necesita una clave Basic o Pro.
El stream es un handshake de dos pasos. Emites un ticket de corta duración por REST, y luego abres el socket con él. Una clave Free recibe un 402 aquí con un enlace para hacer upgrade.
Paso uno, emite un ticket. Es válido por unos 120 segundos:
curl -s -X POST "https://api.dino.markets/v1/stream/token" \
-H "Authorization: Bearer sk_live_..."
{
"ticket": "eyJhbGciOi...",
"ws_url": "wss://stream.dino.markets/connection/websocket",
"expires_in": 120,
"allowed": {
"channels": ["markets:all", "status"],
"max_conns": 3
}
}
Paso dos, conecta. El stream habla el protocolo Centrifugo, así que usa el cliente centrifuge para tu lenguaje y pasa el ticket en los datos de conexión bajo t. No te suscribes a mano. El servidor lee tu plan desde el ticket y envía los canales a los que tienes derecho.
import { Centrifuge } from "centrifuge";
const centrifuge = new Centrifuge("wss://stream.dino.markets/connection/websocket", {
data: { t: ticket },
});
centrifuge.on("publication", (ctx) => {
console.log(ctx.channel, ctx.data);
});
centrifuge.connect();Los mensajes se envían en el instante en que algo cambia: los frames de estado market y de delta price en los canales markets:*; cuando el signal de un pair es arb, sus frames también llevan los libros de profundidad por resultado y max_stake. La página del stream de WebSocket cubre cada forma.
Siguiente
La referencia del objeto Market cubre la forma del objeto canónico, el array outcomes, los tipos de signal y el envelope del stream. La página del stream de WebSocket cubre cómo conectar y cómo recuperarse tras una desconexión. Para los identificadores de plataforma y los términos de resolución, usa GET /v2/pairs/{market_id} documentado en la referencia REST.