Set up a webhook
Build a receiver for Cevoid webhooks, create a webhook destination for it and publish a Flow that sends events there.
A webhook needs three things: a receiver on your side, a destination in Cevoid that points at it, and a Flow whose action sends events to the destination.
Prerequisites
- You can open Settings → Flows in your Cevoid workspace.
- You have a public HTTPS URL for your receiver. Cevoid cannot reach
localhost; during development, expose your machine through a tunnel service.
Build the receiver
Your receiver accepts a POST, verifies the signature against the exact raw body, records the event and answers with a 2xx status within 10 seconds. Do slow work after you respond, for example in a job queue.
These receivers use the Standard Webhooks library (npm install standardwebhooks) to check the signature:
// app/webhooks/cevoid/route.ts
import { Webhook } from "standardwebhooks"
const webhook = new Webhook(process.env.CEVOID_WEBHOOK_SECRET ?? "")
export async function POST(request: Request) {
// The raw body: parsing and re-serializing JSON breaks the signature.
const body = await request.text()
try {
webhook.verify(body, Object.fromEntries(request.headers))
} catch {
return new Response("Invalid signature", { status: 401 })
}
const event = JSON.parse(body)
// Your own storage: skip an event ID you have already processed.
if (await alreadyProcessed(event.id)) return new Response(null, { status: 204 })
switch (event.type) {
case "order.fulfilled":
await queueFulfilledOrder(event.data.order)
break
}
return new Response(null, { status: 204 })
}import express from "express"
import { Webhook } from "standardwebhooks"
const app = express()
const webhook = new Webhook(process.env.CEVOID_WEBHOOK_SECRET)
// express.raw keeps the body as bytes for the signature check.
app.post("/webhooks/cevoid", express.raw({ type: "application/json" }), async (req, res) => {
const body = req.body.toString("utf8")
try {
webhook.verify(body, req.headers)
} catch {
return res.status(401).send("Invalid signature")
}
const event = JSON.parse(body)
// Your own storage: skip an event ID you have already processed.
if (await alreadyProcessed(event.id)) return res.sendStatus(204)
if (event.type === "order.fulfilled") await queueFulfilledOrder(event.data.order)
res.sendStatus(204)
})Answer a bad signature with 401: Cevoid stops retrying, and once your secret is fixed you can retry the delivery from Outbox. Other 4xx statuses stop the delivery for good; see How Cevoid reads your response.
Set up a webhook
- Go to Settings → Flows and choose Create flow.
- Choose Forward event → Webhook.
- Choose the trigger, such as Order fulfilled or Product review submitted. Its event is the
typeyour receiver gets. - Choose Create destination. To reuse a destination, choose it instead and go to step 7.
- Enter a name (up to 80 characters), your receiver's HTTPS URL and, if you like, a description (up to 500 characters), then choose Create destination. Result: the Flow opens in the editor and the signing secret is shown.
- Copy the signing secret, store it where your receiver reads it (for example
CEVOID_WEBHOOK_SECRET) and choose I saved the secret. Cevoid never shows it again. - Choose Publish flow. Result: from now on, each matching event is delivered to your receiver.
To send events from a Flow you already have, add an Action step, set Delivery target to Webhook and choose a destination in Webhook destination, or Create destination there. Preview payload on the step shows the data it sends.
Before you rely on it, test the webhook with a real signed event.
URL requirements
Cevoid checks the URL when you save the destination and again before every attempt:
- It must use HTTPS and resolve only to public addresses. Private, loopback and other reserved ranges are rejected, and so are host names such as
localhostand names ending in.local,.internal,.localhostor.home.arpa. - It must use a host name, not an IP address.
- It cannot contain credentials, a query string or a fragment.
- Ports 22, 23, 25, 110 and 143 are blocked.
Cevoid connects to the address it checked and does not follow redirects, so point the destination at the final URL.
Manage destinations
Destinations are listed under Webhook destinations in Settings → Integrations → Cevoid API. The menu of each destination has:
- Send test: a signed
cevoid.testevent. See Test a webhook. - View deliveries: the destination's deliveries in Outbox.
- Edit: the name, URL and description. A new URL applies to deliveries that have not made their first attempt yet; retries keep the URL of the first attempt.
- Rotate secret and Finish secret rotation: see Rotate the signing secret.
- Disable and Enable: Cevoid sends nothing to a disabled destination; its pending deliveries stop instead. A delivery that stopped between retries can be retried from Outbox once you enable the destination again.
- Archive: hides the destination for good. It is refused while any Flow, published or draft, still uses the destination.