Salta ai contenuti

Campagne

Una campagna invia un messaggio a ogni contatto iscritto di un pubblico. SpacePost lo distribuisce in una email personalizzata per ogni contatto, aggiunge i link di annullamento dell’iscrizione e gli header List-Unsubscribe, salta gli indirizzi soppressi e traccia tutto come qualsiasi altra email.

Stato Significato
draft Creata, modificabile, non inviata.
queued È stato chiamato send; in attesa dell’orario di avvio (subito, oppure scheduled_at).
sending In corso di distribuzione ai contatti.
sent Ogni email è stata accettata per la consegna. sent_at è impostato.
failed La distribuzione si è fermata, ad esempio perché è stata raggiunta una quota o il team è stato messo in pausa.
canceled Annullata prima dell’invio.
broadcast.ts
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);
const audienceId = "0192e1c4-0000-7000-8000-0000000000a1";
// 1. Create a draft
const { data: draft, error } = await spacepost.broadcasts.create({
audienceId,
name: "October newsletter",
from: "Acme <news@acme.com>",
replyTo: "support@acme.com",
subject: "What's new at Acme, {{{FIRST_NAME|friend}}}",
previewText: "Three things we shipped this month",
html: `
<h1>Hi {{{FIRST_NAME|there}}},</h1>
<p>Here is what is new.</p>
<p><a href="{{{SPACEPOST_UNSUBSCRIBE_URL}}}">Unsubscribe</a></p>
`,
});
if (error) throw new Error(error.message);
// 2. Send it now, or schedule it
const { error: sendError } = await spacepost.broadcasts.send(draft.id, { scheduledAt: "in 1 hour" });
if (sendError) throw new Error(sendError.message);
// 3. Check progress
const { data: broadcast } = await spacepost.broadcasts.get(draft.id);
console.log(broadcast?.status); // "queued" | "sending" | "sent" | "failed"

POST /broadcasts crea una bozza e restituisce { "id": "..." }.

audience_idstring (uuid)obbligatorio

Il pubblico a cui inviare.

fromstringobbligatorio

Mittente su un dominio verificato.

subjectstringobbligatorio

Da 1 a 998 caratteri. I segnaposto sono supportati.

htmlstringopzionale

Corpo HTML. Fornisci html, text o entrambi prima dell'invio.

textstringopzionale

Corpo in solo testo.

reply_tostring | string[]opzionale

Fino a 50 indirizzi.

preview_textstringopzionale

Fino a 200 caratteri. Mostrato dopo l'oggetto nelle caselle di posta; inserito come preheader nascosto.

namestringopzionale

Fino a 100 caratteri. Un'etichetta interna.

PATCH /broadcasts/{id} accetta gli stessi campi (tutti facoltativi) e funziona solo sulle bozze. DELETE /broadcasts/{id} funziona sulle bozze e sulle campagne pianificate nel futuro.

Finestra del terminale
# now
curl -X POST https://api.spacepost.dev/broadcasts/$ID/send -H "Authorization: Bearer $SPACEPOST_API_KEY"
# scheduled (ISO or natural language, up to 30 days ahead)
curl -X POST https://api.spacepost.dev/broadcasts/$ID/send \
-H "Authorization: Bearer $SPACEPOST_API_KEY" -H "Content-Type: application/json" \
-d '{ "scheduled_at": "2026-11-01T09:00:00Z" }'

Possono essere inviate solo le bozze con un corpo html o text, da un dominio verificato. La risposta è { "id": "..." }.

Prima di inviare, GET /broadcasts/{id}/readiness restituisce una checklist di recapito (la dashboard mostra lo stesso elenco nell’editor). È un’estensione di SpacePost e non fa parte dell’API di Resend.

{ "ready": true, "checks": [{ "id": "html_size", "level": "warn", "title": "Gmail will clip this message", "detail": "..." }] }
Controllo Livello Quando
sender_domain error Il dominio di from manca o non è verificato.
dmarc warn Nessun record v=DMARC1 in _dmarc.<domain>, oppure la ricerca è fallita. p=none è accettato.
subject error / warn Error se è vuoto. Warning per TUTTO MAIUSCOLO, !!! o $$$, oppure per più di 90 caratteri.
html_size warn HTML oltre i 102 KB, che Gmail tronca.
images warn Solo immagini, oppure quattro o più immagini con poco testo.
shorteners warn Link tramite bit.ly, tinyurl.com, t.co e simili.
spam_phrases warn Formulazioni tipiche dello spam nell’oggetto o nel corpo.
unsubscribe ok Un piè di pagina di annullamento dell’iscrizione viene aggiunto automaticamente quando il tuo corpo non ha un segnaposto, quindi non blocca mai.
audience error Nessun contatto iscritto.
role_addresses warn Più del 20% dei contatti sono indirizzi come info@ o admin@.

ready è false quando un qualsiasi controllo ha livello error. L’invio fallisce quindi con un validation_error (422) che elenca che cosa correggere. I warning non bloccano mai un invio.

Le email delle campagne includono anche gli header List-Id e Feedback-ID (<broadcast id>:<team id>:broadcast:spacepost) in modo che Gmail Postmaster Tools possa attribuire i reclami a una campagna. Le email transazionali no.

  • La personalizzazione viene applicata a subject, html e text (Personalizzazione).
  • Annullamento dell’iscrizione: se il tuo corpo non ha il segnaposto {{{SPACEPOST_UNSUBSCRIBE_URL}}} / {{{RESEND_UNSUBSCRIBE_URL}}}, viene aggiunto automaticamente un piè di pagina di annullamento dell’iscrizione. Gli header List-Unsubscribe e List-Unsubscribe-Post: List-Unsubscribe=One-Click vengono sempre aggiunti.
  • Il Testo di anteprima diventa un preheader nascosto in cima all’HTML.
  • I contatti che hanno annullato l’iscrizione e gli indirizzi nella tua lista di soppressione vengono saltati.

Ogni destinatario conta come una email sulla quota del tuo piano, e per i nuovi account vale la sandbox da 100 email al giorno. Se la quota si esaurisce a metà invio, la campagna termina come failed; le email già create vengono comunque consegnate. La distribuzione è riprendibile se un worker si riavvia.

Ogni email di una campagna è una normale email: compare in GET /emails, include broadcast_id nei payload dei webhook e può rimbalzare o essere aperta.