[{"data":1,"prerenderedAt":962},["ShallowReactive",2],{"doc:\u002Fv\u002F2026.3\u002Fbuild-with-ai\u002Fwebhooks-reference":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"section":10,"version":11,"lastUpdated":12,"body":13,"_type":956,"_id":957,"_source":958,"_file":959,"_stem":960,"_extension":961},"\u002Fv\u002F2026.3\u002Fbuild-with-ai\u002Fwebhooks-reference","build-with-ai",false,"","Webhooks reference","The 21 events Workspace369 sends to your URL, the signed request format, a Node.js signature check, retries, and the plan and permission rules for webhooks.","Build with AI","2026.3","2026-10-18",{"type":14,"children":15,"toc":945},"root",[16,24,29,36,137,150,162,167,172,563,576,582,587,681,686,698,742,748,760,770,775,786,791,797,832,838,868,874,903,909],{"type":17,"tag":18,"props":19,"children":20},"element","p",{},[21],{"type":22,"value":23},"text","A webhook tells your app when something happens in Workspace369, so you do not have to keep asking. When an event you chose occurs, Workspace369 sends a signed HTTPS POST to a URL you control. Your server checks the signature, does its work, and answers with a 2xx status.",{"type":17,"tag":18,"props":25,"children":26},{},[27],{"type":22,"value":28},"Webhooks are available on the Specialist plan and above, including Commander and Enterprise. You manage them in the app, not through an API.",{"type":17,"tag":30,"props":31,"children":33},"h2",{"id":32},"create-a-webhook",[34],{"type":22,"value":35},"Create a webhook",{"type":17,"tag":37,"props":38,"children":39},"ol",{},[40,61,72,93,105,117],{"type":17,"tag":41,"props":42,"children":43},"li",{},[44,46,52,54,59],{"type":22,"value":45},"Open ",{"type":17,"tag":47,"props":48,"children":49},"strong",{},[50],{"type":22,"value":51},"Settings",{"type":22,"value":53}," and choose ",{"type":17,"tag":47,"props":55,"children":56},{},[57],{"type":22,"value":58},"Webhooks",{"type":22,"value":60},".",{"type":17,"tag":41,"props":62,"children":63},{},[64,66,71],{"type":22,"value":65},"Choose ",{"type":17,"tag":47,"props":67,"children":68},{},[69],{"type":22,"value":70},"New webhook",{"type":22,"value":60},{"type":17,"tag":41,"props":73,"children":74},{},[75,77,82,84,91],{"type":22,"value":76},"Enter the ",{"type":17,"tag":47,"props":78,"children":79},{},[80],{"type":22,"value":81},"Endpoint URL",{"type":22,"value":83},". It must be an ",{"type":17,"tag":85,"props":86,"children":88},"code",{"className":87},[],[89],{"type":22,"value":90},"https:\u002F\u002F",{"type":22,"value":92}," address on the standard port, with no username or password, on a public host.",{"type":17,"tag":41,"props":94,"children":95},{},[96,98,103],{"type":22,"value":97},"Under ",{"type":17,"tag":47,"props":99,"children":100},{},[101],{"type":22,"value":102},"Events",{"type":22,"value":104},", select at least one event.",{"type":17,"tag":41,"props":106,"children":107},{},[108,110,115],{"type":22,"value":109},"Leave ",{"type":17,"tag":47,"props":111,"children":112},{},[113],{"type":22,"value":114},"Active",{"type":22,"value":116}," on, then save.",{"type":17,"tag":41,"props":118,"children":119},{},[120,122,127,129,135],{"type":22,"value":121},"Copy the ",{"type":17,"tag":47,"props":123,"children":124},{},[125],{"type":22,"value":126},"Signing secret",{"type":22,"value":128}," now. It starts with ",{"type":17,"tag":85,"props":130,"children":132},{"className":131},[],[133],{"type":22,"value":134},"whsec_",{"type":22,"value":136}," and is shown only once.",{"type":17,"tag":18,"props":138,"children":139},{},[140,142,148],{"type":22,"value":141},"Creating, changing, and rotating webhooks needs the Manage webhooks permission, which Managers and above have. To subscribe to a ",{"type":17,"tag":85,"props":143,"children":145},{"className":144},[],[146],{"type":22,"value":147},"lead.*",{"type":22,"value":149}," event you also need access to Requests, because those events carry the lead's contact details.",{"type":17,"tag":18,"props":151,"children":152},{},[153,155,160],{"type":22,"value":154},"To replace a secret, choose ",{"type":17,"tag":47,"props":156,"children":157},{},[158],{"type":22,"value":159},"Rotate secret",{"type":22,"value":161}," on the webhook. The new secret is shown once and the old one stops working. Deleting a webhook stops its events immediately.",{"type":17,"tag":30,"props":163,"children":165},{"id":164},"events",[166],{"type":22,"value":102},{"type":17,"tag":18,"props":168,"children":169},{},[170],{"type":22,"value":171},"Only these 21 events exist.",{"type":17,"tag":173,"props":174,"children":175},"table",{},[176,195],{"type":17,"tag":177,"props":178,"children":179},"thead",{},[180],{"type":17,"tag":181,"props":182,"children":183},"tr",{},[184,190],{"type":17,"tag":185,"props":186,"children":187},"th",{},[188],{"type":22,"value":189},"Event",{"type":17,"tag":185,"props":191,"children":192},{},[193],{"type":22,"value":194},"Sent when",{"type":17,"tag":196,"props":197,"children":198},"tbody",{},[199,217,234,251,268,285,302,319,336,359,376,393,410,427,444,461,478,495,512,529,546],{"type":17,"tag":181,"props":200,"children":201},{},[202,212],{"type":17,"tag":203,"props":204,"children":205},"td",{},[206],{"type":17,"tag":85,"props":207,"children":209},{"className":208},[],[210],{"type":22,"value":211},"time_entry.created",{"type":17,"tag":203,"props":213,"children":214},{},[215],{"type":22,"value":216},"A time entry is created.",{"type":17,"tag":181,"props":218,"children":219},{},[220,229],{"type":17,"tag":203,"props":221,"children":222},{},[223],{"type":17,"tag":85,"props":224,"children":226},{"className":225},[],[227],{"type":22,"value":228},"time_entry.updated",{"type":17,"tag":203,"props":230,"children":231},{},[232],{"type":22,"value":233},"A time entry is changed.",{"type":17,"tag":181,"props":235,"children":236},{},[237,246],{"type":17,"tag":203,"props":238,"children":239},{},[240],{"type":17,"tag":85,"props":241,"children":243},{"className":242},[],[244],{"type":22,"value":245},"time_entry.deleted",{"type":17,"tag":203,"props":247,"children":248},{},[249],{"type":22,"value":250},"A time entry is deleted.",{"type":17,"tag":181,"props":252,"children":253},{},[254,263],{"type":17,"tag":203,"props":255,"children":256},{},[257],{"type":17,"tag":85,"props":258,"children":260},{"className":259},[],[261],{"type":22,"value":262},"timesheet.submitted",{"type":17,"tag":203,"props":264,"children":265},{},[266],{"type":22,"value":267},"A timesheet is submitted for approval.",{"type":17,"tag":181,"props":269,"children":270},{},[271,280],{"type":17,"tag":203,"props":272,"children":273},{},[274],{"type":17,"tag":85,"props":275,"children":277},{"className":276},[],[278],{"type":22,"value":279},"timesheet.approved",{"type":17,"tag":203,"props":281,"children":282},{},[283],{"type":22,"value":284},"A timesheet is approved.",{"type":17,"tag":181,"props":286,"children":287},{},[288,297],{"type":17,"tag":203,"props":289,"children":290},{},[291],{"type":17,"tag":85,"props":292,"children":294},{"className":293},[],[295],{"type":22,"value":296},"timesheet.rejected",{"type":17,"tag":203,"props":298,"children":299},{},[300],{"type":22,"value":301},"A timesheet is rejected.",{"type":17,"tag":181,"props":303,"children":304},{},[305,314],{"type":17,"tag":203,"props":306,"children":307},{},[308],{"type":17,"tag":85,"props":309,"children":311},{"className":310},[],[312],{"type":22,"value":313},"invoice.created",{"type":17,"tag":203,"props":315,"children":316},{},[317],{"type":22,"value":318},"An invoice is created.",{"type":17,"tag":181,"props":320,"children":321},{},[322,331],{"type":17,"tag":203,"props":323,"children":324},{},[325],{"type":17,"tag":85,"props":326,"children":328},{"className":327},[],[329],{"type":22,"value":330},"invoice.paid",{"type":17,"tag":203,"props":332,"children":333},{},[334],{"type":22,"value":335},"An invoice moves into Paid. Partial payments and reversals do not send it.",{"type":17,"tag":181,"props":337,"children":338},{},[339,348],{"type":17,"tag":203,"props":340,"children":341},{},[342],{"type":17,"tag":85,"props":343,"children":345},{"className":344},[],[346],{"type":22,"value":347},"invoice.status_changed",{"type":17,"tag":203,"props":349,"children":350},{},[351,353,358],{"type":22,"value":352},"An invoice's status changes to any other status. A move into Paid sends this event first, then ",{"type":17,"tag":85,"props":354,"children":356},{"className":355},[],[357],{"type":22,"value":330},{"type":22,"value":60},{"type":17,"tag":181,"props":360,"children":361},{},[362,371],{"type":17,"tag":203,"props":363,"children":364},{},[365],{"type":17,"tag":85,"props":366,"children":368},{"className":367},[],[369],{"type":22,"value":370},"proposal.sent",{"type":17,"tag":203,"props":372,"children":373},{},[374],{"type":22,"value":375},"A proposal is sent.",{"type":17,"tag":181,"props":377,"children":378},{},[379,388],{"type":17,"tag":203,"props":380,"children":381},{},[382],{"type":17,"tag":85,"props":383,"children":385},{"className":384},[],[386],{"type":22,"value":387},"proposal.accepted",{"type":17,"tag":203,"props":389,"children":390},{},[391],{"type":22,"value":392},"A client accepts a proposal.",{"type":17,"tag":181,"props":394,"children":395},{},[396,405],{"type":17,"tag":203,"props":397,"children":398},{},[399],{"type":17,"tag":85,"props":400,"children":402},{"className":401},[],[403],{"type":22,"value":404},"proposal.declined",{"type":17,"tag":203,"props":406,"children":407},{},[408],{"type":22,"value":409},"A client declines a proposal.",{"type":17,"tag":181,"props":411,"children":412},{},[413,422],{"type":17,"tag":203,"props":414,"children":415},{},[416],{"type":17,"tag":85,"props":417,"children":419},{"className":418},[],[420],{"type":22,"value":421},"contract.sent",{"type":17,"tag":203,"props":423,"children":424},{},[425],{"type":22,"value":426},"A contract is sent for signature.",{"type":17,"tag":181,"props":428,"children":429},{},[430,439],{"type":17,"tag":203,"props":431,"children":432},{},[433],{"type":17,"tag":85,"props":434,"children":436},{"className":435},[],[437],{"type":22,"value":438},"contract.recipient_completed",{"type":17,"tag":203,"props":440,"children":441},{},[442],{"type":22,"value":443},"One recipient finishes signing.",{"type":17,"tag":181,"props":445,"children":446},{},[447,456],{"type":17,"tag":203,"props":448,"children":449},{},[450],{"type":17,"tag":85,"props":451,"children":453},{"className":452},[],[454],{"type":22,"value":455},"contract.completed",{"type":17,"tag":203,"props":457,"children":458},{},[459],{"type":22,"value":460},"Every recipient has signed.",{"type":17,"tag":181,"props":462,"children":463},{},[464,473],{"type":17,"tag":203,"props":465,"children":466},{},[467],{"type":17,"tag":85,"props":468,"children":470},{"className":469},[],[471],{"type":22,"value":472},"contract.declined",{"type":17,"tag":203,"props":474,"children":475},{},[476],{"type":22,"value":477},"A recipient declines.",{"type":17,"tag":181,"props":479,"children":480},{},[481,490],{"type":17,"tag":203,"props":482,"children":483},{},[484],{"type":17,"tag":85,"props":485,"children":487},{"className":486},[],[488],{"type":22,"value":489},"contract.voided",{"type":17,"tag":203,"props":491,"children":492},{},[493],{"type":22,"value":494},"A contract is voided.",{"type":17,"tag":181,"props":496,"children":497},{},[498,507],{"type":17,"tag":203,"props":499,"children":500},{},[501],{"type":17,"tag":85,"props":502,"children":504},{"className":503},[],[505],{"type":22,"value":506},"contract.expired",{"type":17,"tag":203,"props":508,"children":509},{},[510],{"type":22,"value":511},"A contract expires before it is signed.",{"type":17,"tag":181,"props":513,"children":514},{},[515,524],{"type":17,"tag":203,"props":516,"children":517},{},[518],{"type":17,"tag":85,"props":519,"children":521},{"className":520},[],[522],{"type":22,"value":523},"lead.created",{"type":17,"tag":203,"props":525,"children":526},{},[527],{"type":22,"value":528},"A new request arrives.",{"type":17,"tag":181,"props":530,"children":531},{},[532,541],{"type":17,"tag":203,"props":533,"children":534},{},[535],{"type":17,"tag":85,"props":536,"children":538},{"className":537},[],[539],{"type":22,"value":540},"lead.converted",{"type":17,"tag":203,"props":542,"children":543},{},[544],{"type":22,"value":545},"A request is converted to a client.",{"type":17,"tag":181,"props":547,"children":548},{},[549,558],{"type":17,"tag":203,"props":550,"children":551},{},[552],{"type":17,"tag":85,"props":553,"children":555},{"className":554},[],[556],{"type":22,"value":557},"lead.archived",{"type":17,"tag":203,"props":559,"children":560},{},[561],{"type":22,"value":562},"A request is archived.",{"type":17,"tag":18,"props":564,"children":565},{},[566,568,575],{"type":22,"value":567},"There are no events for clients, projects, tasks, or bookings. To read those, call Workspace369 with a tool. See ",{"type":17,"tag":569,"props":570,"children":572},"a",{"href":571},"\u002Fv\u002F2026.3\u002Fbuild-with-ai\u002Fcall-workspace369-from-your-app-over-https\u002F",[573],{"type":22,"value":574},"Call Workspace369 from your app over HTTPS",{"type":22,"value":60},{"type":17,"tag":30,"props":577,"children":579},{"id":578},"what-you-receive",[580],{"type":22,"value":581},"What you receive",{"type":17,"tag":18,"props":583,"children":584},{},[585],{"type":22,"value":586},"Each delivery is a POST with a JSON body and these headers:",{"type":17,"tag":173,"props":588,"children":589},{},[590,606],{"type":17,"tag":177,"props":591,"children":592},{},[593],{"type":17,"tag":181,"props":594,"children":595},{},[596,601],{"type":17,"tag":185,"props":597,"children":598},{},[599],{"type":22,"value":600},"Header",{"type":17,"tag":185,"props":602,"children":603},{},[604],{"type":22,"value":605},"Value",{"type":17,"tag":196,"props":607,"children":608},{},[609,630,647,664],{"type":17,"tag":181,"props":610,"children":611},{},[612,621],{"type":17,"tag":203,"props":613,"children":614},{},[615],{"type":17,"tag":85,"props":616,"children":618},{"className":617},[],[619],{"type":22,"value":620},"Content-Type",{"type":17,"tag":203,"props":622,"children":623},{},[624],{"type":17,"tag":85,"props":625,"children":627},{"className":626},[],[628],{"type":22,"value":629},"application\u002Fjson",{"type":17,"tag":181,"props":631,"children":632},{},[633,642],{"type":17,"tag":203,"props":634,"children":635},{},[636],{"type":17,"tag":85,"props":637,"children":639},{"className":638},[],[640],{"type":22,"value":641},"X-Webhook-Id",{"type":17,"tag":203,"props":643,"children":644},{},[645],{"type":22,"value":646},"A unique id for this event. The same event always has the same id, including on retries.",{"type":17,"tag":181,"props":648,"children":649},{},[650,659],{"type":17,"tag":203,"props":651,"children":652},{},[653],{"type":17,"tag":85,"props":654,"children":656},{"className":655},[],[657],{"type":22,"value":658},"X-Webhook-Timestamp",{"type":17,"tag":203,"props":660,"children":661},{},[662],{"type":22,"value":663},"The send time in milliseconds since 1970, as text.",{"type":17,"tag":181,"props":665,"children":666},{},[667,676],{"type":17,"tag":203,"props":668,"children":669},{},[670],{"type":17,"tag":85,"props":671,"children":673},{"className":672},[],[674],{"type":22,"value":675},"X-Webhook-Signature",{"type":17,"tag":203,"props":677,"children":678},{},[679],{"type":22,"value":680},"A hex HMAC-SHA256 signature.",{"type":17,"tag":18,"props":682,"children":683},{},[684],{"type":22,"value":685},"The body is an envelope:",{"type":17,"tag":687,"props":688,"children":693},"pre",{"className":689,"code":691,"language":692,"meta":7},[690],"language-json","{\n  \"webhook_id\": \"...\",\n  \"event_type\": \"invoice.paid\",\n  \"entity_id\": \"...\",\n  \"workspace_id\": \"...\",\n  \"subscription_id\": \"...\",\n  \"data\": { }\n}\n","json",[694],{"type":17,"tag":85,"props":695,"children":696},{"__ignoreMap":7},[697],{"type":22,"value":691},{"type":17,"tag":699,"props":700,"children":701},"ul",{},[702,720,731],{"type":17,"tag":41,"props":703,"children":704},{},[705,711,713,718],{"type":17,"tag":85,"props":706,"children":708},{"className":707},[],[709],{"type":22,"value":710},"webhook_id",{"type":22,"value":712}," is the same value as the ",{"type":17,"tag":85,"props":714,"children":716},{"className":715},[],[717],{"type":22,"value":641},{"type":22,"value":719}," header.",{"type":17,"tag":41,"props":721,"children":722},{},[723,729],{"type":17,"tag":85,"props":724,"children":726},{"className":725},[],[727],{"type":22,"value":728},"entity_id",{"type":22,"value":730}," is the id of the invoice, proposal, contract, time entry, timesheet, or request the event is about.",{"type":17,"tag":41,"props":732,"children":733},{},[734,740],{"type":17,"tag":85,"props":735,"children":737},{"className":736},[],[738],{"type":22,"value":739},"data",{"type":22,"value":741}," holds the details of the record. Log a few real deliveries and build against what you see. Treat any field you do not recognize as optional.",{"type":17,"tag":30,"props":743,"children":745},{"id":744},"verify-the-signature",[746],{"type":22,"value":747},"Verify the signature",{"type":17,"tag":18,"props":749,"children":750},{},[751,753,758],{"type":22,"value":752},"The signature is the HMAC-SHA256, in hex, of the raw request body followed immediately by the timestamp header text, using the whole signing secret as the key. The key includes the ",{"type":17,"tag":85,"props":754,"children":756},{"className":755},[],[757],{"type":22,"value":134},{"type":22,"value":759}," prefix.",{"type":17,"tag":687,"props":761,"children":765},{"className":762,"code":764,"language":22,"meta":7},[763],"language-text","signature = hex( HMAC_SHA256( secret, rawBody + timestamp ) )\n",[766],{"type":17,"tag":85,"props":767,"children":768},{"__ignoreMap":7},[769],{"type":22,"value":764},{"type":17,"tag":18,"props":771,"children":772},{},[773],{"type":22,"value":774},"Compute it over the raw bytes you received. Do not parse the JSON and write it back out, because that can change the text and break the match.",{"type":17,"tag":687,"props":776,"children":781},{"className":777,"code":779,"language":780,"meta":7},[778],"language-js","import crypto from \"node:crypto\";\nimport express from \"express\";\n\nconst SECRET = process.env.WORKSPACE369_WEBHOOK_SECRET; \u002F\u002F whsec_...\nconst MAX_AGE_MS = 5 * 60 * 1000;\nconst seen = new Set(); \u002F\u002F use a database or cache in production\n\nconst app = express();\n\napp.post(\"\u002Fwebhooks\u002Fworkspace369\", express.raw({ type: \"application\u002Fjson\" }), (req, res) => {\n  const rawBody = req.body.toString(\"utf8\");\n  const timestamp = req.get(\"X-Webhook-Timestamp\") ?? \"\";\n  const signature = req.get(\"X-Webhook-Signature\") ?? \"\";\n  const id = req.get(\"X-Webhook-Id\") ?? \"\";\n\n  const expected = crypto\n    .createHmac(\"sha256\", SECRET)\n    .update(rawBody + timestamp)\n    .digest(\"hex\");\n\n  const a = Buffer.from(expected, \"utf8\");\n  const b = Buffer.from(signature, \"utf8\");\n  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {\n    return res.status(401).send(\"bad signature\");\n  }\n\n  if (Math.abs(Date.now() - Number(timestamp)) > MAX_AGE_MS) {\n    return res.status(401).send(\"stale\");\n  }\n\n  if (seen.has(id)) return res.status(200).send(\"duplicate\");\n  seen.add(id);\n\n  const event = JSON.parse(rawBody);\n  \u002F\u002F Hand off the work quickly, then answer.\n  console.log(event.event_type, event.entity_id);\n  res.status(200).send(\"ok\");\n});\n\napp.listen(3000);\n","js",[782],{"type":17,"tag":85,"props":783,"children":784},{"__ignoreMap":7},[785],{"type":22,"value":779},{"type":17,"tag":18,"props":787,"children":788},{},[789],{"type":22,"value":790},"The timestamp check is a safeguard we recommend. Workspace369 signs a fresh timestamp on every attempt, so a retry passes the check.",{"type":17,"tag":30,"props":792,"children":794},{"id":793},"retries-and-failures",[795],{"type":22,"value":796},"Retries and failures",{"type":17,"tag":699,"props":798,"children":799},{},[800,805,817,822,827],{"type":17,"tag":41,"props":801,"children":802},{},[803],{"type":22,"value":804},"Answer with any 2xx status within 10 seconds. Anything else counts as a failure, including a timeout, a redirect, or a connection error. Redirects are not followed.",{"type":17,"tag":41,"props":806,"children":807},{},[808,810,815],{"type":22,"value":809},"After a failure, Workspace369 retries up to 5 more times, with longer waits between attempts. The same ",{"type":17,"tag":85,"props":811,"children":813},{"className":812},[],[814],{"type":22,"value":641},{"type":22,"value":816}," is used each time, so use it to ignore duplicates.",{"type":17,"tag":41,"props":818,"children":819},{},[820],{"type":22,"value":821},"After the last attempt fails, the event is marked as dead and is not sent again.",{"type":17,"tag":41,"props":823,"children":824},{},[825],{"type":22,"value":826},"If the address can never be reached safely, such as a host that resolves to a private network address, Workspace369 switches the webhook off and notifies the workspace once.",{"type":17,"tag":41,"props":828,"children":829},{},[830],{"type":22,"value":831},"Events can arrive more than once and not always in order. Make your handler safe to run twice.",{"type":17,"tag":30,"props":833,"children":835},{"id":834},"plans-and-permissions",[836],{"type":22,"value":837},"Plans and permissions",{"type":17,"tag":699,"props":839,"children":840},{},[841,851],{"type":17,"tag":41,"props":842,"children":843},{},[844,849],{"type":17,"tag":47,"props":845,"children":846},{},[847],{"type":22,"value":848},"Specialist and above.",{"type":22,"value":850}," If a workspace moves to a lower plan, its webhooks stop sending and are kept as they were. They send again after an upgrade.",{"type":17,"tag":41,"props":852,"children":853},{},[854,859,861,866],{"type":17,"tag":47,"props":855,"children":856},{},[857],{"type":22,"value":858},"Lead events.",{"type":22,"value":860}," ",{"type":17,"tag":85,"props":862,"children":864},{"className":863},[],[865],{"type":22,"value":147},{"type":22,"value":867}," events are sent only while the person who created the webhook still belongs to the workspace and can view Requests. If they lose that access, those events are skipped.",{"type":17,"tag":30,"props":869,"children":871},{"id":870},"check-your-webhook",[872],{"type":22,"value":873},"Check your webhook",{"type":17,"tag":37,"props":875,"children":876},{},[877,888,893,898],{"type":17,"tag":41,"props":878,"children":879},{},[880,882,887],{"type":22,"value":881},"Create a test webhook that points at your server and subscribes to one event, such as ",{"type":17,"tag":85,"props":883,"children":885},{"className":884},[],[886],{"type":22,"value":370},{"type":22,"value":60},{"type":17,"tag":41,"props":889,"children":890},{},[891],{"type":22,"value":892},"Trigger the event in Workspace369.",{"type":17,"tag":41,"props":894,"children":895},{},[896],{"type":22,"value":897},"Confirm your server received the request, the signature check passed, and it answered with 200.",{"type":17,"tag":41,"props":899,"children":900},{},[901],{"type":22,"value":902},"Send the same event again from your tool and confirm the duplicate is ignored.",{"type":17,"tag":30,"props":904,"children":906},{"id":905},"if-webhooks-do-not-arrive",[907],{"type":22,"value":908},"If webhooks do not arrive",{"type":17,"tag":699,"props":910,"children":911},{},[912,917,928,940],{"type":17,"tag":41,"props":913,"children":914},{},[915],{"type":22,"value":916},"Confirm the workspace is on Specialist or above.",{"type":17,"tag":41,"props":918,"children":919},{},[920,922,926],{"type":22,"value":921},"Confirm the webhook is ",{"type":17,"tag":47,"props":923,"children":924},{},[925],{"type":22,"value":114},{"type":22,"value":927}," and lists the event.",{"type":17,"tag":41,"props":929,"children":930},{},[931,933,938],{"type":22,"value":932},"Confirm the URL is ",{"type":17,"tag":85,"props":934,"children":936},{"className":935},[],[937],{"type":22,"value":90},{"type":22,"value":939}," on the standard port and that your server answers within 10 seconds.",{"type":17,"tag":41,"props":941,"children":942},{},[943],{"type":22,"value":944},"A signature mismatch is almost always caused by parsing the body before computing the signature, or by using a rotated-out secret.",{"title":7,"searchDepth":946,"depth":946,"links":947},2,[948,949,950,951,952,953,954,955],{"id":32,"depth":946,"text":35},{"id":164,"depth":946,"text":102},{"id":578,"depth":946,"text":581},{"id":744,"depth":946,"text":747},{"id":793,"depth":946,"text":796},{"id":834,"depth":946,"text":837},{"id":870,"depth":946,"text":873},{"id":905,"depth":946,"text":908},"markdown","content:v:2026.3:build-with-ai:webhooks-reference.md","content","v\u002F2026.3\u002Fbuild-with-ai\u002Fwebhooks-reference.md","v\u002F2026.3\u002Fbuild-with-ai\u002Fwebhooks-reference","md",1792310456186]