Saltar para a documentação
Ruby

Difusões

`broadcasts.preview`, `send`, `list`, `list_all`, `iterate`, `get`, `list_recipients`, `list_all_recipients`, `iterate_recipients`, `get_recipient`, `stats`, `analytics` e `cancel`.

Todos os métodos

broadcasts.rb
draft = {  audienceIds: ["aud_4c1b8e2a7d9f05c36b4e8a71"],  from: "Acme <[email protected]>",  subject: "{{firstName|Hello}}, the September release is out",  html: "<p>Hi {{firstName|there}},</p><p>Here is what changed this month.</p>",  text: "Hi {{firstName|there}}, here is what changed this month. Unsubscribe: {{unsubscribeUrl}}",  tags: {campaign: "release-2026-09"}} reach = client.broadcasts.preview(draft)puts reach[:recipients], reach[:unsubscribed], reach[:suppressed] broadcast = client.broadcasts.send(draft) latest = client.broadcasts.get(broadcast[:id])while %w[scheduled queued sending].include?(latest[:status])  sleep 5  latest = client.broadcasts.get(broadcast[:id])end client.broadcasts.iterate_recipients(broadcast[:id]) do |copy|  puts copy[:email], copy[:status], copy[:opens], copy[:clicks]end bounced = client.broadcasts.list_recipients(broadcast[:id], filter: "bounced")bounced.items.each { |row| puts "#{row[:emailId]} #{row[:email]}" } copy = client.broadcasts.get_recipient(broadcast[:id], "msg_01dad25067bc4dac966d515d")puts copy[:subject], copy[:bouncedAt] stats = client.broadcasts.stats(broadcast[:id], grain: "day")puts stats.dig(:totals, :opened), stats.dig(:totals, :clicked), stats.dig(:totals, :unsubscribed) lately = client.broadcasts.stats(broadcast[:id], days: 1)puts lately.dig(:window, :opened) later = client.broadcasts.send(draft, scheduledAt: "P1D")client.broadcasts.cancel(later[:id]) history = client.broadcasts.list(audience_id: draft[:audienceIds].first)puts latest[:status], latest.dig(:counts, :sent), history.items.size month = client.broadcasts.analytics(days: 30)month[:broadcasts].each do |row|  puts row[:subject], row[:sent], row[:opened]end

Uma difusão envia uma mensagem para todos em uma ou mais audiências, como cópia separada para cada pessoa. Cada cópia tem exatamente um destinatário e nem cc nem bcc, por isso ninguém vê para quem mais foi, e cada cópia é um email normal com o seu próprio id msg_, eventos, rastreio e webhooks. list_recipients lista-as com o que aconteceu a cada uma. As cópias não são arquivadas na pasta Enviados, porque a difusão é o registo.

send devolve de imediato a difusão em queued, ou em scheduled quando passa scheduledAt:, e o envio continua em segundo plano. send precisa de emails:send e audiences:read, e preview precisa de audiences:read. list, list_all, iterate, get, list_recipients, list_all_recipients, iterate_recipients, get_recipient, stats e analytics precisam de emails:read, e cancel precisa de emails:send.

Cada send leva uma Idempotency-Key, a sua através de idempotency_key: ou uma que a gem cria, por isso uma repetição após uma falha de rede responde com a difusão que a primeira tentativa criou, com replayed a true, em vez de enviar duas vezes. preview, get, cancel e todas as leituras podem ser repetidos com segurança e são repetidos.

schedule_broadcast.rb
broadcast = client.broadcasts.send(  audienceIds: ["aud_4c1b8e2a7d9f05c36b4e8a71"],  from: "Acme <[email protected]>",  subject: "Doors open on Friday",  text: "Hi {{firstName|there}}, doors open at nine. Unsubscribe: {{unsubscribeUrl}}",  scheduledAt: Time.now + 3600,  idempotency_key: "doors-open-2026-10") puts broadcast[:id], broadcast[:status], broadcast[:replayed]

Os campos de uma difusão são argumentos nomeados ou um único Hash, e mantêm os nomes em camelCase da API (audienceIds:, scheduledAt:). idempotency_key: e api_key: são opções da chamada e nunca são enviados como campos. Os argumentos nomeados passados ao lado de um Hash fundem-se com ele, por isso send(draft, scheduledAt: "P1D") envia o mesmo rascunho um dia mais tarde. scheduledAt: aceita um Time, um DateTime, uma string ISO 8601 ou uma duração como PT2H, e um Time sai como instante UTC. preview só envia audienceIds do que lhe der, por isso aceita o mesmo Hash que send. Uma resposta é um Hash com chaves Symbol, por isso broadcast[:status] lê o estado.

Campos de fusão

subject, html e text são preenchidos para cada pessoa a partir do seu contacto. {{firstName}} é a primeira palavra do nome do contacto, {{lastName}} o resto, {{name}} o nome completo, {{email}} o endereço para onde vai a cópia e {{unsubscribeUrl}} a ligação que lhe cancela a subscrição.

Cada campo aceita um valor alternativo depois de uma barra, usado quando o contacto não tem valor para ele, por isso {{firstName|there}} passa a "there" para um contacto guardado sem nome. Os valores são escapados em html, e qualquer outro {{…}} fica exatamente como foi escrito.

Passe template: em vez de html: e text: para enviar um modelo guardado, como um Hash com id e, opcionalmente, version, props e slots. Os mesmos cinco valores chegam-lhe como props, mas só as props que o modelo declara, por isso um modelo que declara firstName recebe-o e um que não o declara nunca é recusado por isso. Tudo o que está nas suas props vai igual para todas as cópias.

Cancelar subscrição

Cada cópia leva os cabeçalhos para cancelar a subscrição com um clique, que permitem a um cliente de correio mostrar o seu próprio botão, algo que os grandes fornecedores de caixas de correio exigem ao correio em massa. Um corpo html ou text que não coloque {{unsubscribeUrl}} por si recebe um rodapé de uma linha com a ligação. Um modelo é enviado exatamente como está, por isso ponha {{unsubscribeUrl}} no modelo.

Cancelar a subscrição marca a pessoa sem subscrição em todas as audiências para onde essa difusão foi, e audiences.list_contacts mostra-o no unsubscribedAt da sua linha, como descreve a página Audiências. Continua na audiência e no livro de endereços, as outras audiências não são tocadas, e o correio que lhe é enviado uma mensagem de cada vez continua a sair. Retirá-la da audiência e voltar a adicioná-la dá-lhe subscrição de novo.

Quem é ignorado

Uma difusão alcança todos os contactos de pelo menos uma das audienceIds, uma vez por mais audiências que os contenham. Ignora o contacto que cancelou a subscrição de todas essas audiências em que está, e o endereço na lista de supressão após uma devolução ou uma queixa, ou porque alguém o adicionou. Um contacto adicionado a uma das audiências depois de send, mas antes de o envio lá chegar, é incluído.

preview devolve os mesmos números sem enviar: recipients, unsubscribed e suppressed. Um send que não alcançaria ninguém lança 422 no_recipients como OpenEmail::ValidationError.

O envio inteiro é comparado com os envios mensais do plano antes de se escrever qualquer coisa, por isso uma difusão que a quota não consegue cobrir lança 429 send_quota_exceeded como OpenEmail::RateLimitError e não deixa nada para trás. Cada cópia conta como um envio.

Estado e progresso

get lê counts ao vivo a partir das cópias, por isso consulte-o enquanto uma difusão envia, com sleep entre chamadas como faz o exemplo acima. status passa de scheduled ou queued para sending e fixa-se em sent quando cada cópia entregue saiu ou falhou. Continua sending enquanto ainda há cópias à espera, mesmo depois de completedAt dizer que a última pessoa foi alcançada. failed significa que a difusão inteira parou, e lastError diz porquê: o endereço from já não pode enviar, o modelo deixou de se resolver, o plano esgotou-se a meio, o próprio envio falhou repetidamente, ou nem uma cópia pôde ser escrita.

cancel para uma difusão que está scheduled, queued ou sending. Ninguém mais é adicionado e cada cópia ainda à espera é cancelada, enquanto as cópias que saíram não podem ser recuperadas. Quando todas as cópias saíram, cancel lança 409 broadcast_not_cancellable como OpenEmail::ConflictError, e cancelar uma difusão já cancelada devolve-a tal como está.

A quem chegou

list_recipients devolve uma OpenEmail::Page das pessoas para quem uma difusão foi, uma linha por cópia, ordenadas por endereço, com items, has_more? e next_cursor. list_all_recipients percorre todas as páginas para um único Array, e iterate_recipients passa uma cópia de cada vez a um bloco, indo buscar a página seguinte só quando o ciclo a pede. Sem bloco, devolve um Enumerator. limit: vai de 1 a 200 e é 50 por omissão, e um cursor: é reenviado com os mesmos filter: e q:.

`filter:`Mantém
pendingCópias ainda em fila, agendadas ou a enviar.
sentCópias que saíram.
deliveredCópias que o servidor de destino aceitou.
openedCópias abertas pelo menos uma vez.
not_openedCópias enviadas e nunca abertas.
clickedCópias com pelo menos um clique com seguimento.
bouncedCópias que foram devolvidas.
complainedCópias que a pessoa denunciou como spam.
failedCópias que falharam ou foram canceladas.
unsubscribedPessoas que cancelaram a subscrição depois do envio da difusão.

OpenEmail::BROADCAST_RECIPIENT_FILTERS nomeia cada filtro, e q: pesquisa o endereço e o nome, sem distinguir maiúsculas de minúsculas. As aberturas e os cliques excluem proxies de imagens e verificadores de ligações, e ficam em 0 quando a difusão saiu com o rastreio desligado.

get_recipient(id, email_id) devolve uma cópia: a mesma linha, mais subject, html e text exatamente como essa pessoa os recebeu, com os campos de fusão preenchidos e a sua própria ligação para cancelar a subscrição. Passe o emailId de uma linha como email_id. O HTML é de antes de ser acrescentado o rastreio de aberturas e cliques. Um email_id que não é uma cópia desta difusão lança 404 recipient_not_found, e uma difusão desconhecida lança 404 broadcast_not_found, ambos lançados como OpenEmail::NotFoundError.

stats devolve os totais e uma série. totals conta as cópias sent, delivered, bounced, complained e failed, com pending para as que ainda esperam, e as pessoas que opened, clicked e unsubscribed, com opens e clicks como contagens de eventos. series é esparsa e começa pelas mais antigas, com um intervalo por grain: (minute, hour ou day, por omissão hour) em que algo aconteceu, cortado no fuso que fica offset_minutes: minutos a leste de UTC. Passe Time.now.utc_offset / 60 para o fuso local. Conta cada pessoa uma vez, na primeira vez que lhe aconteceu, por isso a soma bate certo com os totais.

Passe days: ou minutes: a stats para ler também o que aconteceu recentemente. window conta então o que foi entregue, devolvido, denunciado como spam, aberto, clicado e com subscrição cancelada dentro desse período, e series mantém apenas os intervalos desse período, enquanto totals continua a abranger toda a difusão. Sem nenhum dos dois, window é nil.

Uma chave limitada a determinados endereços ou domínios só alcança as difusões enviadas de um endereço ou domínio que tem. list, list_all e iterate deixam as outras de fora, e get, os métodos de destinatários, stats e cancel lançam 404 broadcast_not_found para elas.

Resposta: uma difusão

send, get e cancel devolvem cada um uma destas, um Hash com chaves Symbol, e send acrescenta replayed. list devolve uma OpenEmail::Page delas, das mais recentes para as mais antigas, e list_all e iterate percorrem todas as páginas. preview devolve um Hash com audienceIds, recipients, unsubscribed e suppressed. list_recipients devolve uma OpenEmail::Page de linhas de destinatários, get_recipient devolve uma linha com o seu conteúdo, e stats devolve um Hash com broadcastId, grain, totals, window e series. analytics devolve um Hash com totals, series e uma linha por difusão em broadcasts. As horas são strings ISO 8601, que Time.iso8601 analisa.

idString
O identificador duradouro, `brd_` seguido de 24 caracteres hexadecimais.
statusString
`scheduled`, `queued`, `sending`, `sent`, `cancelled` ou `failed`. `OpenEmail::BROADCAST_STATUSES` nomeia cada um.
modeString
`live` ou `test`, conforme a chave que a criou. As cópias de uma difusão de teste são marcadas como enviadas e não são entregues a ninguém.
sourceString
Onde foi iniciada: `api` para uma chave, `oauth` para uma aplicação ligada, `composer` para a aplicação, `mcp` para um assistente.
audienceIdsArray<String>
As audiências para onde foi enviada, cada uma uma vez.
fromString
O endereço de onde cada cópia é enviada.
subjectString
O assunto tal como foi escrito, com os campos de fusão. Vazio quando um modelo fornece o assunto.
countsHash
`recipients` é a estimativa tirada no `send`. `created` conta as cópias escritas, `skipped` as pessoas passadas à frente porque o endereço estava suprimido nessa altura, e `failedToQueue` as pessoas cuja cópia não pôde ser escrita. `queued`, `sending`, `sent`, `failed` e `cancelled` contam as cópias pelo estado em que cada uma está agora.
lastErrorString or nil
Porque falhou a difusão, ou a cópia mais recente que não pôde ser escrita e porquê. É nil enquanto nada tiver corrido mal.
scheduledAtString or nil
ISO-8601 UTC, quando o envio deve começar. É nil para uma difusão enviada de imediato.
startedAtString or nil
ISO-8601 UTC, quando o envio alcançou as primeiras pessoas.
completedAtString or nil
ISO-8601 UTC, quando a última pessoa foi alcançada. Depois disso ainda pode haver cópias à espera de sair.
cancelledAtString or nil
ISO-8601 UTC, quando `cancel` a parou.
createdAtString
ISO-8601 UTC, quando `send` foi chamado. Fixa a ordem da lista.
updatedAtString
ISO-8601 UTC, atualizado à medida que o envio avança.

Resposta: uma linha de destinatário

Cada linha de list_recipients, list_all_recipients e iterate_recipients, como um Hash com chaves Symbol. O Hash que get_recipient devolve acrescenta subject, html e text.

emailIdString
O id `msg_` da cópia desta pessoa. `get_recipient` lê-a com o seu conteúdo, e `emails.get` lê-a como um email enviado, como descreve a página Listar e obter.
contactIdString or nil
O contacto para quem foi, ou nil quando o contacto foi eliminado entretanto.
emailString
O endereço para onde a cópia foi.
nameString or nil
O nome no contacto.
statusString
O estado da cópia: `queued`, `scheduled`, `sending`, `sent`, `failed` ou `cancelled`.
sentAtString or nil
ISO-8601 UTC, quando a cópia saiu.
deliveredAtString or nil
ISO-8601 UTC, quando o servidor de destino a aceitou, o primeiro `email.delivered`.
bouncedAtString or nil
ISO-8601 UTC, quando foi devolvida, o primeiro `email.bounced`.
complainedAtString or nil
ISO-8601 UTC, quando a pessoa a denunciou como spam, o primeiro `email.complained`.
failureString or nil
Porque é que a cópia falhou, se falhou.
opensInteger
Aberturas registadas, sem as que os proxies de imagens e os verificadores geram. 0 quando o seguimento estava desligado.
firstOpenAtString or nil
ISO-8601 UTC, a primeira abertura.
clicksInteger
Cliques registados em ligações com seguimento, sem verificadores.
firstClickAtString or nil
ISO-8601 UTC, o primeiro clique.
unsubscribedAtString or nil
ISO-8601 UTC, quando esta pessoa cancelou a subscrição de uma das audiências da difusão depois do envio, pela ligação da difusão ou de outra forma.