Publicar eventos
Publica desde tu servidor usando tu clave Bird API y la clave y el secreto de la app de Realtime. Nunca incluyas el secreto de la app en código del cliente. Para que los clientes suscritos intercambien señales efímeras, usa eventos de cliente en canales privados o de presencia.
Una publicación mínima
Un evento requiere un nombre y al menos un canal. Su payload opcional puede contener cualquier objeto, arreglo o escalar JSON.
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({
apiKey: process.env.BIRD_API_KEY,
realtime: {
key: process.env.BIRD_REALTIME_KEY,
secret: process.env.BIRD_REALTIME_SECRET,
},
});
await bird.realtime.publish("rap_01krdgeqcxet5s7t44vh8rt9mg", {
event: "order-updated",
channels: ["orders"],
data: { id: 42, status: "shipped" },
});import os
from bird import Bird
client = Bird(
api_key=os.environ["BIRD_API_KEY"],
realtime_key=os.environ["BIRD_REALTIME_KEY"],
realtime_secret=os.environ["BIRD_REALTIME_SECRET"],
)
client.realtime.publish(
"rap_01krdgeqcxet5s7t44vh8rt9mg",
event="order-updated",
channels=["orders"],
data={"id": 42, "status": "shipped"},
)client, err := bird.NewClient(
option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
)
if err != nil {
log.Fatal(err)
}
_, err = client.Realtime.Publish(context.Background(), "rap_01krdgeqcxet5s7t44vh8rt9mg", bird.RealtimePublishParams{
Event: "order-updated",
Channels: []string{"orders"},
Data: map[string]any{"id": 42, "status": "shipped"},
})use MessageBird\Bird;
use MessageBird\RealtimeOptions;
use MessageBird\Wire\Model\RealtimePublish;
$bird = new Bird(
getenv('BIRD_API_KEY') ?: '',
realtime: new RealtimeOptions(
key: getenv('BIRD_REALTIME_KEY') ?: '',
secret: getenv('BIRD_REALTIME_SECRET') ?: '',
),
);
$bird->realtime->publish('rap_01krdgeqcxet5s7t44vh8rt9mg', (new RealtimePublish())
->setEvent('order-updated')
->setChannels(['orders'])
->setData(['id' => 42, 'status' => 'shipped']));curl -X POST https://us1.platform.bird.com/v1/realtime/apps/rap_01krdgeqcxet5s7t44vh8rt9mg/events \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "X-Realtime-Key: $BIRD_REALTIME_KEY" \
-H "X-Realtime-Secret: $BIRD_REALTIME_SECRET" \
-H "Content-Type: application/json" \
-d '{
"event": "order-updated",
"channels": ["orders"],
"data": { "id": 42, "status": "shipped" }
}'Los clientes vinculados a order-updated en orders reciben el evento. El API rechaza nombres publicados desde el servidor que comiencen con los prefijos de protocolo bird: o bird_internal:. Los nombres de eventos originados por el cliente deben comenzar con client-.
La solicitud y respuesta completas, incluidos todos los campos, están en la referencia de publicar un evento.
Qué significa un 200
La publicación se completa cuando el borde de Realtime acepta el evento. La entrega es asíncrona y no tiene confirmación por cliente. Un cliente que se desconecte durante la entrega puede perder el evento, y Realtime no lo reproduce tras reconectarse.
Almacena el estado persistente en tu base de datos. Usa eventos para anunciar cambios y haz que los clientes recarguen el estado actual tras reconectarse.
Transmitir a varios canales
Una sola llamada puede enviar el mismo evento a hasta 100 canales. Un canal private-encrypted- debe ser el único canal en su publicación porque cada canal cifrado usa una clave diferente. El API rechaza un fan-out cifrado con E23000. Consulta Canales cifrados.
await bird.realtime.publish(appId, {
event: "price-changed",
channels: ["ticker-btc", "ticker-eth", "ticker-sol"],
data: { at: "2026-07-31T09:00:00Z" },
});client.realtime.publish(
app_id,
event="price-changed",
channels=["ticker-btc", "ticker-eth", "ticker-sol"],
data={"at": "2026-07-31T09:00:00Z"},
)_, err := client.Realtime.Publish(context.Background(), appID, bird.RealtimePublishParams{
Event: "price-changed",
Channels: []string{"ticker-btc", "ticker-eth", "ticker-sol"},
Data: map[string]any{"at": "2026-07-31T09:00:00Z"},
})$bird->realtime->publish($appId, (new RealtimePublish())
->setEvent('price-changed')
->setChannels(['ticker-btc', 'ticker-eth', 'ticker-sol'])
->setData(['at' => '2026-07-31T09:00:00Z']));curl -X POST "https://us1.platform.bird.com/v1/realtime/apps/$APP_ID/events" \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "X-Realtime-Key: $BIRD_REALTIME_KEY" \
-H "X-Realtime-Secret: $BIRD_REALTIME_SECRET" \
-H "Content-Type: application/json" \
-d '{
"event": "price-changed",
"channels": ["ticker-btc", "ticker-eth", "ticker-sol"],
"data": { "at": "2026-07-31T09:00:00Z" }
}'Cada canal de destino cuenta como un mensaje independiente para el consumo. Este ejemplo cuenta como tres mensajes. Una publicación a 10.000 canales por usuario cuenta, por lo tanto, como 10.000 mensajes.
Agrupar eventos no relacionados en lotes
Una transmisión envía un evento a muchos canales. Un lote envía hasta 10 eventos diferentes, cada uno a un canal, en una sola solicitud.
await bird.realtime.publishBatch(appId, {
events: [
{ event: "order-updated", channels: ["orders-42"], data: { status: "shipped" } },
{ event: "stock-changed", channels: ["inventory-99"], data: { left: 3 } },
],
});client.realtime.publish_batch(
app_id,
events=[
{"event": "order-updated", "channels": ["orders-42"], "data": {"status": "shipped"}},
{"event": "stock-changed", "channels": ["inventory-99"], "data": {"left": 3}},
],
)_, err := client.Realtime.PublishBatch(context.Background(), appID, bird.RealtimePublishBatchParams{
Events: []bird.RealtimeBatchEventParams{
{Event: "order-updated", Channel: "orders-42", Data: map[string]any{"status": "shipped"}},
{Event: "stock-changed", Channel: "inventory-99", Data: map[string]any{"left": 3}},
},
})$bird->realtime->publishBatch($appId, (new RealtimeBatchPublish())
->setEvents([
(new RealtimeBatchEvent())->setEvent('order-updated')->setChannel('orders-42')->setData(['status' => 'shipped']),
(new RealtimeBatchEvent())->setEvent('stock-changed')->setChannel('inventory-99')->setData(['left' => 3]),
]));curl -X POST "https://us1.platform.bird.com/v1/realtime/apps/$APP_ID/batch-events" \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "X-Realtime-Key: $BIRD_REALTIME_KEY" \
-H "X-Realtime-Secret: $BIRD_REALTIME_SECRET" \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "event": "order-updated", "channel": "orders-42", "data": { "status": "shipped" } },
{ "event": "stock-changed", "channel": "inventory-99", "data": { "left": 3 } }
]
}'Usa un lote para combinar actualizaciones no relacionadas en una sola solicitud. Cada evento sigue contando por separado en el consumo, y un lote acepta como máximo 10 eventos. Consulta Publicar un lote.
Excluir al cliente que realizó la acción
Si un cliente ya aplicó su acción localmente, pasa su ID de conexión para evitar que la publicación resultante aplique el mismo cambio de nuevo. El borde omite solo esa conexión.
await bird.realtime.publish(appId, {
event: "message.created",
channels: ["presence-room-1"],
data: { body: "hello" },
exclude_connection_id: "26896.319537",
});client.realtime.publish(
app_id,
event="message.created",
channels=["presence-room-1"],
data={"body": "hello"},
exclude_connection_id="26896.319537",
)_, err := client.Realtime.Publish(context.Background(), appID, bird.RealtimePublishParams{
Event: "message.created",
Channels: []string{"presence-room-1"},
Data: map[string]any{"body": "hello"},
ExcludeConnectionID: "26896.319537",
})$bird->realtime->publish($appId, (new RealtimePublish())
->setEvent('message.created')
->setChannels(['presence-room-1'])
->setData(['body' => 'hello'])
->setExcludeConnectionId('26896.319537'));curl -X POST "https://us1.platform.bird.com/v1/realtime/apps/$APP_ID/events" \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "X-Realtime-Key: $BIRD_REALTIME_KEY" \
-H "X-Realtime-Secret: $BIRD_REALTIME_SECRET" \
-H "Content-Type: application/json" \
-d '{
"event": "message.created",
"channels": ["presence-room-1"],
"data": { "body": "hello" },
"exclude_connection_id": "26896.319537"
}'Lee el ID de la conexión actual del cliente e inclúyelo en la solicitud que desencadena el cambio. Otras pestañas usan conexiones separadas y siguen recibiendo el evento.
Leer el estado del canal al publicar
Usa include para devolver el estado de cada canal de destino en el momento de la publicación y evitar una solicitud de estado de canal aparte:
const result = await bird.realtime.publish(appId, {
event: "order-updated",
channels: ["presence-lobby"],
data: { id: 42 },
include: ["member_count", "connection_count"],
});result = client.realtime.publish(
app_id,
event="order-updated",
channels=["presence-lobby"],
data={"id": 42},
include=["member_count", "connection_count"],
)result, err := client.Realtime.Publish(context.Background(), appID, bird.RealtimePublishParams{
Event: "order-updated",
Channels: []string{"presence-lobby"},
Data: map[string]any{"id": 42},
Include: []bird.RealtimeChannelInclude{bird.RealtimeIncludeMemberCount, bird.RealtimeIncludeConnectionCount},
})$result = $bird->realtime->publish($appId, (new RealtimePublish())
->setEvent('order-updated')
->setChannels(['presence-lobby'])
->setData(['id' => 42])
->setInclude(['member_count', 'connection_count']));curl -X POST "https://us1.platform.bird.com/v1/realtime/apps/$APP_ID/events" \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "X-Realtime-Key: $BIRD_REALTIME_KEY" \
-H "X-Realtime-Secret: $BIRD_REALTIME_SECRET" \
-H "Content-Type: application/json" \
-d '{
"event": "order-updated",
"channels": ["presence-lobby"],
"data": { "id": 42 },
"include": ["member_count", "connection_count"]
}'member_count solo funciona en canales de presencia. connection_count requiere conteo de conexiones en la app. Solicitar estos atributos cuenta como un mensaje extra en el consumo.
Límites
| Límite | Valor |
|---|---|
| Canales por publicación | 100 |
| Eventos por lote | 10 |
| Payload del evento | 10 KB serializados |
| Nombre de canal | 164 caracteres, letras, dígitos y _ - = @ , . ; |
| Nombre de evento | 200 caracteres |
Superar cualquier límite devuelve un error de validación. El API no trunca la solicitud.
Reintentar de forma segura
Reintenta una publicación con la misma Idempotency-Key para evitar entregas duplicadas. Los SDK de TypeScript y Go generan una clave y la reutilizan en reintentos automáticos. Si tu aplicación reintenta una solicitud, proporciona y reutiliza su propia clave. Consulta Idempotencia.
Próximos pasos
- Autorizar canales es lo que un canal private- o presence- necesita antes de que un cliente pueda suscribirse.
- Descripción general de Realtime explica canales, miembros y conexiones, y dónde aparece el consumo.
- Excluir destinatarios de eventos evita que el cliente que realizó la acción reciba su propio cambio.
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.
Explorar la funcionalidadRealtimeSeguir la ruta de aprendizajeBuild your first integrationGuía de implementaciónSend your first realtime event
Prueba el ejercicio y obtén un resumen de implementación