Search the docs

Find a page, a section, or an endpoint.

Pods

A container per customer, with its own sending reputation.

Most accounts never need one. If what you are building hands addresses to its own users — a tenant per landlord, per client, per customer — a pod is where each of them goes.

A pod holds addresses and domains, and it is a real boundary rather than a folder: mail sent from a pod lands on that pod's own sending reputation. So when one of your customers mails a thousand dead addresses, the bounces are theirs. Your other customers keep delivering.

That is the reason this product is on Amazon SES rather than anywhere cheaper, and it is the thing you cannot add afterwards — on a provider with one shared reputation, one careless user degrades delivery for everybody.

GET    /v1/pods                                              yours, the default first
POST   /v1/pods                                              make one
GET    /v1/pods/2f0f6a1c-9a4e-4e26-9a60-2b4c0f5e1d33          one of them
PATCH  /v1/pods/2f0f6a1c-9a4e-4e26-9a60-2b4c0f5e1d33          rename it, or change your own id for it
DELETE /v1/pods/2f0f6a1c-9a4e-4e26-9a60-2b4c0f5e1d33          delete it, with its addresses and their mail

Making one, and putting addresses in it

json
POST /v1/pods
{ "name": "Acme Ltd", "client_id": "cus_8812" }

name is what a person reads. client_id is your id for this customer, carried and returned and never parsed by us — so your own system can look a pod up by the key it already has, instead of keeping a mapping table.

Then name the pod when you create their addresses:

json
POST /v1/identities
{ "address": "hello@yourdomain.com", "type": "agent", "pod_id": "2f0f6a1c-9a4e-4e26-9a60-2b4c0f5e1d33" }

Leave pod_id out and the address goes in your account's default pod, which every account has from the day it is created — including yours, right now, before you have ever thought about this. Nothing you have already built is in the wrong place.

GET /v1/identities?pod_id=… lists one pod's addresses, and every address you read carries the pod_id it is in.

A domain can be in several pods at once, so two of your customers sending from the same domain of yours are isolated from each other at Amazon SES, and yourdomain.com does not have to be added twice. Gmail and Outlook still judge them together, by the domain: Which domain says when to give each customer a domain of its own.

Checking the isolation rather than trusting it

A claim about reputation that you cannot measure is a claim. GET /v1/metrics takes a pod_id, and answers for that pod alone:

GET /v1/metrics?pod_id=2f0f6a1c-9a4e-4e26-9a60-2b4c0f5e1d33&days=30
json
{
"data": {
  "pod": { "id": "2f0f6a1c-9a4e-4e26-9a60-2b4c0f5e1d33", "name": "Acme Ltd" },
  "reputation": { "sending": "enabled" },
  "outbound": { "sent": 1840, "delivered": 1792, "bounced": 41, "rejected": 0, "complained": 7, "delivery_rate": 0.9739 },
  "inbound": { "received": 612, "spam": 9 }
}
}

Put two pods' numbers side by side and the separation is the answer: one customer's bounce rate is theirs.

reputation.sending is the part nothing else can tell you.

  • enabled — the provider is taking mail from this pod.
  • paused — the provider has suspended this pod and nobody else, because of its own bounce or complaint rate. Mail from it queues and retries rather than failing outright, which is correct and is also why you would otherwise never find out. This is how you find out.
  • unknown — we cannot say. A pod that has never sent has no reputation yet, which is the usual reason.

Deleting one

DELETE /v1/pods/{id}?delete_addresses=true revokes the pod's keys and deletes every address in it with all of its mail, then the pod. Without delete_addresses=true a pod that holds an address is refused, so deleting mail is never an accident. The default pod and a pod holding a domain can't be deleted. The whole sequence, and what to do instead to keep the mail, is in Pidgeon for platforms.

To offboard a customer and keep the record of what was said, suspend their addresses instead: suspension keeps the mail.

Making a pod, its first address and its key in one call is there too: provisioning.

A key for one pod

The credential you hand one customer. Create a key with pod_id instead of identity_ids and it reaches every address in that pod — including the ones the pod gains later — and nothing outside it. It can also add, verify and remove that pod's own domains, so a customer can bring their domain without your help, and it sees its own pod and no other in GET /v1/pods.

cURL
curl https://pidgeon.ai/api/v1/api-keys \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Acme", "pod_id": "your-pod-id", "access": "send" }'

Only a key that reaches the whole account can mint one, and a pod key cannot mint another — so a customer can never widen what you gave them. Move an address out of the pod and the key loses it. A private pod is the exception: below.

A private pod

By default your account reads every pod's mail: your key over the whole account, your team in the dashboard and your webhooks. Make a pod private and its mail is readable only with the pod's own keys. Your account keeps the pod, its name and its bill, and can delete it; it can no longer read what is in it.

cURL
curl -X PATCH https://pidgeon.ai/api/v1/pods/your-pod-id \
-H "Authorization: Bearer $PIDGEON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "private": true }'

Or pass "private": true to POST /v1/pods, and the pod is made private once its key exists. Your account can make a pod private and never public again: only one of the pod's own keys at admin can turn it back, so the choice stays with the customer. In a private pod:

  • your account's keys, your team and your webhooks stop reaching its mail;
  • only the pod's own key at admin mints more keys for it;
  • a mail-app password one of your people made for it stops working.

What a pod is not

It is not billed for. Each plan includes a number of pods: Hobby three, Builder ten, Startup twenty-five, and Enterprise no limit. Inboxes are unlimited on every plan, so splitting them across pods costs nothing, and a platform counting its own customers against an invoice is the friction this feature exists to remove. See Limits.