Turn on catch-all and every workspace, customer, or tenant gets its own address at your domain — acct+customer@yourapp.com — with nothing to pre-create. Route specific patterns to specific endpoints, or let everything else fall through to one webhook.
Catch-all makes every address at the domain deliverable instantly — a new signup's address works the moment they use it, not after an admin step.
Match a specific address, a wildcard like invoices+*@yourapp.com, or the whole domain, and send each to its own webhook, an inbox agent, or a forward address.
Every message arrives as the same signed JSON regardless of which tenant it's for — read to.address to know which workspace it belongs to.
Tenants share the domain's quota and account — no per-mailbox fee to charge back, no second vendor as you add customers.
Point MX at MailKite (or a managed subdomain) and flip catch-all on — every address at the domain becomes deliverable.
Create a route matching invoices+*@yourapp.com (or similar) to send that slice to a dedicated endpoint or inbox agent.
The webhook payload's to field tells you exactly which tenant address received the mail — key your lookup off it.
One wildcard route covers every tenant address — the tenant is just a field in the payload.
Dashboard → Routes → [ + New route ]
Match acct+*@yourapp.com
Action Webhook
Destination https://yourapp.com/hooks/tenant-mail
Click [ Save ]Route every acct+*@yourapp.com address to my webhook at
https://yourapp.com/hooks/tenant-mailimport { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
// Every acct+<tenant>@yourapp.com address routes to one webhook;
// nothing to provision per customer.
await mk.createRoute({
match: "acct+*@yourapp.com",
action: "webhook",
destination: "https://yourapp.com/hooks/tenant-mail",
});
// In the handler: evt.to[0].address is "acct+acme@yourapp.com" —
// split on "+" to resolve the tenant.import os
from mailkite import MailKite
mk = MailKite(os.environ["MAILKITE_API_KEY"])
# Every acct+<tenant>@yourapp.com address routes to one webhook;
# nothing to provision per customer.
mk.createRoute({
"match": "acct+*@yourapp.com",
"action": "webhook",
"destination": "https://yourapp.com/hooks/tenant-mail",
})
# In the handler: evt["to"][0]["address"] is "acct+acme@yourapp.com" —
# split on "+" to resolve the tenant.<?php
$mk = new \MailKite\Client(getenv('MAILKITE_API_KEY'));
// Every acct+<tenant>@yourapp.com address routes to one webhook;
// nothing to provision per customer.
$mk->createRoute([
'match' => 'acct+*@yourapp.com',
'action' => 'webhook',
'destination' => 'https://yourapp.com/hooks/tenant-mail',
]);
// In the handler: $evt['to'][0]['address'] is "acct+acme@yourapp.com" —
// split on "+" to resolve the tenant.MailKite mk = new MailKite(System.getenv("MAILKITE_API_KEY"));
// Every acct+<tenant>@yourapp.com address routes to one webhook;
// nothing to provision per customer.
mk.createRoute(Map.of(
"match", "acct+*@yourapp.com",
"action", "webhook",
"destination", "https://yourapp.com/hooks/tenant-mail"
));
// In the handler: the payload's to[0].address is "acct+acme@yourapp.com" —
// split on "+" to resolve the tenant.mk := mailkite.New(os.Getenv("MAILKITE_API_KEY"))
// Every acct+<tenant>@yourapp.com address routes to one webhook;
// nothing to provision per customer.
_, err := mk.CreateRoute(map[string]any{
"match": "acct+*@yourapp.com",
"action": "webhook",
"destination": "https://yourapp.com/hooks/tenant-mail",
})
// In the handler: the payload's to[0].address is "acct+acme@yourapp.com" —
// split on "+" to resolve the tenant.require "mailkite"
mk = Mailkite::Client.new(ENV["MAILKITE_API_KEY"])
# Every acct+<tenant>@yourapp.com address routes to one webhook;
# nothing to provision per customer.
mk.createRoute(
"match" => "acct+*@yourapp.com",
"action" => "webhook",
"destination" => "https://yourapp.com/hooks/tenant-mail"
)
# In the handler: evt["to"][0]["address"] is "acct+acme@yourapp.com" —
# split on "+" to resolve the tenant.# Every acct+<tenant>@yourapp.com address routes to one webhook;
# nothing to provision per customer.
curl https://api.mailkite.dev/api/routes \
-H "Authorization: Bearer $MAILKITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"match": "acct+*@yourapp.com",
"action": "webhook",
"destination": "https://yourapp.com/hooks/tenant-mail"
}'
# In the handler: to[0].address is "acct+acme@yourapp.com" —
# split on "+" to resolve the tenant. No — enable catch-all on the domain and any address works the instant a customer uses it. There's nothing to pre-provision as you onboard new tenants.
Yes. Routes match a specific address or a wildcard pattern and send that slice to its own webhook, forward address, or inbox agent, while everything else falls through to the domain's default.
The parsed webhook payload includes the exact to.address that received it — key your lookup off that (or the +tag if you use plus-addressing).
Start free on unlimited domains — no credit card. Or browse the other solutions.