Sign inGet Started

Wysyłanie e-maili

POST /v1/email/messages wysyła jeden e-mail. Podaj nadawcę, odbiorców i treść w payloadzie JSON. API zwraca 202 Accepted z identyfikatorem wiadomości, a następnie dostarcza e-mail asynchronicznie. Pełne schematy znajdziesz w dokumentacji API.

Minimalne wysłanie

Najmniejszy prawidłowy payload to from, co najmniej jeden odbiorca to, subject i treść (html, text lub oba). Adres from musi znajdować się w domenie zweryfikowanej w tym obszarze roboczym lub w domenie onboardingowej.

const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  subject: "Hello from Bird",
  html: "<p>My first Bird email.</p>",
});
console.log(msg.id, msg.status); // "em_…", "accepted"

Użyj swojego regionalnego hosta (https://us1.platform.bird.com lub https://eu1.platform.bird.com) z pasującym kluczem bk_{region}_....

Przykład wysyłania używa delivered@messagebird.dev, adresu sandboxowego, który zawsze przyjmuje pocztę. API odrzuca domeny zastępcze z błędem 422: example.com, example.net, example.org, example.edu, test.com oraz wszystko w zarezerwowanych TLD .test, .example, .invalid i .localhost. Wysyłka na te domeny może jedynie zostać odrzucona (bounce), co kosztuje Cię reputację nadawcy.

Wysyłanie przed zweryfikowaniem domeny

Podczas onboardingu możesz wysyłać z naszej współdzielonej domeny onboardingowej onboarding@messagebird.dev. Te wysyłki pomijają sprawdzanie domeny, ale docierają tylko do zweryfikowanych członków Twojego obszaru roboczego i adresów sandboxowych, z dziennym limitem odbiorców. Quickstart zawiera dokładne zasady i limity.

Budowanie payloadu

Odbiorcy

to, cc i bcc przyjmują po maksymalnie 50 adresów, a to wymaga co najmniej jednego. Każdy wpis to zwykły ciąg z adresem e-mail, ciąg skrzynki pocztowej RFC 5322 (Jane <jane@acme.com>) lub obiekt z opcjonalną nazwą wyświetlaną.

Odbiorcy znajdujący się na liście suppresji obszaru roboczego nie powodują błędu żądania. Żądanie nadal zwraca 202, a każdy odbiorca objęty suppresją pojawia się w endpointach odczytu jako status: rejected z powodem recipient_suppressed, również wtedy, gdy dotyczy to wszystkich odbiorców wysyłki.

Treść

subject jest wymagany w wysyłkach inline i może mieć do 998 znaków. Podaj html, text lub oba, każdy do 524 288 znaków. Wysyłaj oba, gdy to możliwe: klient, który nie potrafi renderować HTML, wyświetli wtedy część tekstową.

Aby spersonalizować treść inline, umieść tokeny {{ variable }} w temacie lub treści i przekaż ich wartości w parameters, do 16 KB po serializacji. Jeden zestaw wartości obejmuje wszystkich odbiorców wysyłki, a token bez pasującego klucza renderuje się jako pusty. Dla treści wielokrotnego użytku wyślij zamiast tego szablon.

Dodaj parameters, nawet jako pusty obiekt ({}), aby temat i treść zostały przetworzone jako Liquid. Pomiń go, aby wysłać tokeny takie jak {{ animal }} dokładnie w zapisanej postaci. Każda nazwa parametru to pojedyncze słowo, np. first_name; nazwy z kropkami i zarezerwowana nazwa bird są odrzucane. Nieprawidłowa składnia Liquid oraz nieobsługiwane tagi lub filtry zwracają 422.

Wartości wstawiane do HTML są escapowane, aby nie mogły zmienić otaczającego kodu znaczników. Dla pełnego adresu URL linku lub obrazu użyj {{ link }} bez url_encode. Wartość umieszczaną w zapytaniu URL zakoduj jawnie, na przykład https://example.com/search?q={{ query | url_encode }}.

Reply-to i niestandardowe nagłówki

reply_to przyjmuje od 1 do 25 adresów w tych samych formatach co odbiorcy. Każda odpowiedź odbiorcy trafia do wszystkich tych adresów, więc zwykle podaje się jeden lub dwa.

headers to obiekt typu string-to-string na Twoje własne nagłówki, na przykład {"X-Campaign": "spring-2026"}, z limitem 25 nagłówków o wartościach do 998 znaków. Dwa rodzaje nagłówków powodują zwrócenie 422:

  • Nagłówki adresowe i platformowe. Ustaw adresowanie wiadomości przez dedykowane pola (from, to, cc, bcc, reply_to, subject). Tych nazw ani nagłówków, które generujemy za Ciebie (Content-Type, Content-Transfer-Encoding, DKIM-Signature, Received, Return-Path), nie można ustawiać tutaj.
  • Dowolna wartość zawierająca znak powrotu karetki lub nowej linii.

Wysyłki transakcyjne akceptują List-Unsubscribe i List-Unsubscribe-Post. Wysyłki marketingowe domyślnie korzystają z rezygnacji zarządzanej przez Bird.

Śledzenie

track_opens i track_clicks domyślnie mają wartość true. Ustaw dowolne z nich na false, aby pominąć wstrzykiwanie piksela otwarcia lub przepisywanie linków w tej wysyłce. Te flagi nie zmieniają pikseli śledzących ani linków, które już znajdują się w przesłanej treści. Śledzenie i metryki opisuje, co każda z nich zmienia w wiadomości.

Kategoria i pula IP

category klasyfikuje treść i ustawia politykę suppresji: marketing blokuje dostarczanie przy każdym powodzie suppresji i każdej rezygnacji, a transactional dostarcza mimo suppresji ze skargi lub rezygnacji tylko z marketingu (rezygnacja zarejestrowana dla wszystkich wiadomości również blokuje). Domyślnie przyjmuje kategorię szablonu w wysyłce z szablonem, a w pozostałych przypadkach marketing, więc ustaw transactional jawnie dla potwierdzeń, resetów haseł i innej poczty operacyjnej. Kategorie opisują wybór. Poczta przesłana przez SMTP pobiera natomiast kategorię z konfiguracji SMTP klucza.

ip_pool_id wybiera pulę wysyłkową: identyfikator puli (ipp_...) lub ipp_shared, aby jawnie kierować przez pulę współdzieloną. Pomiń go, aby użyć domyślnej puli organizacji. Nieznana pula lub pula bez dostępnych dedykowanych adresów IP jest odrzucana z błędem 422.

Opis pól

PoleTypWymaganeLimity i uwagi
fromaddresstakMusi być w zweryfikowanej domenie lub w domenie onboardingowej
toaddress[]takOd 1 do 50
cc, bccaddress[]nieDo 50 każde
subjectstringwysyłki inlineDo 998 znaków; pomiń w wysyłkach z szablonem
html, textstringco najmniej jednoDo 524 288 znaków każde; pomiń w wysyłkach z szablonem
reply_toaddress[]nieOd 1 do 25; odpowiedzi trafiają do każdego wymienionego adresu
headersobject (string → string)nieDo 25; zarezerwowane nazwy są odrzucane (zobacz niestandardowe nagłówki)
parametersobjectnieWartości dla {{ tokens }} w treści inline; do 16 KB po serializacji; wspólne dla wszystkich odbiorców
tags{name, value}[]nieDo 20; nazwa ≤ 32 znaki, wartość ≤ 64 znaki; tylko [A-Za-z0-9_-]; nazwy unikalne w wysyłce
metadataobjectnieDowolny JSON, do 2 KB po serializacji
referencestringnieOd 1 do 255 znaków; dokładne dopasowanie dla ?reference= na liście wiadomości
track_opensbooleannieDomyślnie true
track_clicksbooleannieDomyślnie true
categorystringniemarketing lub transactional; domyślnie kategoria szablonu w wysyłce z szablonem, w przeciwnym razie marketing
ip_pool_idstringnieipp_... lub ipp_shared; pomiń, aby użyć domyślnej puli organizacji
templateobjectnieWyślij opublikowany szablon po id lub slug, z parameters dla jego zmiennych i opcjonalnym language
attachmentsobject[]nieDo 20; zobacz załączniki
scheduled_atznacznik czasu RFC 3339nieZaplanuj wysyłkę treści inline lub template; zobacz planowanie wysyłki

Wysyłanie z szablonem

Szablony mogą używać wartości bird.contact.* z kontaktu pasującego do każdego adresu To. Odbiorcy Cc i Bcc otrzymują kopię spersonalizowanego e-maila każdego odbiorcy To. Działa to również we wsadowym API i w wysyłkach zaplanowanych; przykład z wieloma odbiorcami znajdziesz w sekcji personalizacja za pomocą zmiennych.

Zamiast treści inline wyślij opublikowany szablon: ustaw template na obiekt wskazujący go po id (emt_...) lub po slug, dokładnie jedno z dwóch, z wartościami zmiennych w template.parameters. Pomiń subject, html i text, ponieważ szablon już je zawiera.

const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  category: "transactional",
  template: {
    slug: "welcome-email",
    parameters: { first_name: "Jane" },
  },
});
console.log(msg.id, msg.status);

Treść szablonu to Liquid, więc oprócz zwykłego podstawiania {{ variable }} może korzystać z filtrów, instrukcji warunkowych {% if %} i pętli {% for %}. Personalizacja za pomocą zmiennych wymienia kilka konstrukcji, które publikacja odrzuca. W template.parameters podajesz wartości własnych parametrów szablonu, według nazwy. Jeśli pominiesz którąś z nich, wysyłka zostanie odrzucona z błędem 422 wskazującym jej nazwę. Wysyłka obsługuje te same tags, metadata, śledzenie i załączniki co e-mail inline. Co jest specyficzne dla wysyłki z szablonem:

  • Inline albo szablon, nigdy oba. Wysłanie template razem z subject, html lub text jest odrzucane z błędem 422. API odrzuca również wartości zmiennych w polu parameters najwyższego poziomu; w wysyłce z szablonem należy je umieścić w template.parameters.
  • bird to jedyna zarezerwowana nazwa. Ścieżka placeholdera zaczynająca się od bird. wskazuje nasze własne dane, takie jak link rezygnacji czy rekord kontaktu odbiorcy, więc klucz template.parameters nie może nosić nazwy bird. Każdy inny klucz możesz zdefiniować sam, a każdy jest prostym pojedynczym słowem: {"order_number": "A-1043"} wypełnia {{ order_number }}.
  • Szablon można wysłać teraz lub później. Dodaj scheduled_at, aby zaplanować wysyłkę. W momencie przyjęcia zapisujemy opublikowaną wersję, wybrany język, parametry przekazane przez wywołującego i wartości kontaktów, więc późniejsze zmiany kontaktów lub wartości zastępczych nie zmieniają przyjętych wiadomości. Jeśli usuniesz szablon przed zaplanowanym czasem wysyłki, wiadomość zostanie odrzucona z błędem generation_failure.
  • Personalizuj za pomocą atrybutów kontaktu. Zobacz wymagania dotyczące kontaktów i domyślne powitania.
  • Dopasowanie kontaktu ignoruje nazwy wyświetlane. Adresy e-mail są zapisywane małymi literami, z zachowaniem kropek i tagów z plusem. Jeśli kilka kontaktów ma ten sam adres, wysyłka zwraca EmailTemplateContactAmbiguous; zaktualizuj zduplikowane rekordy przed ponowną próbą.
  • Wysyłka korzysta z uprawnień e-mail. Klucz z emails:write może wysłać opublikowany szablon bez uprawnienia do wyszukiwania kontaktów. emails:read daje dostęp do niewrażliwej treści wynikowej wiadomości. Wyszukiwanie kontaktów i właściwości zachowuje dotychczasowe uprawnienia.
  • Wysyłka korzysta z opublikowanej wersji szablonu. Wersje robocze nigdy nie są wysyłane. Nieznany szablon jest odrzucany z błędem 404, a szablon bez opublikowanej wersji z błędem 422.
  • language wybiera jeden z języków szablonu. Pomiń go, aby wysłać domyślny język szablonu. Jeśli poprosisz o język, którego szablon nie posiada, jego własne ustawienie on_missing_language decyduje, czy zamiast tego zostanie wysłane najbliższe dopasowanie, czy wysyłka zostanie odrzucona. Szablon z ustawieniem language_source_required odrzuca wysyłkę, która nie wskazuje żadnego języka.
  • Kategoria szablonu jest wartością domyślną, a Twoja ją nadpisuje. Pomiń category, a wysyłka odziedziczy kategorię szablonu, więc szablon transakcyjny nie wymaga powtarzania jej przy każdym wywołaniu.

Szablony e-mail opisują tworzenie, publikowanie i konstrukcje, jakie szablon może zawierać.

Odczyt treści dla odbiorcy

Historia wiadomości z szablonu używa wartości kontaktów zapisanych w momencie przyjęcia wysyłki, nawet jeśli później edytujesz lub usuniesz kontakt. Każde skopiowane dostarczenie ma własny identyfikator odbiorcy.

Pobierz listę odbiorców wiadomości, aby uzyskać ich identyfikatory, a następnie przekaż recipient_id do Get stored message content. Nowa wiadomość z szablonu z wieloma migawkami odbiorców zwraca 422, jeśli nie podasz tego selektora. Pojedynczy odbiorca jest wybierany automatycznie; odbiorca należący do innej wiadomości zwraca 404.

Odpowiedzi GET i listy wiadomości zawierają przyjęty temat dla pierwszego odbiorcy To, wskazanego przez subject_recipient_id. Lista odbiorców podaje własny temat każdego odbiorcy. Tematy te pozostają dostępne, gdy przechowywanie treści jest wyłączone. Odczyty treści nadal podlegają ustawieniom przechowywania i retencji wiadomości, w tym 404, gdy treść nie jest przechowywana, 425 w trakcie przetwarzania i 410 po wygaśnięciu.

Jeśli zachowana migawka odbiorcy stanie się niedostępna, status wiadomości i reprezentatywny temat nadal można odczytać, ale tematy odbiorców są pomijane, a treść jest niedostępna. Odczyty nie pobierają bieżących wartości kontaktów, aby odtworzyć wcześniejszą wysyłkę.

Tagi a metadane

Te pola dołączają Twoje własne dane do wysyłki i różnią się sposobem późniejszego odpytywania:

  • tags to strukturalne pary {name, value}: do 20 na wysyłkę, nazwa do 32 znaków, wartość do 64, tylko litery ASCII, cyfry, podkreślnik i myślnik, nazwy unikalne w ramach wysyłki. Tagi są wymiarami filtrowania, więc możesz filtrować listę wiadomości po tagu oraz dzielić analitykę i podsumowania dashboardu po tagu. Używaj ich dla etykiet o niskiej kardynalności, takich jak campaign, experiment_variant czy source.
  • metadata to dowolny obiekt JSON, do 2 KB po serializacji. Przechowujemy go, zwracamy przy odczytach API i odsyłamy w każdym zdarzeniu webhooka, więc nadaje się do kontekstu, który chcesz odzyskać: wewnętrzne ID, klucze obce, strukturalne payloady.
  • reference to jeden ciąg od 1 do 255 znaków, po którym chcesz wyszukać wiadomość, np. numer zamówienia lub zgłoszenia. GET /v1/email/messages?reference= dopasowuje go dokładnie, z uwzględnieniem wielkości liter, a kilka wiadomości może mieć tę samą wartość. Jest zwracany przy odczytach i odsyłany w zdarzeniach webhooka wiadomości. Ustawiaj go tylko wtedy, gdy musisz po nim wyszukiwać, a pozostałe dane umieszczaj w metadata.

Każde zdarzenie webhooka zawiera tagi i metadane razem z identyfikatorami korelacji (email_id, recipient_id), więc możesz uzgodnić dane ze swoimi rekordami bez dodatkowego odczytu. Nazwy tagów i klucze metadanych najwyższego poziomu zaczynające się od __bird są odrzucane. Nie musisz kodować urządzenia, geografii, dostawcy skrzynki, typu odrzucenia ani domeny odbiorcy w żadnym z tych pól, ponieważ każdy z nich rejestrujemy już jako wymiar analityki.

Przykład kodu
{
  "tags": [{ "name": "campaign", "value": "onboarding" }],
  "metadata": { "user_id": "usr_12345", "order_id": "ord_98765" },
  "reference": "ord_98765"
}

Załączniki

attachments przyjmuje do 20 plików na wiadomość jako bajty zakodowane w base64. Odrzucamy wysyłkę, której szacowany rozmiar wygenerowanej wiadomości przekracza 20 MB (mierzony po kodowaniu base64), więc utrzymuj surową zawartość załączników na poziomie 15 MB lub mniej, jako zapas. Załączniki zawierają kontrakt pól, obrazy inline, zablokowane typy plików i sposób pobierania załącznika.

Co oznacza 202

Udana wysyłka zwraca 202 Accepted z identyfikatorem wiadomości z prefiksem em_ i status: accepted:

Przykład kodu
{
  "id": "em_01ky7ma8y2es1s2akzk53tmjn0",
  "status": "accepted",
  "category": "marketing",
  "from": { "email": "hello@yourdomain.com" },
  "to": [{ "email": "delivered@messagebird.dev" }],
  "subject": "Hello from Bird",
  "accepted_count": 1,
  "processed_count": 0,
  "delivered_count": 0,
  "deferred_count": 0,
  "bounced_count": 0,
  "complained_count": 0,
  "rejected_count": 0,
  "open_count": 0,
  "click_count": 0,
  "track_opens": true,
  "track_clicks": true,
  "created_at": "2026-07-23T13:58:20.866Z"
}

202 oznacza, że trwale przyjęliśmy wysyłkę. Błędy, które możesz naprawić, wracają w samym żądaniu jako 422: niezweryfikowana domena nadawcy lub pole, które nie przechodzi walidacji. Wyniki per odbiorca (dostarczono, odrzucono, odroczono, zgłoszono skargę) docierają potem przez webhooki i endpointy odczytu wiadomości.

Wynikają z tego dwie rzeczy:

  • Odczyty zwracają stan bez treści. GET /v1/email/messages/{message_id} zwraca stan wiadomości i odbiorcy, nigdy treść html ani text. Gdy przechowywanie treści jest włączone dla obszaru roboczego, zapisane treści pozostają dostępne przez maksymalnie 30 dni od GET /v1/email/messages/{message_id}/content.
  • Odczyt może chwilowo nie nadążać za wysyłką. 404 na endpointach odczytu tuż po 202 oznacza, że wiadomość nie jest jeszcze widoczna, więc spróbuj ponownie za chwilę.

Bezpieczne ponawianie

Wyślij nagłówek Idempotency-Key z unikalną wartością dla każdej logicznej wysyłki. Jeśli żądanie się powiodło, ale nie otrzymałeś odpowiedzi, wyślij je ponownie z tym samym kluczem. API zwraca oryginalny wynik zamiast wysyłać drugi e-mail i dołącza nagłówek Idempotency-Replay. Idempotentność opisuje format klucza i czas przechowywania.

Wysyłanie wsadowe

Aby zmniejszyć liczbę żądań API, POST /v1/email/batches przyjmuje do 100 niezależnych wiadomości i waliduje je jako jedną całość. Wywoływanie endpointu pojedynczej wysyłki w pętli również jest obsługiwane. Element wsadu używa payloadu opisanego na tej stronie, włącznie z scheduled_at, więc jeden wsad może łączyć wiadomości natychmiastowe i zaplanowane.

Koszty i rozliczenia

Wysyłki e-mail są mierzone per odbiorca, więc wiadomość do trzech odbiorców liczy się jako trzy wysyłki. W planie Email Free wysyłki są odliczane od jego miesięcznego i dziennego limitu. W płatnym planie Email każda wysyłka jest pobierana z Twojego portfela według stawki planu za 1000 e-maili. Rozliczenia i zużycie opisują model mierzenia i odczyt bieżącego zużycia, a strona z cennikiem e-mail podaje stawkę każdego planu.

Następne kroki

Przejdź do dokumentacji, przewodników i przykładów dotyczących tego tematu.