{"name":"Example: Webhook to Contact Upsert","note":"Example workflow on fictional data. Review and configure before running; no client data or credentials are included.","active":false,"nodes":[{"id":"webhook-contact-upsert-0","name":"Booking webhook","type":"n8n-nodes-base.webhook","typeVersion":2,"position":[0,120],"parameters":{"httpMethod":"POST","path":"example-contact-upsert","responseMode":"onReceived","options":{}}},{"id":"webhook-contact-upsert-1","name":"Dedupe event","type":"n8n-nodes-base.code","typeVersion":2,"position":[220,120],"parameters":{"jsCode":"const seen = $getWorkflowStaticData('global'); seen.ids ??= {}; const event = $json.body ?? $json; if (!event.eventId || seen.ids[event.eventId]) return []; seen.ids[event.eventId] = Date.now(); return [{ json: event }];"}},{"id":"webhook-contact-upsert-2","name":"Upsert contact","type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[440,120],"parameters":{"method":"POST","url":"https://example.invalid/crm/contact-upsert","sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({email: $json.email, name: $json.name, eventId: $json.eventId}) }}","options":{"timeout":10000}},"onError":"continueRegularOutput"},{"id":"webhook-contact-upsert-3","name":"Request failed?","type":"n8n-nodes-base.if","typeVersion":2,"position":[660,120],"parameters":{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"condition","leftValue":"={{ Boolean($json.error) }}","rightValue":true,"operator":{"type":"boolean","operation":"true","singleValue":true}}],"combinator":"and"},"options":{}}},{"id":"webhook-contact-upsert-4","name":"Notify owner","type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[880,40],"parameters":{"method":"POST","url":"https://example.invalid/alerts","sendBody":true,"specifyBody":"json","jsonBody":"={{ JSON.stringify({subject: \"Contact upsert needs review\", error: $json.error}) }}","options":{"timeout":10000}},"onError":"continueRegularOutput"},{"id":"webhook-contact-upsert-5","name":"Record success","type":"n8n-nodes-base.code","typeVersion":2,"position":[880,240],"parameters":{"jsCode":"return [{json:{status:\"contact-upserted\",response:$json}}];"}}],"connections":{"Booking webhook":{"main":[[{"node":"Dedupe event","type":"main","index":0}]]},"Dedupe event":{"main":[[{"node":"Upsert contact","type":"main","index":0}]]},"Upsert contact":{"main":[[{"node":"Request failed?","type":"main","index":0}]]},"Request failed?":{"main":[[{"node":"Notify owner","type":"main","index":0}],[{"node":"Record success","type":"main","index":0}]]}},"settings":{"executionOrder":"v1"},"pinData":{},"tags":[],"meta":{"trigger":"A booking webhook receives a contact event.","systems":["n8n","GoHighLevel contact API","Owner notification webhook"],"beforeRunning":["Replace the contact and notification endpoints and configure credentials.","Match incoming fields and the eventId dedupe key to your source contract.","Replace sample static dedupe with durable storage and test the failure branch."],"example":true,"slug":"webhook-contact-upsert","notes":["Dedupe key: the incoming eventId, not the customer’s name.","Upsert: the receiving CRM matches on email in this fictional contract.","Retry: none automatically; failed requests go to a person for review.","Error branch: an HTTP error is carried into the explicit failure check.","Alert: notify the owner; sample static dedupe needs durable storage in production."],"description":"Hand-authored example on fictional data. Not an export from a client system. Replace illustrative endpoints and add credentials before use."}}