Groups & send limits
Mailbox groups are where per-mailbox send rate limits, spam thresholds, and retention overrides live.
A mailbox group is a policy bundle you attach mailboxes to. It is where per-mailbox send rate limits live, along with a spam threshold and a retention override. Use groups to stop one high-volume mailbox from burning a domain's whole sending reputation, and to hold different mailboxes to different rules.
A mailbox joins a group through its groupId (see Mailboxes). A
mailbox with no group has no per-mailbox send cap of its own, though the
project's default limits and your plan allowance still apply.
How limits resolve
Send limits resolve down a chain, most specific wins:
platform default -> project default -> group overrideA field left null on the group inherits the project default; a field left
null on the project inherits the platform default. So a group only needs to
set the fields it wants to change. Project defaults are set under
Settings (see Sending); the group is the tighter, per-cohort
layer on top.
Create
Groups are project scoped, so pass the project with X-Project-Id:
import { Postbox } from "@postbox/sdk";
const pb = new Postbox({
apiKey: process.env.PB_KEY!,
projectId: process.env.PROJECT_ID!,
});
const group = await pb.mailboxGroups.create({
name: "Transactional",
hourlyLimit: 500,
dailyLimit: 5000,
burstLimit: 50,
});import os
from postbox import Postbox
pb = Postbox(api_key=os.environ["PB_KEY"], project_id=os.environ["PROJECT_ID"])
group = pb.mailbox_groups.create(
{
"name": "Transactional",
"hourlyLimit": 500,
"dailyLimit": 5000,
"burstLimit": 50,
}
)using Postbox;
var pb = new PostboxClient(
new PostboxOptions
{
ApiKey = Environment.GetEnvironmentVariable("PB_KEY")!,
ProjectId = Environment.GetEnvironmentVariable("PROJECT_ID")!,
}
);
var group = await pb.MailboxGroups.CreateAsync(
new MailboxGroupsCreateBody
{
Name = "Transactional",
HourlyLimit = 500,
DailyLimit = 5000,
BurstLimit = 50,
}
);import cloud.postboxapp.*;
import cloud.postboxapp.gen.*;
import java.util.*;
Postbox pb = new Postbox(PostboxOptions.builder().apiKey(System.getenv("PB_KEY")).projectId(System.getenv("PROJECT_ID")).build());
var group = pb.mailboxGroups.create(MailboxGroupsCreateBody.builder().name("Transactional").hourlyLimit(500.0).dailyLimit(5000.0).burstLimit(50.0).build());import postbox "github.com/postboxapp/postbox-go"
pb, err := postbox.New(postbox.Options{APIKey: os.Getenv("PB_KEY"), ProjectID: os.Getenv("PROJECT_ID")})
ctx := context.Background()
group, err := pb.MailboxGroups.Create(ctx, &postbox.MailboxGroupsCreateBody{Name: "Transactional", HourlyLimit: 500, DailyLimit: 5000, BurstLimit: 50})curl -X POST https://api.postboxapp.cloud/v1/mailbox-groups \
-H "Authorization: Bearer $PB_KEY" \
-H "X-Project-Id: $PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Transactional",
"hourlyLimit": 500,
"dailyLimit": 5000,
"burstLimit": 50,
"spamScoreThreshold": 5,
"actionOnSpam": "junk",
"retentionDays": 90
}'| Field | Required | Notes |
|---|---|---|
name | yes | Label for the group. |
hourlyLimit | no | Max sends per rolling hour. null inherits the project default. |
dailyLimit | no | Max sends per rolling day. null inherits. |
burstLimit | no | Max sends in a short burst window. null inherits. |
spamScoreThreshold | no | 0 to 10. Inbound score at or above which the spam action fires for this group's mailboxes. |
actionOnSpam | no | reject, junk, or tag. What to do when the threshold is hit. |
retentionDays | no | Delete stored mail older than this. null keeps mail indefinitely. |
Setting a limit to 0 is a real value: a hard pause, not "unlimited". Use null
to inherit instead.
List, fetch, update, delete
await pb.mailboxGroups.list();
await pb.mailboxGroups.get(groupId);
await pb.mailboxGroups.update(groupId, { hourlyLimit: 1000 });
await pb.mailboxGroups.delete(groupId);pb.mailbox_groups.list()
pb.mailbox_groups.get(group_id)
pb.mailbox_groups.update(group_id, {"hourlyLimit": 1000})
pb.mailbox_groups.delete(group_id)await pb.MailboxGroups.ListAsync();
await pb.MailboxGroups.GetAsync(groupId);
await pb.MailboxGroups.UpdateAsync(groupId, new MailboxGroupsUpdateBody { HourlyLimit = 1000 });
await pb.MailboxGroups.DeleteAsync(groupId);pb.mailboxGroups.list();
pb.mailboxGroups.get(groupId);
pb.mailboxGroups.update(groupId, MailboxGroupsUpdateBody.builder().hourlyLimit(1000.0).build());
pb.mailboxGroups.delete(groupId);pb.MailboxGroups.List(ctx)
pb.MailboxGroups.Get(ctx, groupID)
pb.MailboxGroups.Update(ctx, groupID, &postbox.MailboxGroupsUpdateBody{HourlyLimit: 1000})
pb.MailboxGroups.Delete(ctx, groupID)curl https://api.postboxapp.cloud/v1/mailbox-groups \
-H "Authorization: Bearer $PB_KEY" -H "X-Project-Id: $PROJECT_ID"
curl https://api.postboxapp.cloud/v1/mailbox-groups/$GROUP_ID \
-H "Authorization: Bearer $PB_KEY" -H "X-Project-Id: $PROJECT_ID"
curl -X PATCH https://api.postboxapp.cloud/v1/mailbox-groups/$GROUP_ID \
-H "Authorization: Bearer $PB_KEY" -H "X-Project-Id: $PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{ "hourlyLimit": 1000 }'
curl -X DELETE https://api.postboxapp.cloud/v1/mailbox-groups/$GROUP_ID \
-H "Authorization: Bearer $PB_KEY" -H "X-Project-Id: $PROJECT_ID"PATCH is a partial update: send only the fields you want to change. Every field
accepted on create is editable, including name.
Attach a mailbox
Set groupId when you create a mailbox, or patch it later. Setting groupId to
null detaches the mailbox, which also drops its per-mailbox send limits back to
the project default.
await pb.mailboxes.update(mailboxId, { groupId: group.id });
await pb.mailboxes.update(mailboxId, { groupId: null }); // detachA group is a shape, not a container
Mailboxes are not stored "inside" a group. The group holds the rules; a mailbox points at it. Deleting a group leaves its mailboxes in place, back on the project defaults.