Skip to main content
A pod is an isolated workspace inside your account. Each pod holds its own inboxes, so you can give every one of your end users (or tenants, agents, or projects) a clean, separate slice of OpenMail while keeping a single account and API key. Pods are designed for multi-tenant apps. If you run one agent for yourself, you don’t need to think about them — your inboxes simply live in your account’s default pod.

The hierarchy

Account (your OpenMail account, one API key)
├── Domain (account-wide)       ← usable by every pod; optional
├── Default pod                 ← inboxes land here unless you say otherwise
│   ├── Inbox
│   └── Inbox
├── Pod (your customer A)
│   ├── Domain (scoped)         ← only this pod can use it
│   ├── Inbox
│   └── Inbox
└── Pod (your customer B)
    ├── Domain (scoped)
    ├── Inbox
    └── Inbox
  • Account — Your business. One account, one set of API keys, one bill.
  • Pod — A tenant in your product (a customer, end user, agent, or environment). Provides organizational isolation between sets of inboxes.
  • Domain — A verified custom domain. Either account-wide (lives at account level, any pod can use it) or scoped to one pod (lives under that pod). A domain cannot be scoped to more than one pod, but not all pods.
  • Inbox — An email address. Always belongs to exactly one pod.

When to use pods

  • Multi-tenant SaaS / agencies — Create one pod per customer account so their inboxes never mix with another customer’s.
  • White-label email — Give each end user their own pod and keep their data cleanly separated under your brand.
  • AI agent platforms — Give each agent (support, sales, marketing) its own pod with dedicated inboxes.
  • Environments or teams — Separate staging from production, or teams from each other, under one account.
If you just need many inboxes under one umbrella and don’t require isolation, you can skip pods and create inboxes directly — they land in the default pod.

Common patterns

The same building block — one pod per tenant — maps onto a few common shapes. Multi-tenant SaaS — one pod per customer company, addressed by your own tenant ID:
Account
├── Pod  clientId: "meridian"        (Meridian Analytics)
│   ├── Domain: meridian.io
│   ├── support@meridian.io
│   └── billing@meridian.io
└── Pod  clientId: "cedar"          (Cedar Works)
    ├── Domain: cedarworks.com
    ├── hello@cedarworks.com
    └── team@cedarworks.com
Agency / white-label — one pod per client you manage on their behalf:
Account
├── Pod  clientId: "client-vantage"   (Vantage Retail)
│   ├── Domain: vantageretail.com
│   └── info@vantageretail.com
└── Pod  clientId: "client-slate"    (Slate Capital)
    ├── Domain: slatecapital.ai
    └── support@slatecapital.ai
AI agent platform — one pod per agent, each with its own set of inboxes:
Account
├── Domain: relaystack.com          ← account-wide; shared across agent pods
├── Pod  "support-agent"
│   ├── support@relaystack.com
│   ├── help@relaystack.com
│   └── tickets@relaystack.com
└── Pod  "sales-agent"
    ├── sales@relaystack.com
    ├── outreach@relaystack.com
    └── leads@relaystack.com
Each tenant pod typically owns its own scoped domain. When several pods share one domain (like the agent platform above), keep it account-wide so every pod can use it.

The default pod

Every account has exactly one default pod, created automatically when you sign up.
  • Any inbox you create without specifying a pod lands in the default pod.
  • The default pod is always listed first and is marked with "isDefault": true.
  • It cannot be deleted.

clientId

When you create a pod you can pass your own clientId — a stable identifier from your own system, such as your user or tenant ID.
{
  "clientId": "meridian",
  "name": "Meridian Analytics"
}
The clientId must be unique within your account. Once set, you can address a pod by it anywhere the API takes a pod identifier — without ever storing OpenMail’s pod ID:
# Get a pod by your own identifier
curl https://api.openmail.sh/v1/pods/meridian \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"

# Create an inbox directly in that pod
curl -X POST https://api.openmail.sh/v1/inboxes \
  -H "Authorization: Bearer $OPENMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"podId": "meridian"}'
Pass your own user or tenant ID as clientId at signup. Then you can create and look up that tenant’s inboxes using your ID, with no extra mapping table on your side.
Both clientId and name are optional. Omit clientId and OpenMail still generates a pod with its own ID.

Scoping inboxes to a pod

Pods and inboxes connect through the inbox’s podId:
  • Create — Pass podId (a pod ID or clientId) to POST /v1/inboxes to place the inbox in that pod. Omit it to use the default pod.
  • List — Pass podId to GET /v1/inboxes to return only that pod’s inboxes.
  • Read — Every inbox response includes its podId.
An inbox always belongs to exactly one pod. Inboxes cannot be moved between pods after creation — pick the pod when you create the inbox.

Custom domains and pods

Custom domains sit in one of two places in the hierarchy:
ScopeWhere it livesWho can use it
Account-wideUnder the account (not inside a pod)Any pod
Pod-scopedUnder that podOnly inboxes in that pod
When you create an inbox, domain and podId must agree: pod-scoped domains require the inbox in that same pod; account-wide domains work in any pod. You cannot scope a domain to several pods but not all — it is either one pod or every pod. Manage scope from the dashboard (Settings → Domains, or a pod’s Domains tab). See Pod scoping for DNS, verification, and reassignment rules.

What pods do and don’t isolate

Pods give you organizational isolation — a clean way to group and scope inboxes per tenant. They are not a network or permission boundary:
  • Email is not walled off. Inboxes in different pods are still ordinary email addresses; they can send to and receive from each other and the outside world.
  • API keys are account-wide. An account API key can read and write resources in every pod. There are no pod-scoped API keys today, so don’t hand a raw account key to an end user as a way to limit them to their pod.

Lifecycle

You can delete a pod with DELETE /v1/pods/:id, with these guardrails:
  • The pod must be empty — delete its inboxes first, or you’ll get pod_not_empty (409).
  • The pod must not own pod-scoped custom domains — reassign them to account-wide or another pod first, or you’ll get pod_has_domains (409).
  • The default pod cannot be deleted (default_pod, 409).
Deleting a pod does not delete inboxes or domains; it only removes an empty container. To offboard a customer, clean up their pod-scoped resources first (you can address the pod by your own clientId):
# 1. List the pod's inboxes
curl "https://api.openmail.sh/v1/inboxes?podId=meridian" \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"

# 2. Delete each inbox (deleting an inbox also removes its messages and threads)
curl -X DELETE https://api.openmail.sh/v1/inboxes/INBOX_ID \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"

# 3. Reassign or delete any pod-scoped domains (dashboard: widen to account-wide,
#    move to another pod, or delete the domain once it has no inboxes)

# 4. Now the pod is empty and can be deleted
curl -X DELETE https://api.openmail.sh/v1/pods/meridian \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"

Managing pods in the console

You can also manage pods without code. In the console, open Pods to see every pod, create new ones, and open a pod to view its inboxes and pod-scoped domains. The default pod is labeled with a Default badge.

Give your agent the pods API

Paste this into Cursor, Claude, or any coding agent to give it the full pods API in one shot:
OpenMail Pods — multi-tenant isolation. REST API, bearer auth with an account API key.
Base URL: https://api.openmail.sh
Auth header: Authorization: Bearer <OPENMAIL_API_KEY>

A pod is an isolated container for inboxes (one per tenant/customer/agent).
Every account has one auto-created default pod; inboxes with no pod land there.
Address any pod by its id OR by your own clientId.

Pods:
- GET    /v1/pods                 list pods (default pod first); ?limit&offset
- POST   /v1/pods                 body: { clientId?, name? } -> 201 pod
- GET    /v1/pods/{idOrClientId}  fetch one pod
- PATCH  /v1/pods/{idOrClientId}  body: { clientId?, name? }
- DELETE /v1/pods/{idOrClientId}  must be empty and not the default pod
    409 pod_not_empty   -> delete its inboxes first
    409 pod_has_domains -> reassign pod-scoped domains first
    409 default_pod     -> the default pod cannot be deleted

Inboxes (scoped to a pod):
- POST /v1/inboxes        body: { podId?, mailboxName?, displayName? }
    podId accepts a pod id or clientId; omit to use the default pod
    400 invalid_pod -> podId did not match a pod in your account
- GET  /v1/inboxes?podId=<idOrClientId>   list only that pod's inboxes
- every inbox object includes its podId

Notes:
- Inboxes can't move between pods; choose the pod at creation time.
- API keys are account-wide (no pod-scoped keys); pods are organizational isolation, not network isolation.

Frequently asked questions

No. Pods are optional. Every account has a default pod, so if you only manage email for yourself you can create inboxes directly and ignore pods entirely. Reach for pods when you need to isolate inboxes per customer or tenant.
Yes. Pods provide organizational isolation, not network isolation. Inboxes in different pods are ordinary email addresses and can send to and receive from one another like any other mailbox.
No. An inbox’s pod is fixed at creation. To “move” an inbox, create a new one in the target pod and delete the old one.
There’s no enforced limit on the number of pods. Note that inboxes are still subject to your plan’s inbox limit across the whole account.
Not today. Account API keys can access every pod. If you need per-tenant access boundaries, enforce them in your own application layer for now.
Yes. Scope a domain to one pod and create inboxes on it only inside that pod — for example support@meridian.io in the Meridian Analytics pod and hello@cedarworks.com in the Cedar Works pod. You can also add account-wide domains that every pod shares.

API reference

See the API reference for full request and response details. Pod endpoints:
OperationEndpoint
List podsGET /v1/pods
Create podPOST /v1/pods
Get podGET /v1/pods/{id}
Update podPATCH /v1/pods/{id}
Delete podDELETE /v1/pods/{id}