Macroplane price alerts for any thesis or basket can now go to your own HTTPS endpoints as signed Standard Webhooks, with retries and delivery logs powered by the Webhook Relay Outbound Gateway.
More Macroplane supply-chain guides · Baskets · Investment theses · Macro trends
Macroplane can now send price alerts for any thesis or basket to your own systems as signed webhooks. When a ticker you track moves past your threshold, Macroplane POSTs a JSON event to your HTTPS endpoint. That endpoint can be a trading bot, a Slack or Discord relay, an n8n or Zapier flow, or an internal dashboard. Every delivery is signed with the Standard Webhooks scheme, retried automatically if your server is down, and recorded in a delivery log you can inspect from Settings.
This post covers setup, the exact payload, how to verify signatures in Node.js and Python, and why we moved delivery onto the Webhook Relay Outbound Gateway instead of running it ourselves.
Price alerts already watch the companies in a thesis or basket and notify you when one moves more than a set percentage in a day. Until now the only reliable channel was email. Webhooks give you a second channel, and you can enable it alongside email or on its own.
Setup takes about two minutes:
Each endpoint has a few controls of its own. You can pause it, and events are skipped until you resume (a stale price move is rarely worth replaying). You can rotate its secret. And you can open its delivery log, which lists each attempt with status, HTTP response code, retry count, duration and the first part of your server's response body. When a deploy on your side breaks the receiver, the log is the first place to look.
The request body is the event JSON itself, with no envelope. Here is an illustrative alert for the Memory Supercycle basket at a 5% threshold, with Micron ($MU) and Sandisk ($SNDK) both up more than 5% on the day:
Field notes:
The Settings test event is a different event type (webhook.test) with a much smaller body: {"message": "Test event from Macroplane", "sent_at": "…"}. Check for tickers before treating a body as an alert.
We treat this shape as a contract. New fields may be added, but existing ones will not be renamed or removed.
Every delivery carries three headers:
The signature is a base64 HMAC-SHA256 of {webhook-id}.{webhook-timestamp}.{raw body}. The key is your secret with the whsec_ prefix removed and the rest base64-decoded. For a broader explainer, see what a webhook signature is.
Three details are easy to get wrong:
The verification uses only hmac, hashlib and base64; Flask is there just to receive the request. Because the scheme is Standard Webhooks, any library that implements the spec will also verify these deliveries.
Respond with a 2xx quickly and do any slow work, such as placing orders or calling other APIs, after you've responded. A slow or failing response counts as a failed delivery and will be retried. Since retries are possible, deduplicate on webhook-id before doing anything with side effects.
Macroplane had webhook alerts before this release, but they were minimal. Our servers POSTed the JSON to a URL saved on the alert, with a 10-second timeout and three attempts spaced a few hundred milliseconds apart. There was no signature, so a receiver could not tell our request from anyone else's. If your server was down for the minute it took to deploy, the alert was gone. If it was down for a day, we kept trying it on every alert anyway. Neither of us could see what had happened.
A production webhook system needs more than that:
We could have built all of this, but a queue, a retry scheduler, a signing service and a log store would be a lot of infrastructure for what is a secondary feature of an investment research product. So we moved delivery onto the Webhook Relay Outbound Gateway. The integration looks like this:
A side effect is that Macroplane no longer stores webhook URLs or signing secrets in its own database. HTTPS URLs saved on older alerts are imported as endpoints on your account, so existing integrations keep working. They also start receiving signatures, and you can begin verifying them whenever you're ready. Plain http:// URLs can't be imported. If you had one, add an HTTPS endpoint under Settings → Webhooks.
The tradeoff is a dependency: if the gateway is unavailable, publishing fails. The alert then counts as not delivered and is retried on the next sweep, not silently dropped. If you're building webhooks into your own product and weighing the same decision, the outbound docs cover the consumer, endpoint and message model, and the gateway is available on every Webhook Relay plan, including Free.
Two today: price_alert.triggered, which fires when tickers on a thesis or basket cross your threshold, and webhook.test, which is sent from Settings to check an endpoint. An endpoint subscribed to all events will also receive any event types we add later.
Yes, through a small relay: a serverless function, an n8n or Zapier webhook trigger, or your own bot. It verifies the signature, formats tickers into a message, and posts it to the channel's incoming webhook. Slack and Discord expect their own message formats, so pointing the endpoint directly at a Slack or Discord URL won't render correctly.
The delivery is retried automatically with backoff, up to 8 attempts over 48 hours, and every attempt shows up in the endpoint's delivery log. If you would rather not receive alerts at all during planned downtime, pause the endpoint: events are skipped while it is paused and the alerts that fire after you resume are delivered as usual.
Store each webhook-id you've processed and skip repeats. On our side, real alerts are published with deterministic IDs, so a retried sweep doesn't create a second message.
No. Price alerts report observed market moves. What your systems do with them is up to you, and anything that trades automatically should be tested with test: true previews and safeguards of your own before it handles real orders.
Two today: price_alert.triggered, which fires when tickers on a thesis or basket cross your threshold, and webhook.test, which is sent from Settings to check an endpoint. An endpoint subscribed to all events will also receive any event types we add later.
Yes, through a small relay: a serverless function, an n8n or Zapier webhook trigger, or your own bot. It verifies the signature, formats tickers into a message, and posts it to the channel's incoming webhook. Slack and Discord expect their own message formats, so pointing the endpoint directly at a Slack or Discord URL won't render correctly.
The delivery is retried automatically with backoff, up to 8 attempts over 48 hours, and every attempt shows up in the endpoint's delivery log. If you would rather not receive alerts at all during planned downtime, pause the endpoint: events are skipped while it is paused and the alerts that fire after you resume are delivered as usual.
Store each webhook-id you've processed and skip repeats. On our side, real alerts are published with deterministic IDs, so a retried sweep doesn't create a second message.
No. Price alerts report observed market moves. What your systems do with them is up to you, and anything that trades automatically should be tested with test: true previews and safeguards of your own before it handles real orders.