Skip to main content
El feed de usuario transmite las actualizaciones de tu cuenta (órdenes, cruces, cancelaciones).

Mensajes

El feed de usuario envía cada actualización como un objeto JSON sin envoltorio (sin envoltorio de tupla). Todas las actualizaciones comparten un mismo envoltorio; la acción la determinan cuáles de unmatched / matched están rellenos y el valor de origin.

Envoltorio común

messageID es el id de entrada del stream que añade la streaming-api antes de enviar. Persiste el último que hayas procesado: es tu cursor de reproducción. Consulta Reproducir mensajes perdidos más abajo.

El bloque matched

Presente siempre que la actualización represente un cruce (matched != null). Cada campo de abajo se envía en cada cruce salvo los marcados como condicionales. Todos los valores son desde tu perspectiva: como taker ves el lado que tomaste; como maker ves el lado que colocaste.
No derives win a partir de risk. risk y win se redondean cada uno a 2 decimales de forma independiente desde el importe sin redondear, así que risk x odds puede discrepar de win en un céntimo. Contabiliza el valor win tal como llega; si falta, trata el mensaje como malformado en lugar de reconstruirlo.No trates amount como sinónimo de risk. En un cruce de taker amount excluye la comisión cobrada en caso de pérdida y risk la incluye. Contabilizar amount como tu riesgo subcontará la comisión en cada toma.
Las mismas cantidades en REST (obtener apuestas cruzadas) van formateadas como string a 2 decimales en lugar de números, y se calculan con un orden de comisión y redondeo ligeramente distinto. Reconcilia con un céntimo de tolerancia en lugar de igualdad exacta.

El bloque unmatched

Presente siempre que la actualización concierna a una orden que está (o deja de estar) en el libro: colocaciones, cancelaciones y el lado maker de un cruce. Las cuotas y los lados son desde la perspectiva del maker, es decir, lo que colocaste, no lo que el libro ofrece a los demás.
filled y remaining no son el mismo tipo de número. remaining es estado acumulado — lo que queda en el libro ahora mismo —, pero en un cruce filled describe solo ese evento. A lo largo de varios cruces parciales no suman: filled + remaining iguala a offered en el primer cruce y se desvía después.Para seguir cuánto de una orden en espera se ha cruzado, usa offered - remaining, o acumula filled tú mismo. No mezcles ambos.

Cómo identificar la acción

  • unmatched.filled === 0 && unmatched.offered > 0 -> orden colocada
  • unmatched.offered === 0 -> orden cancelada
  • matched != null && unmatched == null -> cruzado como taker
  • matched != null && unmatched != null -> cruzado como maker (cruce parcial si unmatched.remaining > 0)
Las actualizaciones de órdenes colocadas con orderType: "postArb" también llevan isPostArb: true dentro de matched / unmatched (en actualizaciones de colocación, cruce y cancelación); el campo se omite en el resto.

Semántica de side y market por tipo de apuesta

El significado de side (y qué campos extra aparecen) dentro de matched / unmatched depende de type: market solo está presente en actualizaciones moneyline1x2: nombra el resultado a 3 vías del que trata el mercado (equipo local, equipo visitante o el empate), y side indica si la apuesta es yes o no sobre ese resultado. Todos los campos son desde tu perspectiva: como maker ves el lado que colocaste; como taker ves el lado que tomaste.

Acción: orden colocada

Se puso una oferta nueva en el libro. unmatched.filled es 0, unmatched.offered > 0 y matched es null.

Acción: orden cancelada

El usuario (o el sistema en su nombre) canceló una oferta. El campo distintivo es unmatched.offered === 0.

Acción: orden cruzada (taker)

El usuario tomó la oferta de otro. unmatched es null, matched lleva el cruce y origin es "wager".

Acción: orden cruzada (maker, cruce parcial)

Alguien golpeó la oferta colocada del usuario. Tanto matched como unmatched están rellenos; unmatched.remaining muestra lo que sigue en el libro. Como unmatched está definido, origin es "offer".

Acción: orden cruzada (moneyline1x2)

Los cruces en mercados de fútbol a 3 vías llevan el par market + side descrito arriba en lugar de un side hex de participante. Aquí el usuario tomó “yes” sobre el equipo local a +120 (una apuesta a que gana Arsenal):
Observa las dos perspectivas del mismo cruce: el taker ve side: "yes" a +120, el maker ve side: "no" a -120 sobre el mismo market.

Reproducir mensajes perdidos

El feed de usuario v2 admite recuperación de huecos tras una desconexión. Cada mensaje lleva un messageID (un id de entrada de stream monótonamente creciente, p. ej. "1751552702114-0"). Si se cae la conexión, puedes obtener exactamente los mensajes que te perdiste.

Endpoint

La autenticación es la misma que en el WebSocket: token en la cabecera Authorization, la cabecera Auth o el parámetro de consulta token. Solo se devuelven mensajes que pertenecen al usuario autenticado.

Respuesta: success

Tu afterID seguía presente en el historial retenido, así que la lista devuelta es un relleno de hueco completo: no se perdió nada entre afterID y beforeID:
Aplica los mensajes en orden y reanuda el procesamiento de los mensajes en vivo.

Respuesta: cache_expired

Tu afterID ya salió del historial retenido, así que el servidor no puede demostrar que la reproducción es completa:
availableMessages es lo que sigue retenido, de más antiguo a más reciente. Los mensajes anteriores a la ventana de retención no se pueden recuperar con la reproducción: reconecta de inmediato en lugar de confiar en una mirada atrás larga.

Ejemplo: cliente que reconecta con reproducción

Un cliente Node.js completo (el keepalive ping/pong se omite por brevedad; consulta el inicio rápido al principio de esta página). Dos cosas lo mantienen correcto: cada mensaje —en vivo, en búfer o reproducido— pasa por una sola comprobación de cursor que solo avanza, y una reproducción fallida reconecta en lugar de pasar a vivo por encima del hueco.