Webhook setup and debugging in SGEN
Webhooks let SGEN push events to external services in near-real-time. A form submission can land in your CRM the moment it happens. An order can trigger fulfillment in a warehouse system. A published blog post can drop a card into your team's Slack channel. Webhooks are how SGEN talks to the rest of your stack without you writing polling code or running a sync script every five minutes.
This walkthrough covers the full setup — creating a webhook in the SGEN admin, what the payload looks like, how to verify on the receiving side that the message came from SGEN, what happens when delivery fails, and the debugging checklist that resolves most issues.
A webhook delivers user data to a third-party service. Anything sent over a webhook leaves SGEN and lands in whatever system you point it at. Before you send form submissions, order details, or customer information anywhere, confirm the receiving service is secure and that you have the right to send the data there.
What is this for?
A webhook is a small message SGEN sends to an address you control, the instant something happens on your site. The receiving service can then do whatever it likes — write the data to a database, fire a notification, kick off a workflow.
Use a webhook when:
- An external service needs to know about SGEN events as they happen (not on a polling schedule).
- You want to glue SGEN to a tool that does not have a built-in SGEN integration (Zapier, Make, n8n, your own internal app).
- You need an audit trail of events outside SGEN — every webhook attempt is logged on the receiver side as well.
The SGEN mechanism is straightforward: you tell SGEN which events to listen for and which address to deliver them to, SGEN signs each message so you can confirm its origin, and SGEN retries automatically if the first attempt does not land.
Good use cases
Form submission to CRM. A visitor fills the contact form on yoursite.com. SGEN fires a form.submission webhook to your CRM, which creates a lead with the visitor's name, email, message, and the page they submitted from. The CRM does the rest — assignment, follow-up sequence, sales pipeline.
Order placed to fulfillment. A customer buys the Digital Guide from the Your Store shop. SGEN fires an order.placed webhook to your warehouse system. The warehouse generates a packing slip and prints a shipping label without anyone in the office touching a screen.
Post published to team Slack. A team member publishes a new blog post on the Your Store site. SGEN fires a post.published webhook to a small relay that drops a Slack card into the #marketing channel — title, excerpt, link, author. The team sees it without anyone copying and pasting.
Subscription event to billing. A subscriber upgrades their subscription tier. SGEN fires a subscription.updated webhook to your billing service, which adjusts the plan and queues a confirmation email — no manual reconciliation on the next billing cycle.
What NOT to use this for
- Large file transfers. A webhook carries the event metadata, not the assets. If a webhook fires when media is uploaded, the message contains the file's URL and metadata — not the bytes. Pull the file separately if you need it on the receiver side.
- Polling-style "give me everything since timestamp X" queries. A webhook is a push, not a pull. If you need to fetch a list of records, use the SGEN admin export tools or the Migration backup feature.
- Synchronous user-facing flows. A webhook is fire-and-forget from SGEN's side. If the receiving service is down for an hour, the user does not see an error — they see a successful form submission and your retry queue handles the redelivery. Do not use a webhook as a real-time validation step in the user's flow.
- Transmitting secrets in the payload. Never include passwords, payment card numbers, or session tokens in webhook payloads. The signing secret protects authenticity, not contents — assume any service that holds the receiving address could read what arrives.
How this connects to other features
- View and manage orders — the source of
order.placed,order.paid,order.shipped, andorder.refundedevents. Any state change in the Orders panel fires a corresponding webhook if you have one configured. - Manage form submissions — the source of
form.submissionevents. Every form on your site fires a webhook the moment a submission lands. - Push notifications setup — push events (
push.sent,push.delivered,push.clicked) flow through the same webhook channel as form and order events. - Configure site identity — the site name and email in your identity settings are the values SGEN uses in the webhook payload's
siteblock. Update identity settings first if you renamed your site recently.
Before you start
- You have admin access to the SGEN site that will send the webhooks. Editor and Contributor roles cannot reach the Integrations panel.
- You have a receiving address ready — a URL on a server you control that can accept incoming messages. Common patterns: a small relay you built, a Zapier/Make/n8n "Webhook" trigger, an internal app's webhook intake route.
- You have a way to read the receiving side's logs. Without logs on the receiver, you cannot tell whether SGEN reached you, what it sent, or why your code rejected it.
- You have decided how the receiver will verify that incoming requests came from SGEN — most teams hash the message body with a shared secret and compare it to the signature header SGEN attaches. See "Verify the signature" below.
- The receiving address is reachable from the public internet. SGEN cannot deliver to addresses that sit behind a corporate firewall, a VPN, or a localhost tunnel that is not exposed.
Where to go
You move between two places during setup:
| Panel | Path |
|---|---|
| Webhooks list | your admin area |
| New webhook form | your admin area |
| Per-webhook log | your admin area |
The receiving side is whatever tool or app holds the address you wired in — Slack, your CRM, Zapier, your internal service. SGEN does not see anything on the receiver side; you watch its logs in its own interface.
Setup steps
The five steps below run in order. The first one is "decide what you want to send" — skipping it leads to a webhook that fires too often or on the wrong event.
1. Decide what event you want to send
Open the New webhook form to see the current list of events you can subscribe to. The common ones:
| Event | Fires when | Typical receiver |
|---|---|---|
form.submission | Any form on the site is submitted | CRM, email service, helpdesk |
order.placed | A shop checkout completes successfully | Fulfillment, accounting, Slack |
order.paid | A pending order is marked paid | Fulfillment, finance |
order.shipped | An order is marked shipped | Customer-notification service |
order.refunded | A refund is issued | Finance, support |
post.published | A blog post moves from draft to published | Team Slack, social-scheduling tool |
subscription.updated | A subscription tier or plan changes | Billing service |
push.delivered | A push notification is delivered | Engagement analytics |
Pick one event per webhook. If you need three events to land in the same receiver, create three webhooks — it makes the per-event logs and retry behavior easier to read later.
2. Create the webhook
Open Integrations → Webhooks and click New webhook.
Click Save webhook. SGEN generates the signing secret and displays it once at the top of the next screen — copy it now and paste it into the receiving side's environment or secrets store.
3. Wire signature verification on the receiver
Every message SGEN delivers includes a header named X-SGEN-Signature. The header holds a fingerprint of the message body, computed using your signing secret. Your code on the receiver side computes the same fingerprint and compares — if they match, the message came from SGEN; if not, reject it.
Three quick samples in common languages. Pick the one closest to your stack — the logic is identical, only the syntax differs.
code-output-panelExpected ',' or '}' after property value in JSON at position 746 (line 1 column 747)
Whatever stack you use, three rules hold:
- Read the raw body before any parsing. Parsing changes the bytes; the fingerprint will not match if you hash the parsed version.
- Use a constant-time comparator (
crypto.timingSafeEqual,hash_equals,hmac.compare_digest). Never==orstrcmpon the fingerprint. - Reject and stop on mismatch. Do not log the contents of an unverified message; do not process it; just reject.
4. Send a test event and verify delivery
Open the webhook's detail screen and click Send test event. SGEN sends a small message with the event name webhook.test and a dummy payload to your receiving address.
On the receiver side, check the logs. You should see:
- One incoming request from SGEN's address range.
- The
X-SGEN-Signatureheader present. - Your verification code passed.
- Your handler processed the test event and returned success.
If the receiver did not log anything, SGEN could not reach it — see "What to do if it does not work" below.
If the receiver logged the request but your verification rejected it, the secret on the receiver side does not match the one in SGEN — copy the secret from the SGEN admin again and update the receiver's environment.
5. Switch the webhook to Active
Once the test event delivers cleanly, return to the webhook's settings, switch Active to on, and save. Real events now flow to your receiver.
Open the Webhooks list to confirm — the new webhook appears with a green Active badge and a small counter showing recent deliveries.
What the payload looks like
Every webhook carries a small message with the same outer shape:
The outer wrapper (event, timestamp, site) is identical across every event. The data block changes shape per event — an order.placed carries customer, line items, and total; a post.published carries title, slug, excerpt, and author. The webhook detail screen shows the exact shape for each event you subscribe to.
How retries work
If the receiver does not respond with success within five seconds, SGEN treats the delivery as failed and queues a retry. The retry schedule:
| Attempt | When |
|---|---|
| 1 | Immediately after the event fires |
| 2 | About 30 seconds after Attempt 1 |
| 3 | About 2 minutes after Attempt 2 |
| 4 | About 10 minutes after Attempt 3 |
| 5 | About 1 hour after Attempt 4 |
| — | After Attempt 5 fails, SGEN marks the delivery permanently failed and stops |
Five attempts spread across roughly seventy minutes. If your receiver is briefly down, SGEN will reach it once it comes back. If it stays down past the retry window, the event is logged as failed and the message is dropped — SGEN does not store unlimited failed deliveries.
The retry behavior makes one design choice on your side mandatory: make your receiver handler idempotent. Because SGEN may retry the same event, your receiver may see the same submission_id or order_id more than once. Check whether you have already processed it before acting again — otherwise a brief network blip turns into a duplicate lead, a duplicate order ship, or a duplicate Slack message.
What success looks like
A healthy webhook produces all of the following:
- The webhook appears in the Webhooks list with the green Active badge.
- The Last 24h counter shows steady delivery counts that match the volume of real events on the site.
- The per-webhook log shows recent attempts with a success response and short response time (under 1 second is typical, under 5 seconds is the hard ceiling).
- Your receiver's own logs show the message arriving, the signature verifying, and the handler processing it without errors.
- No retried or failed entries persist longer than the receiver's known maintenance windows.
The green line should be steady and proportional to your real event volume. The yellow line should be small (a few retries per day is normal — networks blink). The red line should be flat at zero for weeks at a time — any failed delivery deserves a look at the receiver-side log.
Examples in context
The three scenarios below show how teams at Your Store wire webhooks for different parts of their stack.
Example 1: Form submission to the team's CRM.
The Your Store office manager wants every contact form submission to land in the CRM automatically so the sales pipeline tracks every enquiry. They set up a form.submission webhook pointing at crm.yoursite.com/incoming/sgen.
Within ten minutes of switching the webhook Active, a site visitor submits the contact form asking whether the Digital Guide ships to the UK. SGEN fires the webhook within a second. The CRM logs the incoming message, verifies the signature, parses the fields, creates a lead with the visitor's name, email, message, and source page, and assigns it to the manager's queue. The lead arrives within seconds.
The Webhooks log for this webhook over the first day:
Example 2: Order placed routed to fulfillment plus Slack.
The fulfillment lead at Your Store needs the warehouse system to receive every paid order immediately, and the office Slack channel to see a heads-up so the team knows order volume in real time.
Two webhooks are created for the same order.placed event — one pointing at warehouse.yoursite.com/orders and one pointing at the team's Slack incoming address. When a customer buys a Canvas Tote Bag and a Sticker Pack, both webhooks fire from SGEN within the same second. The warehouse picks the order; the Slack channel sees "New order #2026-0184 — Customer — $35.99 — 2 items" land instantly.
The Slack relay routes the message through a small payload-shaping app before dropping it in the channel:
The team appreciates that the two paths are decoupled — if Slack is down, fulfillment still gets the order; if the warehouse system is down, Slack still sees the order land. Each webhook has its own retry timer and its own log.
Example 3: Receiver outage triggers retry exhaustion — and what happens next.
The marketing lead runs the marketing site for Your Store. The post.published webhook points at a small relay that drops a card into the team's Slack. The relay's hosting provider has a planned maintenance window on a Saturday morning and the relay is down for two hours.
A new blog post is published during the maintenance window. SGEN attempts delivery five times across about seventy minutes — every attempt fails because the relay is unreachable. After the fifth attempt, the delivery is marked permanently failed and a single red entry appears in the webhook log.
When the maintenance ends, no automatic re-delivery happens. The missing Slack card is noticed the next Monday. Opening the webhook log reveals the failed entry, and manually republishing the blog post (toggle to draft, save, toggle to published, save) fires a fresh post.published event that delivers cleanly.
The lesson: receiver-side maintenance windows should be communicated to whoever owns the SGEN events. Either pause the webhook in the SGEN admin before the maintenance starts (and re-activate after, then manually fire any events that happened during the window), or accept that some events will need manual replay.
What to do if it does not work
- Test event never arrives at the receiver. Check the webhook log in SGEN. If SGEN tried and got an error, the log shows the receiver's response. If SGEN tried and got a network error, the receiving address is not reachable from the public internet — confirm the address is correct, that the receiving server is running, and that no firewall is dropping the request.
- Test event arrives but signature verification fails. Two common causes: the secret on the receiver does not match the one in SGEN (copy it from SGEN again and update the receiver's environment), or your code reads the parsed message body rather than the raw bytes (parsing rewrites the bytes, so the fingerprint will not match — switch to reading the raw body before parsing).
- The same event arrives multiple times. This is the at-least-once delivery guarantee. Make your receiver idempotent — check whether you have already processed this
submission_idororder_idbefore acting again.
- Webhook fires but the related data is not yet ready. Eventual consistency is real. If you receive a
post.publishedevent but the post's images are still being uploaded, your receiver may see incomplete state. Either query the SGEN site to confirm full state before acting, or design the receiver to accept partial information.
- Delivery is slow or intermittent. Check the response time in the webhook log. If the receiver consistently takes longer than three seconds, the receiver is doing too much work synchronously — return success immediately and queue the actual processing on the receiver side, so SGEN's five-second window is not the bottleneck.
- Webhook log shows nothing at all but you know an event happened. Confirm the webhook is Active (not Paused) and that the event you expected matches the event you subscribed to —
order.placedfires only when a checkout completes, not when an order is added manually in the admin.
Tips for a smooth rollout
Send to a staging receiver first. Wire the new webhook to a staging address (a simple log-only receiver) for the first day. Watch the payloads land, confirm the field shape matches what your production receiver expects, then switch the address to production.
Name each webhook for its event plus its receiver. Six months from now, "webhook 3" tells you nothing. "Form submissions to Your Store CRM" tells you the event, the destination, and roughly why it exists.
Document where the secret lives. Write down which environment variable on which server holds the signing secret. If the only person who knows is on holiday when the receiver breaks, you will spend an hour finding it before you can debug anything.
Treat the receiver log as the source of truth, not the SGEN log. The SGEN log shows what SGEN sent and what response it got. The receiver log shows whether the message reached your handler, whether the signature verified, and what your code did with it. Most debugging answers are on the receiver side.
Set up a monitor for permanently failed deliveries. Five retries across seventy minutes is generous, but it is not infinite. If a delivery fails permanently, you should know within the hour — not the next time you happen to scroll past the webhook log. Most teams add a Slack alert that fires whenever the webhook log shows a permanently failed entry.
Pause before you delete. If a webhook is misbehaving, pause it rather than delete it. Pausing keeps the configuration and the log so you can debug; deleting wipes the signing secret and the log together, and a new webhook with the same name does not inherit the old delivery history.
Related reading
- View and manage orders — full reference for the Orders panel, which sources
order.placed,order.paid,order.shipped, andorder.refundedevents. - Manage form submissions — full reference for the Forms panel, which sources
form.submissionevents. - Set up push notifications — push events flow through the same webhook channel; the push panel reference covers per-event semantics.
- Configure site identity — the site identity values appear in every webhook payload's
siteblock.
