Notifications API for alerts and signed webhooks
Publish an event once. Takelan delivers it to email, webhooks, Slack, Mattermost and PagerDuty, with signed webhooks and retries.
What it does
- The Notifications API is a fan-out for alerts. Your code publishes one event with a topic, such as "backup.failed". People and teams decide where it goes by creating channels and subscribing them to topics. Your app never has to know who is listening.
- It solves the alert-wiring mess. Without it, every app grows its own Slack code, its own webhook sender, its own retry loop and its own "who gets paged" list. Here you set up channels once and every app shares them.
- A channel can be email, a webhook, both, Slack, Mattermost or PagerDuty. Slack and Mattermost channels take an incoming-webhook URL. PagerDuty takes an Events API v2 routing key. A channel can be private to one user or shared across the tenant, and it can be muted for a while.
- Webhooks are signed. Each delivery carries an X-Signature-256 header, an HMAC-SHA256 of the exact body using your channel secret, plus X-Takelan-Event, X-Takelan-Delivery and X-Takelan-Attempt headers. Failed deliveries are retried with backoff, and you can retry one by hand. A "verify" call and a "test" call let you check a channel before an incident.
- Outbound calls are guarded against server-side request forgery. Webhook targets must be https and must not resolve to loopback, link-local or cloud-metadata addresses. If your receiver lives on a private network, an administrator can allow that host on an explicit list.
- Event publishing needs a service token with the publish scope, or an API key that can publish to its own tenant. Over the limit, you get a 429 with a Retry-After header. Exact numbers vary by environment, so none are quoted here.
- Affordable by design. Start free* inside platform limits. *Free within platform limits; usage beyond limits may be charged to maintain the platform. Connected ShadowCradle organizations can switch on Takelan SSO and these free* services with one switch, and ShadowCradle alerts can use the same channels. Airgap licences work without any Takelan connection.
See how it works
Publish once, fan out to channels
A signed webhook delivery
Example use cases
Page the on-call engineer
A critical event goes to a PagerDuty channel, while the same event posts a short message to a Slack channel for the wider team. The app publishes once.
Signed webhooks to your own systems
A developer points a webhook channel at an internal service. The receiver checks X-Signature-256 against the body before it trusts the call, and uses X-Takelan-Delivery to skip duplicates.
Let each person choose how to be told
One engineer wants email, another wants Mattermost. Each creates a private channel and subscribes it to the topics they care about. Admins can also create tenant-wide channels.
Self-hosted chat on a private network
An IT team runs Mattermost inside its network. A tenant admin lists the host once, so notifications can reach it without opening general access to internal addresses.
Prove an alert was sent
After an incident, the team reads the deliveries list to see which channel got what, what failed and what was retried, instead of guessing from chat history.
One-click unsubscribe links
Email deliveries can include a magic link so a recipient can change their own subscription from the message itself.
Try it
Create a Slack channel and subscribe it to a topic
curl -X POST https://app.takelan.com/api/v1/notify/channels \
-H "X-API-Key: $TAKELAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "ops-alerts",
"kind": "slack",
"webhook_url": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
"scope": "tenant"
}'
# Response (abridged, fictional)
# { "id": "5b1e...90", "name": "ops-alerts", "kind": "slack", "enabled": true }Then call POST /api/v1/notify/channels/{channel_id}/test to send a test message, and POST /api/v1/notify/subscriptions to attach topics. Tenant-scoped channels need an administrator.
Verify a signed webhook (receiver side, Python)
import hmac, hashlib
def is_valid(secret: bytes, body: bytes, header: str) -> bool:
expected = "sha256=" + hmac.new(secret, body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header)
# header = request.headers["X-Signature-256"]
# body = the raw request bytes, before any JSON parsingCompare against the raw bytes you received. Use X-Takelan-Delivery to ignore a delivery you have already handled.
Endpoints
POST /api/v1/notify/channelsCreate a channel: email, webhook, both, slack, mattermost or pagerduty.GET /api/v1/notify/channelsList channels.GET /api/v1/notify/channels/{channel_id}One channel.PATCH /api/v1/notify/channels/{channel_id}Rename, enable, disable or mute a channel, or change its target.DELETE /api/v1/notify/channels/{channel_id}Delete a channel.POST /api/v1/notify/channels/{channel_id}/rotate-secretRotate the webhook signing secret.POST /api/v1/notify/channels/{channel_id}/verifyVerify a channel can receive.POST /api/v1/notify/channels/{channel_id}/testSend a test notification.GET /api/v1/notify/topicsList topics you can subscribe to.POST /api/v1/notify/subscriptionsSubscribe a channel to a topic, with optional filters.GET /api/v1/notify/subscriptionsList subscriptions.PATCH /api/v1/notify/subscriptions/{sub_id}Change a subscription.DELETE /api/v1/notify/subscriptions/{sub_id}Remove a subscription.POST /api/v1/notify/eventsPublish an event (service token, or an API key for its own tenant). Returns 202.GET /api/v1/notify/events/{event_id}Delivery state of a published event.GET /api/v1/notify/deliveriesList deliveries and their outcome.POST /api/v1/notify/deliveries/{delivery_id}/retryRetry a failed delivery.POST /api/v1/notify/webhook-jobsHand over one ready-to-send signed webhook request (service callers). Returns 202.POST /api/v1/notify/webhook-jobs/{job_id}/retryReplay a dead webhook job.GET /api/v1/notify/private-hostsList allowed private-network hosts.POST /api/v1/notify/private-hostsAllow a private-network host (administrators; may be switched off by the platform).
MCP
Available as tools through /mcp/utils. Listing channels, topics, subscriptions and deliveries works with a read-only key. Creating or changing channels is a write, so it is off by default: it needs the tenant's writes switch and a key that is not read-only. Event publishing, webhook jobs and private-host rules are not exposed as tools, and secret-bearing routes are marked sensitive. About MCP
Common questions
how to send alerts to Slack from an API
Create a channel of kind "slack" with your Slack incoming-webhook URL, subscribe it to a topic, then publish events on that topic. Use the test endpoint first to confirm it works.
can I send notifications to PagerDuty, Mattermost and email at once
Yes. Make one channel per target, subscribe each to the same topic, and publish one event. Takelan fans it out. A single channel can also be "both" (email and webhook).
how do I verify a webhook signature HMAC SHA256
Each webhook delivery has an X-Signature-256 header in the form sha256=<hex>. Compute HMAC-SHA256 of the raw request body with your channel secret and compare in constant time. Rotate the secret any time with the rotate-secret endpoint.
what happens if my webhook endpoint is down
Failed deliveries are retried with backoff, and each try carries an X-Takelan-Attempt header. You can see every delivery in the deliveries list and retry one by hand. We do not publish a retry count or delivery-time guarantee here.
can a webhook call a server on my private network
Not by default. Targets must be https and cannot resolve to loopback, link-local or cloud-metadata addresses. A tenant admin can allow a private-range host on the private-hosts list, if the platform administrator permits it.
who can publish events to the notification service
A service token with the publish scope, or an API key publishing to its own tenant. Plain user logins cannot publish. Keys are limited to non-transactional topics.
is there an audit trail for notifications
Yes. Deliveries are listed with their state, and channel and private-host changes are recorded in an audit log.
is the notification API free
It is affordable by design: start free* within platform limits. *Free within platform limits; usage beyond limits may be charged to maintain the platform.
