Diffusions
`broadcasts.preview`, `send`, `list`, `list_all`, `iterate`, `get`, `list_recipients`, `list_all_recipients`, `iterate_recipients`, `get_recipient`, `stats`, `analytics` et `cancel`.
Toutes les méthodes
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]endUne diffusion envoie un message à tous les membres d'une ou plusieurs audiences, sous forme de copie distincte pour chaque personne. Chaque copie a exactement un destinataire et ni cc ni bcc, si bien que personne ne voit à qui d'autre elle est partie, et chaque copie est un e-mail ordinaire avec son propre id msg_, ses événements, son suivi et ses webhooks. list_recipients les liste avec ce qui est arrivé à chacune. Les copies ne sont pas classées dans le dossier Envoyés, car c'est la diffusion qui sert de trace.
send retourne immédiatement avec la diffusion en queued, ou en scheduled quand vous passez scheduledAt:, et l'envoi s'exécute en arrière-plan. send exige emails:send et audiences:read, et preview exige audiences:read. list, list_all, iterate, get, list_recipients, list_all_recipients, iterate_recipients, get_recipient, stats et analytics exigent emails:read, et cancel exige emails:send.
Chaque send porte un Idempotency-Key, le vôtre via idempotency_key: ou un que génère la gem : un réessai après un échec réseau répond donc avec la diffusion créée par la première tentative, avec replayed à true, au lieu d'envoyer deux fois. preview, get, cancel et toutes les lectures peuvent être répétés sans risque et sont réessayés.
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]Les champs d'une diffusion sont des arguments nommés ou un seul Hash, et gardent les noms en camelCase de l'API (audienceIds:, scheduledAt:). idempotency_key: et api_key: sont des options de l'appel et ne sont jamais envoyés comme champs. Des mots-clés passés à côté d'un Hash y sont fusionnés : send(draft, scheduledAt: "P1D") envoie donc le même brouillon un jour plus tard. scheduledAt: prend un Time, un DateTime, une chaîne ISO 8601 ou une durée comme PT2H, et un Time part comme un instant UTC. preview n'envoie que audienceIds de ce que vous lui donnez : il prend donc le même Hash que send. Une réponse est un Hash à clés Symbol : broadcast[:status] lit donc le statut.
Champs de fusion
subject, html et text sont remplis pour chaque personne à partir de son contact. {{firstName}} est le premier mot du nom du contact, {{lastName}} le reste, {{name}} le nom complet, {{email}} l'adresse à laquelle part la copie et {{unsubscribeUrl}} le lien qui la désabonne.
Chaque champ accepte une valeur de repli après une barre, utilisée quand le contact n'a pas de valeur pour lui : {{firstName|there}} devient donc "there" pour un contact enregistré sans nom. Les valeurs sont échappées dans html, et tout autre {{…}} est laissé exactement tel qu'il est écrit.
Passez template: au lieu de html: et text: pour envoyer un modèle stocké, sous forme de Hash avec id et optionnellement version, props et slots. Les cinq mêmes valeurs lui parviennent comme props, mais seulement les props que le modèle déclare : un modèle qui déclare firstName le reçoit, et un modèle qui ne le déclare pas n'est jamais refusé pour autant. Tout ce qui se trouve dans ses props va à chaque copie à l'identique.
Désabonnement
Chaque copie porte les en-têtes de désabonnement en un clic qui permettent à un client de messagerie d'afficher son propre bouton de désabonnement, ce que les grands fournisseurs de boîtes exigent du courrier en masse. Un corps html ou text qui ne place pas {{unsubscribeUrl}} lui-même reçoit un pied de page d'une ligne avec le lien. Un modèle est envoyé exactement tel quel : mettez donc {{unsubscribeUrl}} dans le modèle.
Le désabonnement marque la personne comme désabonnée dans chaque audience à laquelle cette diffusion a été envoyée, et audiences.list_contacts l'indique dans le unsubscribedAt de sa ligne, comme le décrit la page Audiences. Elle reste dans l'audience et dans le carnet d'adresses, ses autres audiences ne sont pas touchées, et le courrier qui lui est envoyé un message à la fois part toujours. La retirer de l'audience puis l'y rajouter la réabonne.
Qui est ignoré
Une diffusion atteint chaque contact d'au moins une des audienceIds, une fois quel que soit le nombre d'audiences qui le contiennent. Elle ignore le contact qui s'est désabonné de chacune de ces audiences dont il fait partie, et l'adresse figurant sur la liste de suppression après un rebond ou une plainte, ou parce que quelqu'un l'y a ajoutée. Un contact ajouté à l'une des audiences après send, mais avant que l'envoi ne l'atteigne, est inclus.
preview renvoie les mêmes chiffres sans envoyer : recipients, unsubscribed et suppressed. Un send qui n'atteindrait personne lève un 422 no_recipients sous forme d'OpenEmail::ValidationError.
L'envoi entier est confronté aux envois mensuels du forfait avant que quoi que ce soit ne soit écrit : une diffusion que le quota ne peut pas couvrir lève donc un 429 send_quota_exceeded sous forme d'OpenEmail::RateLimitError et ne laisse rien derrière elle. Chaque copie compte comme un envoi.
Statut et avancement
get lit counts en direct à partir des copies : interrogez-le donc régulièrement pendant l'envoi d'une diffusion, avec sleep entre les appels comme le fait l'exemple ci-dessus. status passe de scheduled ou queued à sending et s'arrête sur sent une fois que chaque copie transmise est partie ou a échoué. Il reste à sending tant que des copies attendent encore, même après que completedAt indique que la dernière personne a été atteinte. failed signifie que toute la diffusion s'est arrêtée, et lastError dit pourquoi : l'adresse from ne peut plus servir à envoyer, le modèle a cessé de se résoudre, le forfait s'est épuisé en cours de route, l'envoi lui-même a échoué à répétition, ou pas une seule copie n'a pu être écrite.
cancel arrête une diffusion qui est scheduled, queued ou sending. Plus personne n'est ajouté et chaque copie encore en attente est annulée, tandis que les copies parties ne peuvent pas être rappelées. Une fois toutes les copies parties, cancel lève un 409 broadcast_not_cancellable sous forme d'OpenEmail::ConflictError, et annuler une diffusion déjà annulée la renvoie telle quelle.
Qui elle a atteint
list_recipients renvoie une OpenEmail::Page des personnes auxquelles une diffusion a été envoyée, une ligne par copie, triées par adresse, avec items, has_more? et next_cursor. list_all_recipients parcourt toutes les pages dans un seul Array, et iterate_recipients passe les copies une par une à un bloc, en ne récupérant la page suivante que lorsque la boucle la demande. Sans bloc, il renvoie un Enumerator. limit: va de 1 à 200, 50 par défaut, et un cursor: se renvoie avec les mêmes filter: et q:.
| `filter:` | Garde |
|---|---|
| pending | Copies encore en file d'attente, programmées ou en cours d'envoi. |
| sent | Copies parties. |
| delivered | Copies acceptées par le serveur destinataire. |
| opened | Copies ouvertes au moins une fois. |
| not_opened | Copies envoyées et jamais ouvertes. |
| clicked | Copies avec au moins un clic suivi. |
| bounced | Copies qui ont rebondi. |
| complained | Copies que la personne a signalées comme spam. |
| failed | Copies échouées ou annulées. |
| unsubscribed | Personnes qui se sont désabonnées après le départ de la diffusion. |
OpenEmail::BROADCAST_RECIPIENT_FILTERS nomme chaque filtre, et q: cherche dans l'adresse et le nom, sans tenir compte de la casse. Les ouvertures et les clics excluent les proxys d'images et les scanners de liens, et restent à 0 quand la diffusion est partie avec le suivi désactivé.
get_recipient(id, email_id) renvoie une copie : la même ligne, plus subject, html et text exactement tels que cette personne les a reçus, avec les champs de fusion remplis et son propre lien de désabonnement. Passez l'emailId d'une ligne comme email_id. Le HTML est celui d'avant l'ajout du suivi des ouvertures et des clics. Un email_id qui n'est pas une copie de cette diffusion lève un 404 recipient_not_found, et une diffusion inconnue lève un 404 broadcast_not_found, tous deux sous forme d'OpenEmail::NotFoundError.
stats renvoie les totaux et une série. totals compte les copies sent, delivered, bounced, complained et failed, avec pending pour celles qui attendent encore, et les personnes qui ont opened, clicked et unsubscribed, avec opens et clicks comme nombres d'événements. series est clairsemée et commence par la plus ancienne, un intervalle par grain: (minute, hour ou day, hour par défaut) dans lequel il s'est passé quelque chose, découpé dans le fuseau situé offset_minutes: à l'est d'UTC. Passez Time.now.utc_offset / 60 pour le fuseau local. Elle compte chaque personne une fois, la première fois où l'événement lui est arrivé : elle s'additionne donc pour donner les totaux.
Passez days: ou minutes: à stats pour lire aussi ce qui s'est passé récemment. window compte alors ce qui a été livré, a rebondi, a été signalé comme spam, ouvert, cliqué et désabonné dans cette fenêtre, et series ne garde que ses intervalles, tandis que totals couvre toujours toute la diffusion. Sans l'un ni l'autre, window vaut nil.
Une clé limitée à certaines adresses ou certains domaines n'atteint que les diffusions envoyées depuis une adresse ou un domaine qu'elle détient. list, list_all et iterate omettent les autres, et get, les méthodes de destinataires, stats et cancel lèvent pour elles un 404 broadcast_not_found.
Réponse : une diffusion
send, get et cancel en renvoient chacun une, sous forme de Hash à clés Symbol, et send ajoute replayed. list en renvoie une OpenEmail::Page, de la plus récente à la plus ancienne, et list_all et iterate parcourent toutes les pages. preview renvoie un Hash avec audienceIds, recipients, unsubscribed et suppressed. list_recipients renvoie une OpenEmail::Page de lignes de destinataires, get_recipient une ligne avec son contenu, et stats un Hash avec broadcastId, grain, totals, window et series. analytics renvoie un Hash avec totals, series et une ligne par diffusion dans broadcasts. Les dates sont des chaînes ISO 8601, que Time.iso8601 analyse.
idString- L'identifiant durable, `brd_` suivi de 24 caractères hexadécimaux.
statusString- `scheduled`, `queued`, `sending`, `sent`, `cancelled` ou `failed`. `OpenEmail::BROADCAST_STATUSES` nomme chacun d'eux.
modeString- `live` ou `test`, selon la clé qui l'a créée. Les copies d'une diffusion de test sont marquées envoyées et ne sont remises à personne.
sourceString- D'où elle a été lancée : `api` pour une clé, `oauth` pour une application connectée, `composer` pour l'application, `mcp` pour un assistant.
audienceIdsArray<String>- Les audiences auxquelles elle est partie, chacune une fois.
fromString- L'adresse depuis laquelle chaque copie est envoyée.
subjectString- L'objet tel qu'écrit, champs de fusion compris. Vide quand un modèle fournit l'objet.
countsHash- `recipients` est l'estimation prise au `send`. `created` compte les copies écrites, `skipped` les personnes laissées de côté parce que leur adresse était supprimée à ce moment-là, et `failedToQueue` les personnes dont la copie n'a pas pu être écrite. `queued`, `sending`, `sent`, `failed` et `cancelled` comptent les copies selon l'état où chacune se trouve maintenant.
lastErrorString or nil- Pourquoi la diffusion a échoué, ou la copie la plus récente qui n'a pas pu être écrite et pourquoi. nil tant que rien ne s'est mal passé.
scheduledAtString or nil- ISO-8601 UTC, quand l'envoi doit commencer. nil pour une diffusion envoyée immédiatement.
startedAtString or nil- ISO-8601 UTC, quand l'envoi a atteint les premières personnes.
completedAtString or nil- ISO-8601 UTC, quand la dernière personne a été atteinte. Des copies peuvent encore attendre de partir après.
cancelledAtString or nil- ISO-8601 UTC, quand `cancel` l'a arrêtée.
createdAtString- ISO-8601 UTC, quand `send` a été appelé. Fixe l'ordre de la liste.
updatedAtString- ISO-8601 UTC, mis à jour à mesure que l'envoi avance.
Réponse : une ligne de destinataire
Chaque ligne de list_recipients, list_all_recipients et iterate_recipients, sous forme de Hash à clés Symbol. Le Hash que renvoie get_recipient ajoute subject, html et text.
emailIdString- L'id `msg_` de la copie de cette personne. `get_recipient` la lit avec son contenu, et `emails.get` la lit comme un e-mail envoyé, comme le décrit la page Lister et récupérer.
contactIdString or nil- Le contact auquel elle est allée, ou nil quand le contact a été supprimé depuis.
emailString- L'adresse à laquelle la copie est partie.
nameString or nil- Le nom du contact.
statusString- L'état de la copie : `queued`, `scheduled`, `sending`, `sent`, `failed` ou `cancelled`.
sentAtString or nil- ISO-8601 UTC, moment où la copie est partie.
deliveredAtString or nil- ISO-8601 UTC, moment où le serveur destinataire l'a acceptée, le premier `email.delivered`.
bouncedAtString or nil- ISO-8601 UTC, moment où elle a rebondi, le premier `email.bounced`.
complainedAtString or nil- ISO-8601 UTC, moment où la personne l'a signalée comme spam, le premier `email.complained`.
failureString or nil- Pourquoi la copie a échoué, le cas échéant.
opensInteger- Ouvertures enregistrées, sans celles des proxys d'images et des scanners. 0 quand le suivi était désactivé.
firstOpenAtString or nil- ISO-8601 UTC, la première ouverture.
clicksInteger- Clics enregistrés sur les liens suivis, sans les scanners.
firstClickAtString or nil- ISO-8601 UTC, le premier clic.
unsubscribedAtString or nil- ISO-8601 UTC, quand cette personne s'est désabonnée de l'une des audiences de la diffusion après son départ, via son lien ou autrement.