Reference

Testing Without Sending

Exercise your webhook handlers, your retry logic and your bounce and complaint paths against real SendFleet events, without emailing a real person and without moving a single one of your numbers.

The test addresses

Use them anywhere you would use a real recipient address. The request is accepted, the log row is written, and the matching webhook fires, with the same payload shape as a genuine delivery event, so your handler cannot tell the difference by its keys.

SendFleet test addresses and the outcome each one produces
AddressYou getWebhook
delivered@sendfleet.netLog status delivered, with a delivered_at timestampemail.delivered
bounce@sendfleet.netLog status bounced, bounce type Permanent / subtype Generalemail.bounced
complaint@sendfleet.netLog status complained, with a complained_at timestampemail.complained

success@sendfleet.net and sent@sendfleet.net are accepted aliases for delivered@, and bounced@ / complained@ for the other two, in case the spelling in your fixtures already reads that way. Matching is case-insensitive, and a display name (QA <bounce@sendfleet.net>) is fine.

Making a test send

There is nothing to configure. It is the same endpoint, with a test address in to:

cURL: trigger a test bounce
curl -X POST https://sendfleet.net/api/send/ \
  -H "X-API-Key: $SENDFLEET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "you@yourdomain.com",
    "to":   "bounce@sendfleet.net",
    "subject": "Webhook smoke test",
    "html": "<p>If you can read this in your handler, testing works.</p>"
  }'

The response is an ordinary 200 with an extra entry in warnings:

Response from a test send
{
  "success": true,
  "message": "Email queued for delivery.",
  "message_id": "…",
  "mode": "shared",
  "warnings": [
    "Test send: this counts towards your monthly quota like any other send, but is not counted towards your bounce or complaint rates."
  ]
}

What the webhook payload looks like

Identical in shape to a genuine event, so the same verification and parsing code handles both. Two values necessarily differ: the message ID is a synthetic sendfleet-test-… string rather than an AWS one, and SMTP-level detail is a fixed placeholder (smtp_response on a delivery, for instance) because no SMTP conversation happened.

Payload from bounce@sendfleet.net
{
  "idempotency_key": "8f14e45fceea167a5a36dedd4bea2543",
  "ses_message_id": "sendfleet-test-3f9c…",
  "recipient": "bounce@sendfleet.net",
  "status": "bounced",
  "bounce_type": "Permanent",
  "bounce_subtype": "General",
  "bounced_recipients": ["bounce@sendfleet.net"],
  "timestamp": "2026-09-26T14:03:11.482913+00:00"
}
Request fields that behave differently for a test send
FieldBehaviour
toMust be one of the addresses above. Any other address is real traffic and is treated as such.
fromMust still be a verified sender domain in your account. The normal sending gates run first, so a test send cannot be used to bypass domain verification.
attachmentsAccepted and staged as normal, then discarded with the rest of the test send. Nothing is transmitted.
idempotency_keyBehaves exactly as on a real send. A retried test send with the same key is deduplicated the same way.

What counts and what does not

What a test send does to your numbers
CounterEffect of a test send
Monthly send allowanceCounts, like any other send. At your limit a test send gets the same 429 usage_limit_exceeded.
Bounce rateNone. This is the reason the addresses exist: pointing a staging deploy at bounce@sendfleet.net cannot push an account over a limit.
Complaint rateNone, for the same reason.
Email logA row is written, exactly as for real traffic, and is purged on the normal 14-day schedule.
Customer webhooksFire normally. That is the point.

The AWS SES simulator

Anything at simulator.amazonses.com is treated the same way for your numbers (it counts against your monthly allowance and never against your rates), with one important difference: it is handed to AWS. The SES simulator accepts and swallows simulator addresses, which is what makes it useful when you are testing your SES-level configuration.

cURL: send to the SES simulator
curl -X POST https://sendfleet.net/api/send/ \
  -H "X-API-Key: $SENDFLEET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "you@yourdomain.com",
    "to":   "bounce@simulator.amazonses.com",
    "subject": "SES-level smoke test",
    "html": "<p>Handed to AWS and swallowed there.</p>"
  }'
Test addresses versus the SES simulator
ItemTest addressSES simulator
Handed to AWSNoYes, and swallowed there
Appears in the email logYesYes
Fires your webhookYesYes, if AWS reports the outcome
Counts against your monthly allowanceYesYes
Counts toward bounce / complaint ratesNoNo
Use it to testYour SendFleet integration: handlers, retries, error pathsYour AWS SES configuration, from the SendFleet API

BYOC

This is not an oversight and it is worth understanding why. The test addresses work by SendFleet fabricating the delivery event itself: that is what gives you a webhook without a message leaving our infrastructure. On BYOC your own AWS account performs the send, and that account has no event destination wired to SendFleet, so there is nothing for us to fabricate. A BYOC send to bounce@sendfleet.net would put a real message into your SES, addressed to a mailbox that does not exist: your account would look the address up, get a real non-delivery report, and count it against the sender reputation you own, and you would get no webhook, because BYOC delivers no delivery events at all.

What happens per recipient on a BYOC domain
RecipientResult
bounce@ / complaint@ / delivered@sendfleet.netRefused with 403 unauthorized. Nothing queued, nothing billed, no message in your account.
*@simulator.amazonses.comSent. SES accepts and swallows simulator addresses in any account, so on BYOC this does what you asked without touching your reputation. On Free BYOC it counts against the monthly allowance like any other send.
A real addressOrdinary BYOC send. Nothing changes.

To exercise a BYOC integration, send to a real address you control. A plus-addressed alias on a domain you own is enough to verify SPF, DKIM, DMARC and your own suppression handling end to end, and it costs you one message against your own quota rather than a permanent NDR in your account.

Testing a production-shaped flow

A pattern that keeps a permanent staging configuration from ever touching a real address list: keep your sandbox credentials pointed at the test addresses, and let promotion to production be the only thing that swaps them.

Node.js: send only test addresses outside production
const TEST_ADDRESSES = new Set([
  "delivered@sendfleet.net",
  "bounce@sendfleet.net",
  "complaint@sendfleet.net",
])

// `config` stands for however your app already reads its environment.
async function send({ to, ...mail }) {
  // Outside production, refuse to mail a real person. Inside production,
  // refuse to pretend: a test address there is almost always a mistake.
  const isTest = TEST_ADDRESSES.has(to) || to.endsWith("@simulator.amazonses.com")

  if (!config.isProduction && !isTest) {
    throw new Error(`refusing to send to ${to} outside production`)
  }
  if (config.isProduction && isTest) {
    throw new Error(`refusing to send to test address ${to} in production`)
  }

  return post("/api/send/", {
    ...mail,
    to,
    apiKey: config.sendfleetApiKey,
  })
}

Frequently asked questions

Test addresses, what they cost you, and where they work.

How do I test my bounce and complaint handling without emailing real people?
Send to one of the SendFleet test addresses: delivered@sendfleet.net for a successful delivery, bounce@sendfleet.net for a hard bounce, and complaint@sendfleet.net for a spam complaint. Each one produces a real webhook with the same payload shape as a genuine event and a matching entry in your email log, without a message ever leaving our infrastructure.
Do test sends count against my usage or my bounce rate?
They count against your monthly allowance like any other send, and at your limit they get the same 429 usage_limit_exceeded. They never count toward your bounce or complaint rates, which is why you can point your integration at bounce@sendfleet.net during a deploy without putting your account at risk. The response carries a warnings entry saying so.
What about the AWS SES simulator addresses?
Anything at simulator.amazonses.com is handled the same way for your numbers: it counts against your monthly allowance and is never included in your bounce or complaint rates. The difference is that it is handed to AWS, because the SES simulator accepts and swallows it, which is useful if you are testing at the SES level rather than at the SendFleet level. Your email log and your webhooks still record it.
Do test sends work on BYOC?
No. The test addresses work by SendFleet generating the delivery event itself, which is what gives you a webhook without a message being sent. On BYOC your own AWS account performs the send and has no event destination connected to SendFleet, so there is nothing for us to generate. A BYOC send to bounce@sendfleet.net is refused with HTTP 403 unauthorized rather than delivered, because it would otherwise produce a real non-delivery report in your account and count against the sender reputation you own, while producing no webhook for you to test. Anything at simulator.amazonses.com does work on BYOC, since SES accepts and swallows those addresses in any account; on Free BYOC it counts against the monthly allowance like any other send.