CarlyEmail docs

Allow and block lists

Who you will accept mail from, and who you will write to.

Lists are addressed as /v0/lists/{direction}/{type}.

Direction Type Effect
receive block Mail from the address never reaches the inbox
receive allow Only listed senders reach the inbox
send block Sending to the address is refused
send allow Only listed recipients can be sent to
reply block Replies on an existing thread are refused; new messages are not

An entry is one address (someone@example.org) or a whole domain (example.org, which covers everyone on it). Entries are stored lowercased and matching ignores case.

Blocking

curl -X POST https://api.carlyemail.com/v0/lists/receive/block \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
  -H 'content-type: application/json' \
  -d '{"entry": "noreply@example.org", "reason": "nothing useful here"}'

Blocked inbound mail is kept, not deleted. It is stored with the blocked label, left out of listings unless you ask for it, and raises message.received.blocked instead of message.received — so a webhook or an agent watching the ordinary event never sees it, and you can still go and look.

curl "https://api.carlyemail.com/v0/inboxes/$INBOX_ID/messages?include_blocked=true" \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY"

A blocked recipient on the outbound side is refused before anything is sent, with recipient_blocked.

Allowing

Warning

An allow list is exhaustive as soon as it is not empty. With no entries, everyone is permitted. Add one entry and everyone else is refused — that is what an allow list is for, and it is easy to do by accident.

curl -X POST https://api.carlyemail.com/v0/lists/send/allow \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
  -H 'content-type: application/json' \
  -d '{"entry": "customer.example"}'

That agent can now email customer.example and nowhere else. Sending anywhere else returns recipient_not_allowed. Empty the list to permit everyone again.

A block beats an allow wherever the two disagree.

Scope

Every list exists at two scopes. /v0/lists/… applies to the whole organization; /v0/inboxes/{inbox_id}/lists/… applies to one mailbox. Both are consulted, so an organization-wide block cannot be escaped by an inbox-level allow.

What is matched

On the way out, every recipient — to, cc and bcc alike.

On the way in, both the From header and the envelope sender, which are not always the same address. A block on either refuses the message: a sender who puts a different bounce address in the envelope is still that sender. An allow only has to match one of them, because legitimate list mail routinely arrives from bounces-1234@ with the real sender named only in the header.

Automatic entries are read-only

When a recipient hard-bounces or marks your mail as spam, that address is added to your organization's send/block list automatically, with the reason and the event that caused it.

You can see those entries; you cannot delete them. That is deliberate, and it is not us being precious: sending providers suspend an account at roughly a 5% bounce rate or a 0.1% complaint rate. Continuing to mail an address that already complained is the fastest route to losing the ability to send at all — for you and, on a shared domain, for everyone else.

A soft bounce — a full mailbox, a temporary server problem — does not suppress. Those recover, and suppressing on them loses real mail.

Automatic suppression is send only. An address that bounced can still write to you.

Watching your rates

GET /v0/metrics/events gives sends, deliveries, bounces and complaints over time, per organization and per pod — so you can tell which agent is generating bounces, not just that something is.