Alerts don't need another channel. They need an owner
Digestron is a webhook-native operational inbox. POST an event, get a ticket someone owns — with a status, an assignee and an audit trail. One endpoint is the entire integration.
import { DigestronClient, blocks } from "@digestron/sdk"
const client = new DigestronClient({
apiKey: process.env.DIGESTRON_API_KEY!,
baseUrl: "https://inbox.acme.com", // your Digestron instance
})
const { id, jobId } = await client.send({
channelId: "fraud-alerts",
// optional — a repeat send updates the same ticket
idempotencyKey: "CLM-9821",
callbackUrl: "https://acme.com/hooks/digestron",
// routing only, never rendered
metadata: {
severity: "critical",
user_segment: "premium",
},
blocks: [
blocks.header("Card testing detected"),
blocks.section("5 declined authorizations in 90 seconds."),
blocks.fields({ Card: "•••• 4412", Attempts: "5" }),
],
})
// 202 Accepted — the ticket renders on the queue, so a slow
// render never blocks the path the alert came in on.Card testing detected
5 declined authorizations in 90 seconds.
- Card
- •••• 4412
- Attempts
- 5
Same BIN range as this morning. Blocking at the gateway, keeping this open until the retry window closes.
Confirmed — filed upstream with the issuer.
- message.createdvia webhook · CLM-982114:02
- message.updatedassignee → D. Whitfield14:09
- message.updatedNEW → IN_PROGRESS14:09
Four fields, one permanent contract
- blocks
- You control what the human sees. Block Kit compatible, so the payload you already render into Slack works here unchanged.
- metadata
- Never rendered. Key/value pairs reserved for routing, priority and assignment — the ops analyst never sees your internal flags.
- idempotencyKey
- Send the same event twice and it updates one ticket instead of creating two. Comments and assignment history survive the update.
- callbackUrl
- When a ticket reaches a terminal status we POST back, retried three times, with every attempt readable over the API.
Two teams, one inbox
The same ticket is a delivery receipt on one side of the webhook and a piece of work on the other. Neither side has to hold the other's tools.
Engineering
The side that emits the event.
- One endpoint is the whole integrationA bearer key and a JSON body. The SDK is optional — zero runtime dependencies, anywhere fetch runs, typed so a payload that drifts from the server schema fails your build.
- The payload you already produceBlock Kit objects render unchanged, so the alert you format for Slack needs no second formatter.
- Retries cannot double-fileAn idempotency key makes a redelivered event update the ticket it already created, comments and assignment intact.
- The loop closes back in your systemA terminal status POSTs to your callback, retried three times, with every attempt readable over the API.
- Nothing new on your critical pathIngest answers 202 and renders on a queue, and keys are per workspace, so the alert path neither waits on the inbox nor shares a credential with anything else.
Operations
The side that has to do something about it.
- A queue, not a channelEvery event arrives as a ticket with a status, an assignee and a priority — work you can pick up rather than a message that scrolls away.
- Transitions are enforced, not suggestedNothing reaches RESOLVED without having been worked, and any terminal state can be reopened when an alert turns out to be live again.
- The discussion sits on the alertThreaded comments live with the ticket, so the reasoning behind a decision is still there the next time the same alert fires.
- An answer to who changed thisEvery move is timestamped in an immutable activity log, and roles decide who can move what.
- None of the internal noiseSeverity flags, customer segments and routing hints stay in metadata and never reach the screen.
Statuses that mean something
- NEW
- IN_PROGRESS
- RESOLVED
- REJECTED
- ARCHIVED
Transitions are enforced, not suggested. Nothing reaches RESOLVED without having been worked, every terminal state can be reopened because a closed alert that turns out to be live again is routine, and ARCHIVED is the one-way exit. Every move is timestamped and logged.
Or skip the SDK entirely
The SDK is a convenience over one HTTP call. This is the same send, by hand: POST /webhooks with an Authorization: Bearer header and a JSON body.
{
"channelId": "fraud-alerts",
"idempotencyKey": "CLM-9821",
"callbackUrl": "https://acme.com/hooks/digestron",
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "Card testing detected" }
},
{
"type": "section",
"text": { "type": "mrkdwn", "text": "5 declined authorizations in 90 seconds." }
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*Card*\n•••• 4412" },
{ "type": "mrkdwn", "text": "*Attempts*\n5" }
]
}
],
"metadata": [
{ "key": "severity", "value": "critical" },
{ "key": "user_segment", "value": "premium" }
]
}Anything that can make an HTTP request can file a ticket — curl, a Lambda, a cron job, a language with no Digestron package at all. The call answers 202 with the accepted webhook and the job that renders it, so a slow render never blocks the path your alert came in on.
Why none of your existing tools do this
On-call tools are built around outages and page engineers at 3am. Support desks are built around customers writing in. Issue trackers still need a human to type the ticket. Chaining a webhook through an automation platform into one of them is plumbing, not a product.
Digestron sits in the layer none of them own: the human triage step between a system event and the tool where the work actually gets done.
Block Kit, unchanged
blocks is Slack Block Kit compatible. If you already render alerts into a Slack channel, you already have the payload — point it somewhere that keeps score. Slack's block reference is the payload reference: the objects it documents are the objects this accepts.
The ticket at the top of this page leaves two fields out: severity and user_segment were in the send but never reach the screen. Metadata is for routing, not for reading.
Where it is today
- spring 2026spring 2026
Ingest, end to end
shippedOne authenticated endpoint that accepts a Block Kit payload, queues it and renders it into a ticket without the caller waiting on the render.
webhook ingest · block rendering · per-workspace API keys
- spring 2026spring 2026
A queue someone works
shippedThe part that makes it an inbox rather than a log: enforced transitions, an owner and a priority per ticket, the discussion attached to it, and a record of every move.
the ticket lifecycle · assignment and priority · threaded comments · an immutable activity log · role-based access · volume and unassigned-aging analytics
- summer 2026summer 2026
The loop closes
shippedA repeat send updates the ticket it already created instead of filing a second one, and a terminal status reports back to the system that raised the alert.
idempotent rematerialization · terminal-status callbacks · delivery log
- fall 2026fall 2026
Rules that route
in progressMetadata keys discovered from the traffic you actually send, multi-condition rules over them, and actions that set a priority, assign an owner or move a ticket to another channel before a human sees it.
key auto-discovery · rule builder · rule actions
- winter 2027winter 2027
Rules you can audit
in progressA rule that quietly matches nothing is worse than no rule, so each one carries a match log and a health indicator that says so out loud.
match log · rule health
Self-hostable. A hosted version is not live yet.