Email for platforms
Sub-accounts give each of your users their own domains, reputation, quotas and suppressions.
If you run a platform whose users send email (a website builder, a CRM, a store builder), give each of those users a sub-account. A sub-account has its own:
- domains and sending reputation at the mail provider (its own SES tenant),
- reputation at coss.com: its bounces, complaints and blocked content pause it, not you,
- quotas you set on it,
- suppression list, and
- stats.
Your organization stays accountable for its sub-accounts. They are billed to you, your own reputation still counts everything they send, and if your organization is suspended, all of them stop.
Live sub-accounts need a plan with sub-accounts (Scale or Enterprise). Sandbox ones are free, so you can build your integration first. Sub-accounts send transactional email only.
Create a sub-account
Create one per user, and give it a uid (your own id for that user). Every call that takes a
sub-account accepts its id (sub_…) or its uid.
const { : } = await ...({
: "Acme Bakery",
: "user_8812",
: { : 5000 },
});Sub-accounts belong to the API key's environment. A coss_test_… key only sees sandbox ones, and a
coss_live_… key only sees production ones.
Send for a sub-account
Name the sub-account with subaccount:
await ..({
: "user_8812",
: "Acme Bakery <orders@acmebakery.com>",
: "customer@example.com",
: "Your order is ready",
: "<p>Come and pick it up.</p>",
});Over SMTP, use the X-Coss-Subaccount header. In a batch, each email can name
its own sub-account. The email's subaccount_id, and the subaccount_id in its webhook events, tell
you which user it was for.
Domains
A live sub-account sends from:
- its own domains. Add them with
subaccount. Only that sub-account can send from them, through its own sending reputation at the mail provider. If the provider pauses that reputation, only that sub-account stops (sending_paused). - domains you share with your sub-accounts. For users who don't have a domain of their own, share one of yours. They then send from it through your organization's sending reputation, and your dedicated IPs if you have them. Sub-accounts' own domains send from shared IPs.
// The user's own domain: publish its DNS records, like any domain.
const { : } = await ..({
: "acmebakery.com",
: "user_8812",
});
// Or let every sub-account send from one of your own domains.
await ..(, { : true });Nobody else can send from a sub-account's domain. Your own sends can't either: name the sub-account instead. A sub-account can have up to 10 domains, and up to 5 awaiting verification at once. They don't count toward your plan's domain limit. Sub-accounts' domains don't have custom tracking or receiving domains yet.
Quotas
Set a daily quota, a per-second quota, or both. A send over one is refused with 429
quota_exceeded, and your other sub-accounts go on sending. Your organization's own quotas apply
too. Change them with coss.email.subaccounts.update. null removes a quota.
Reputation
coss.com measures each sub-account's permanent bounce and complaint rates on its own. It uses your
organization's window and thresholds (see delivery). At the warning threshold
the sub-account's reputation becomes warning, and it clears once the rates recover. At the
suspension threshold, or when content screening blocks one of its emails, it
becomes paused: its live sends are refused with 403 subaccount_paused.
A pause is never lifted on its own. Once you've dealt with the cause, reinstate the sub-account. Its rates are then measured again from that moment.
const { } = await ...("user_8812");
if (?.. === "paused") {
await ...("user_8812");
}Subscribe a webhook endpoint to these events to hear about changes:
subaccount.reputation_warning, subaccount.reputation_recovered, subaccount.paused and
subaccount.reinstated. They are sent for live sub-accounts only.
Every new sub-account's first emails are always screened for spam and phishing, so a bad actor who signs up to your platform is caught early.
Suppressions
A sub-account's sends skip addresses on its own suppression list and on your environment's list.
Its permanent bounces, complaints and one-click unsubscribes go on its own list only, so one user's
bounces never block another's mail. Manage a sub-account's list by passing subaccount to the
suppression calls.
Stats and emails
coss.email.subaccounts.stats("user_8812") returns its recipients per day: sent, delivered, bounced,
complained, failed and suppressed, for up to the last 45 days. coss.email.list({ subaccount }) lists
its emails.
Disable or delete
status: "disabled" refuses a sub-account's sends until you set it back to active. Deleting a
sub-account refuses its sends at once. Its domains are then released and it is removed with its
suppression list. Its emails stay, with its id.