Publicando eventos
Publique a partir do seu servidor usando sua chave Bird API e a chave e o segredo do app Realtime. Nunca inclua o segredo do app em código do lado do cliente. Para permitir que clientes inscritos troquem sinais de curta duração, use eventos de cliente em canais privados ou de presença.
Uma publicação mínima
Um evento requer um nome e pelo menos um canal. Seu payload opcional pode conter qualquer objeto, array ou 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" }
}'Clientes vinculados a order-updated em orders recebem o evento. O API rejeita nomes publicados pelo servidor que comecem com os prefixos de protocolo bird: ou bird_internal:. Nomes de eventos originados pelo cliente devem começar com client-.
A solicitação e a resposta completas, incluindo todos os campos, estão na referência publicar um evento.
O que um 200 significa
A publicação é concluída depois que a borda Realtime aceita o evento. A entrega é assíncrona e não tem confirmação por cliente. Um cliente que se desconectar durante a entrega pode perder o evento, e o Realtime não o reenvia após a reconexão.
Armazene estado durável no seu banco de dados. Use eventos para anunciar mudanças e faça os clientes recarregarem o estado atual após a reconexão.
Transmitindo para vários canais
Uma chamada pode enviar o mesmo evento para até 100 canais. Um canal private-encrypted- deve ser o único canal na publicação, porque cada canal criptografado usa uma chave diferente. O API rejeita um fan-out criptografado com E23000. Veja Canais criptografados.
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 conta como uma mensagem separada para uso. Este exemplo conta como três mensagens. Uma publicação para 10.000 canais por usuário conta, portanto, como 10.000 mensagens.
Agrupando eventos não relacionados em lote
Um broadcast envia um evento para vários canais. Um lote envia até 10 eventos diferentes, cada um para um canal, em uma única solicitação.
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 } }
]
}'Use um lote para combinar atualizações não relacionadas em uma solicitação. Cada evento ainda conta separadamente para uso, e um lote aceita no máximo 10 eventos. Veja Publicar um lote.
Excluindo o cliente que executou a ação
Se um cliente já aplicou sua ação localmente, passe o ID de conexão dele para evitar que a publicação resultante aplique a mesma mudança novamente. A borda ignora apenas essa conexão.
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"
}'Leia o ID da conexão atual do cliente e inclua-o na solicitação que dispara a mudança. Outras abas usam conexões separadas e ainda recebem o evento.
Lendo o estado do canal ao publicar
Use include para retornar o estado de cada canal de destino no momento da publicação e evitar uma solicitação separada de estado do canal:
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 funciona apenas em canais de presença. connection_count requer contagem de conexões no app. Solicitar esses atributos conta como uma mensagem extra para uso.
Limites
| Limite | Valor |
|---|---|
| Canais por publicação | 100 |
| Eventos por lote | 10 |
| Payload do evento | 10 KB serializado |
| Nome do canal | 164 caracteres, letras, dígitos e _ - = @ , . ; |
| Nome do evento | 200 caracteres |
Exceder qualquer limite retorna um erro de validação. O API não trunca a solicitação.
Tentando novamente com segurança
Tente novamente uma publicação com a mesma Idempotency-Key para evitar entrega duplicada. Os SDKs de TypeScript e Go geram uma chave e a reutilizam para tentativas automáticas. Se sua aplicação tentar novamente uma solicitação, forneça e reutilize sua própria chave. Veja Idempotência.
Próximos passos
- Autorizando canais é o que um canal private- ou presence- precisa antes que um cliente possa se inscrever.
- Visão geral do Realtime explica canais, membros e conexões, e onde o uso aparece.
- Excluindo destinatários de eventos impede que o cliente que executou a ação receba sua própria mudança.
Recursos relacionados
Continue com a documentação, guias e exemplos sobre este tópico. Os recursos estão em inglês.
Explore a funcionalidadeRealtimeSiga o percurso de aprendizagemBuild your first integrationGuia de implementaçãoSend your first realtime event
Experimente na prática e obtenha um resumo de implementação