Stream triggers
Fire signed webhooks on paid submissions and goal milestones for any tool that accepts them.
Stream triggers send a signed HTTP POST to a URL you choose the moment something happens on your stream, so lighting controllers, automation tools, or your own server can react in real time. Each payload includes the amount paid or the goal that was crossed, so effects can scale with it.
Set up
- Open Settings, pick the Developer tab, and find Stream triggers.
- Paste your webhook URL. It must be a public https URL.
- Turn on the events you want and save. Nero generates a signing secret for you.
- Press Send test event and confirm your tool received it.
Events
submission.paid payload
{
"event": "submission.paid",
"data": {
"sessionId": "9f6a1c1e-2b64-4e5a-9a94-1f2d3c4b5a69",
"tier": "superskip",
"amountPaid": 25,
"submitterName": "drake",
"submissionName": "family matters",
"timestamp": 1767200000000
}
}goal.reached payload
{
"event": "goal.reached",
"data": {
"sessionId": "9f6a1c1e-2b64-4e5a-9a94-1f2d3c4b5a69",
"metric": "earnings",
"threshold": 300,
"level": 3,
"currentValue": 305.5,
"timestamp": 1767200000000
}
}Test events from the settings page use the same shapes with an extra top-level "test": true field, so you can filter them out of real effects.
Verify the signature
Every request carries two headers. X-Nero-Event is the event type. X-Nero-Signature is sha256= followed by the hex HMAC-SHA256 of the raw request body, keyed with the signing secret from your settings page. Compute the same HMAC over the exact bytes you received and compare.
const crypto = require("crypto");
function verifyNeroSignature(rawBody, header, secret) {
// header looks like "sha256=6c2e..."; rawBody must be the exact
// unparsed request body string, not re-serialized JSON.
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
return (
header.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected))
);
}Delivery behavior
- Respond with any 2xx status within 5 seconds. Slower responses count as failures.
- Failed deliveries retry up to 3 more times with growing delays (about 3s, 6s, then 12s).
- Goal totals are evaluated a few seconds after each submission, so a goal.reached event can arrive shortly after the submission.paid event that crossed the threshold.
- Redirects are not followed, and the URL must resolve to a public address.
- Deliveries are best-effort and never block payments or the queue. The settings page shows your last delivery's outcome for debugging.
Need help?
Email support@nero.fan and include your webhook URL and the last delivery status shown in settings.