Skip to content

Send a message

const { data, error } = await resend.emails.send({
from: "Acme Billing <[email protected]>",
subject: "Your receipt",
html: "<p>Thanks for your order.</p>",
});
data?.id; // dlv_… the delivery this send left behind

from is required, exactly as Resend requires it, and has to be on a domain you verified. See Sending and delivery.

to, cc, bcc and reply_to each take one address or a list, headers are passed on, and tags are accepted and dropped, because Cowliss labels a delivery by its own fields.

Every send is checked against your credit and your suppression list first. An address that has bounced or complained is dropped from the message; if that leaves nobody, the call still answers with an id and the delivery records that it was suppressed.

template names a template key, variables are its props:

await resend.emails.send({
template: { id: "vip-order", variables: { orderId: "A-2291" } },
});

The template writes the whole message, so a subject, html or text beside it is refused: a message either names a template or writes its own body. The props are checked by the template itself, exactly as they are when you press Send test on its page. See Email templates.

Only a transactional template can be sent this way. A marketing template is refused, because a direct send carries no consent purpose, so there is nothing to check an unsubscribe against. Send those from a journey.

The delivery records the template key, so a template’s page shows what your code sent beside what your journeys sent.

const { data } = await resend.emails.get("dlv_…");

You get Resend’s email object: the id, the provider’s message_id, the addresses, the subject, when it was created, and last_event. Cowliss keeps no rendered bodies, so html and text are always null, scheduled_at is null, and tags is empty.

Where the message got to last_event
Handed over sent
Accepted by the recipient’s mail server delivered
Rejected bounced
Marked as spam complained
Stopped before it went, or failed on the way failed