Event Routing
API Alerts 2.0 is in closed beta. This page describes the full 2.0 product. Current beta status →
This page is the technical reference. For the conceptual overview, see event routing.
Overview
Event routing controls where your events are delivered beyond push notifications. You create routers with glob patterns that match event names, and attach destinations that deliver to external services.
Routers
A router matches events by name and forwards them to destinations. Create routers in the dashboard under the Routers page.
Glob patterns
Each router has a glob pattern that matches against the event field of incoming events. The grammar is Unix fnmatch - the same style used by shell globs, .gitignore, and GitHub Actions path filters.
| Pattern | Matches | Doesn’t match |
|---|---|---|
* | Everything | (nothing) |
user.purchase | user.purchase only | user.signup |
user.* | user.purchase, user.signup, user.account.deleted | app.error |
*.failed | payment.failed, payment.subscription.failed | payment.success |
*.error.* | app.error.crash, db.error.timeout, cdn.error.503 | error |
ci.*.publish | ci.sdk.publish, ci.mobile.android.publish | ci.publish |
*deploy* | ci.deploy.success, predeploy-check | ci.build.success |
Deploy * | Deploy Complete, Deploy Failed | Deploy, Deployed |
Grammar
The rules are deliberately small:
*matches any sequence of characters, including zero characters. This includes dots and spaces, soci.*matchesci.deployandci.sdk.publish.pythonalike, andUser *matchesUser Signup.- Everything else is literal.
- Matching is case-sensitive.
That’s it. There’s no **, no character classes, no regex. Patterns without a * are exact-match only.
Events without an event field. Routing operates on the event field, so events sent without one don’t match any pattern - not even *. They still get delivered as push notifications (push is channel-based, not router-driven), so a workspace’s team members still get notified. They just don’t fan out to non-push destinations like email or Slack until the event includes an event field to match on.
The takeaway: if you want an event to reach destinations beyond push, include an event field on it. Bare {"message": "..."} events are valid and trigger push; routing kicks in once event is set.
One quirk worth knowing: because * matches zero or more characters, User * Action will also match User Action (two spaces between the words). Almost never a real concern with normal event names, but useful to know when debugging an unexpected match.
Common patterns
A handful of recipes for typical routing needs:
| Goal | Pattern | Example matches |
|---|---|---|
| Route everything in a namespace | ci.* | ci.deploy.success, ci.sdk.publish.python |
| Catch any failure across the platform | *.failed | payment.failed, auth.signup.failed |
| Catch a cross-cutting concern by segment | *.error.* | app.error.crash, db.error.timeout |
| Match by trailing action across sources | *.publish | ci.sdk.publish, package.npm.publish |
| Match free-form event names with a prefix | Deploy * | Deploy Complete, Deploy Failed |
| Loose substring search | *payment* | payment.failed, stripe.payment.created |
A single event can match multiple patterns. When it does, every matching router fires and their destinations all receive it. See Overlapping patterns.
Naming conventions
Use a domain.action pattern for event names:
user.purchase
user.signup
deploy.success
deploy.failure
app.error.crash
payment.refund
This makes glob patterns intuitive. user.* catches all user events, deploy.* catches all deployment events.
Overlapping patterns
If multiple routers match the same event, all of them fire. The dashboard warns you when a new router’s pattern overlaps with existing ones.
Destinations
A destination is a router’s connection to an integration. It configures how the event is formatted and delivered.
Supported destinations
| Destination | Configuration |
|---|---|
| Recipients, subject template, body sections | |
| SMS / WhatsApp | Recipients, message template |
| Slack | Channel, Block Kit layout (header, text, fields, buttons) |
| Webhooks | JSON payload template, custom headers |
| Zapier | Automatic, managed by Zapier |
Template variables
All destination templates support the {{variable}} syntax. Variables are replaced with event data at delivery time.
See the Template Variables reference for the full list.
Status
Each destination has a status:
- Ready. Fully configured, will deliver on matching events
- Needs Setup. Missing required configuration (e.g. no Slack channel selected)
Destinations with “Needs Setup” status are skipped during delivery.
Delivery pipeline
When an event is submitted:
- Push notifications fire immediately for all members of the event’s channel
- Routers are checked. Each router’s glob pattern is tested against the event name
- Destinations on matching routers are collected
- Templates are rendered with the event data
- Delivery tasks are dispatched in parallel to each integration
Each delivery is tracked with a status (sent, failed, skipped) and duration.
Default router
Every workspace starts with a default * router that matches all events. It comes with a push notification destination pre-configured. Add more destinations to start routing events to email, Slack, or webhooks.
Push notifications
Push notifications are not router-driven. They fire implicitly for every event, delivered to all members assigned to the event’s channel. This is separate from the router pipeline. You don’t need to configure push as a destination.