Skip to main content
When a monitor fires, Tako posts one request to every notification channel listed on that monitor. This page describes that request: its headers, its body, how to verify the signature, and how Tako retries a delivery that fails. Tako follows the Standard Webhooks specification, so a library that verifies Standard Webhooks signatures verifies these.

Headers

The request body

A channel whose kind is webhook receives JSON in this shape:
monitor carries id, name, type, and parameters, which is the stored parameter object rather than the input you sent to Create a monitor. A type that resolves a subject stores the resolved value, so a monitor you created with a ticker carries a trading_item_id. firing carries id, occurrence_key, occurred_at, and trigger:
  • occurrence_key identifies the occurrence. Tako records one firing per key per monitor, so a source that reposts the same occurrence doesn’t fire twice.
  • occurred_at is when the occurrence happened in the data. created_at is when Tako recorded it. The gap between them is however long the source took to report.
  • trigger says what woke the monitor. push, meaning new data arrived, is the only value Tako sends today.
Verify the signature before you trust the body. Anyone who learns your channel’s URL can post to it. The signature is the only thing that proves a request came from Tako.

Verify the signature

Tako signs the concatenation of the delivery id, the timestamp, and the raw request body, joined with periods:
The key is the base64-decoded part of your channel’s secret after the whsec_ prefix. The signature is v1, followed by the base64 HMAC-SHA256 digest. Sign the bytes you received, not a re-serialized object. Tako sends compact JSON with no spaces after separators, and any reformatting breaks the signature.
Compare the signatures in constant time, and reject a webhook-timestamp far from the current time so an attacker can’t replay an old delivery.

How Tako retries

Tako allows 10 seconds for a response, and doesn’t follow redirects. A delivery gets 6 attempts: the first one, then retries after 1 minute, 5 minutes, 15 minutes, 1 hour, and 2 hours 45 minutes. Tako stops retrying a delivery more than 4 hours 30 minutes old, even when attempts remain. Respond 2xx as soon as you’ve stored the delivery, and do the slow work afterwards. A receiver that works for longer than 10 seconds gets retried, and receives the firing again. After 2 consecutive failed deliveries, Tako pauses the channel and sets its status_reason to delivery_failures. Monitors that post to a paused channel keep evaluating and recording firings, and those firings reach no one. Fix the destination, then resume the channel, which clears the consecutive-failure count. To see how each delivery went, call List a monitor’s firings and read deliveries.

Payload fields by monitor type

payload is a flat object of strings, numbers, booleans, and nulls. The fields depend on the monitor’s type.
The fields a type sends are its contract. Tako can add a field, which your receiver should ignore, and removing one is a breaking change. While monitors is experimental, these shapes can change without a deprecation window.

Slack workflow bodies

A channel whose kind is slack_workflow receives a flat body of strings instead, because a Slack Workflow Builder trigger rejects nested values:
This shape carries no payload, so a receiver that needs the values that caused the firing needs a webhook channel. Tako signs and retries both kinds the same way.

What Tako accepts as a URL

Create a notification channel rejects a url that:
  • Doesn’t use https.
  • Uses a port other than 443 or 8443.
  • Embeds credentials, as in https://user:pass@example.com/hook.
  • Has a host that doesn’t resolve.
  • Has a host that resolves to a loopback, link-local, multicast, private, reserved, or shared address.
Tako normalizes the URL it stores: it lowercases the host, drops the fragment, and gives a bare host a trailing slash. Read url in the response to see what Tako posts to.