Skip to main content
Batch sending allows you to send multiple emails at once (up to 100) instead of making individual API requests for each email.

When to use batch sending

Use batch sending when you need to:
  • Send multiple transactional emails (e.g., order confirmations and notifications)
  • Trigger emails to different recipients with unique content
  • Reduce the number of API calls to improve performance
For marketing campaigns, use our no-code editor, Broadcasts, instead.

Send batch emails

You can send up to 100 emails in a single API call using the batch endpoint. Each email in the batch can have different recipients, subjects, and content.
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.batch.send([
  {
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Welcome to Acme',
    html: '<p>Thanks for signing up!</p>',
  },
  {
    from: 'Acme <onboarding@resend.dev>',
    to: ['delivered@resend.dev'],
    subject: 'Order Confirmation',
    html: '<p>Your order has been confirmed.</p>',
  },
]);

console.log(data);
$resend = Resend::client('re_xxxxxxxxx');

$resend->batch->send([
  [
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Welcome to Acme',
    'html' => '<p>Thanks for signing up!</p>',
  ],
  [
    'from' => 'Acme <onboarding@resend.dev>',
    'to' => ['delivered@resend.dev'],
    'subject' => 'Order Confirmation',
    'html' => '<p>Your order has been confirmed.</p>',
  ]
]);
import resend
from typing import List

resend.api_key = "re_xxxxxxxxx"

params: List[resend.Emails.SendParams] = [
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Welcome to Acme",
    "html": "<p>Thanks for signing up!</p>",
  },
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Order Confirmation",
    "html": "<p>Your order has been confirmed.</p>",
  }
]

resend.Batch.send(params)
require "resend"

Resend.api_key = 're_xxxxxxxxx'

params = [
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Welcome to Acme",
    "html": "<p>Thanks for signing up!</p>",
  },
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Order Confirmation",
    "html": "<p>Your order has been confirmed.</p>",
  }
]

Resend::Batch.send(params)
package main

import (
	"context"
	"fmt"

	"github.com/resend/resend-go/v3"
)

func main() {
  ctx := context.TODO()
  client := resend.NewClient("re_xxxxxxxxx")

  var batchEmails = []*resend.SendEmailRequest{
    {
      From:    "Acme <onboarding@resend.dev>",
      To:      []string{"delivered@resend.dev"},
      Subject: "Welcome to Acme",
      Html:    "<p>Thanks for signing up!</p>",
    },
    {
      From:    "Acme <onboarding@resend.dev>",
      To:      []string{"delivered@resend.dev"},
      Subject: "Order Confirmation",
      Html:    "<p>Your order has been confirmed.</p>",
    },
  }

  sent, err := client.Batch.SendWithContext(ctx, batchEmails)

  if err != nil {
    panic(err)
  }
  fmt.Println(sent.Data)
}
use resend_rs::types::CreateEmailBaseOptions;
use resend_rs::{Resend, Result};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let emails = vec![
    CreateEmailBaseOptions::new(
      "Acme <onboarding@resend.dev>",
      vec!["delivered@resend.dev"],
      "Welcome to Acme",
    )
    .with_html("<p>Thanks for signing up!</p>"),
    CreateEmailBaseOptions::new(
      "Acme <onboarding@resend.dev>",
      vec!["delivered@resend.dev"],
      "Order Confirmation",
    )
    .with_html("<p>Your order has been confirmed.</p>"),
  ];

  let _emails = resend.batch.send(emails).await?;

  Ok(())
}
import com.resend.*;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Resend resend = new Resend("re_xxxxxxxxx");

        CreateEmailOptions firstEmail = CreateEmailOptions.builder()
            .from("Acme <onboarding@resend.dev>")
            .to("delivered@resend.dev")
            .subject("Welcome to Acme")
            .html("<p>Thanks for signing up!</p>")
            .build();

        CreateEmailOptions secondEmail = CreateEmailOptions.builder()
            .from("Acme <onboarding@resend.dev>")
            .to("delivered@resend.dev")
            .subject("Order Confirmation")
            .html("<p>Your order has been confirmed.</p>")
            .build();

        CreateBatchEmailsResponse data = resend.batch().send(
            Arrays.asList(firstEmail, secondEmail)
        );
    }
}
using Resend;

IResend resend = ResendClient.Create("re_xxxxxxxxx");

var mail1 = new EmailMessage()
{
    From = "Acme <onboarding@resend.dev>",
    To = "delivered@resend.dev",
    Subject = "Welcome to Acme",
    HtmlBody = "<p>Thanks for signing up!</p>",
};

var mail2 = new EmailMessage()
{
    From = "Acme <onboarding@resend.dev>",
    To = "delivered@resend.dev",
    Subject = "Order Confirmation",
    HtmlBody = "<p>Your order has been confirmed.</p>",
};

var resp = await resend.EmailBatchAsync([mail1, mail2]);
Console.WriteLine("Nr Emails={0}", resp.Content.Data.Count);
curl -X POST 'https://api.resend.com/emails/batch' \
     -H 'Authorization: Bearer re_xxxxxxxxx' \
     -H 'Content-Type: application/json' \
     -d $'[
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Welcome to Acme",
    "html": "<p>Thanks for signing up!</p>"
  },
  {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Order Confirmation",
    "html": "<p>Your order has been confirmed.</p>"
  }
]'

Response format

The batch endpoint returns an array of email IDs for successfully created emails. When the request succeeds, each entry in data corresponds to the email at the same index in the batch payload (0-based). The first email in your request will be the first entry in data, and so on.
{
  "data": [
    {
      "id": "ae2014de-c168-4c61-8267-70d2662a1ce1"
    },
    {
      "id": "faccb7a5-8a28-4e9a-ac64-8da1cc3bc1cb"
    }
  ]
}
If the request fails, the response will include an error object with a message property. You can find more information about the error in the Errors section of the API Reference.

Limitations

When using batch sending, keep in mind:
  • Maximum of 100 emails per batch request
  • The attachments field is not supported yet
  • The scheduled_at field is not supported yet
  • Each email in the batch is processed independently
  • The request will fail and return an error if any email in your payload is invalid (for example, required fields are missing or fields contain invalid data).

View batch emails

All emails sent via the batch endpoint appear in the Emails page of your dashboard along with individually sent emails. Each email will have a queued status initially before being processed.

API Reference

For complete API documentation, see the Send Batch Emails API reference.