Search the docs
Find a page, a section, or an endpoint.
Allow and block lists
Who may write to an address, and who it may write to.
Two lists, one per direction. Who may write to an address, and who that address may write to. They are separate endpoints because they answer different questions and have different consequences — one decides what you are charged for storing, the other decides what leaves.
Both are scoped to a single address. There is no list that silences a sender for a whole account over the API, deliberately: a key that administers one address must not be able to change what fourteen other addresses receive.
Who may write to you
GET /v1/identities/idn_4f2a/receive-rules
POST /v1/identities/idn_4f2a/receive-rules { "action": …, "value": … }
DELETE /v1/identities/idn_4f2a/receive-rules?rule_id=…value is an address or a domain and the string says which:
billing@acme.com matches one person, acme.com matches everybody there. You
are not asked to classify it, because a caller asked to classify it will
eventually classify it wrong.
action is one of five:
action | What happens |
|---|---|
reject | The message is refused before it is stored. No row, no thread, nothing. |
spam | Stored, and filed as spam. |
trash | Stored, and filed as deleted. |
archive | Stored, and skips the inbox. |
inbox | Never classify this sender as spam. The rescue, not a block. |
curl -X POST https://pidgeon.ai/api/v1/identities/idn_4f2a/receive-rules \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-d '{ "action": "reject", "value": "noreply@spam.example" }'reject is the one worth understanding
The other four decide where a message goes. reject decides whether there
is one at all — it refuses before the insert, so nothing is stored, nothing is
threaded, no storage is charged and no webhook fires.
That last part is the reason it exists. message.spam is a deliverable event,
so before this an address under sustained abuse was paying storage and
webhook deliveries for every message its owner had already said they did not
want. For a mailbox a person reads, spam is right — you want to be able to
look. For an address no human will ever open, reject is.
It is not a security control. The From: header is written by the sender,
and anybody blocked can change it for the price of a new address. What reject
buys is not paying for mail from senders who have not bothered, which is most
of them. If you need to be certain who sent something, read the
authentication results on the message rather than its From:.
The more specific rule wins
A rule naming an address beats a rule naming its domain, so blocking a whole domain and letting one person through does what it looks like:
reject acme.com — everybody at acme.com
inbox billing@acme.com — except billing@, which is never spamAnd an address's own rule beats an account-wide one. Rules made in the dashboard apply to every address; rules made through this endpoint apply to one, and the one wins. That ordering is what makes this address receives verification codes from one service and nothing else expressible without touching anything else you own.
Who you may write to
GET /v1/identities/idn_4f2a/send-rules
POST /v1/identities/idn_4f2a/send-rules { "effect": "allow" | "block", "value": … }
DELETE /v1/identities/idn_4f2a/send-rules?rule_id=…effect rather than action, because the outbound side has a verdict rather
than a destination. The same matching applies — address beats domain, adding
replaces.
These rules hang off the address's send policy, which GET returns beside
them and which is set with PATCH /v1/identities/{id}:
send_policy | Who it may write to |
|---|---|
open | Anyone. |
reply_only | Anyone who has written to it first, plus its allow list. |
list | Only its allow list. |
A block rule refuses under every policy, including open. A block list
that a setting could switch off is not a block list.
A refusal tells you which kind it was: blocked means a rule said no,
not_permitted means the policy did. They are different things to be told, and
an agent debugging a send needs to know which.
Reply is not a third list
An address that may receive from somebody and must not answer them is one
block rule on the send side. There is no separate reply list, because it
would be a second way to express a rule that already exists.
reply_only is the opposite case — may write, but only to people who wrote
first — and it is a policy rather than a list.
Reading the rules from an agent
The MCP server exposes both as read-only tools — list_receive_rules and
list_send_rules — so an agent asking why did nothing arrive or why was
that refused can answer it. Writing a rule is deliberately not a tool: an
agent that can edit its own lists can quietly stop its own mail.