[{"data":1,"prerenderedAt":666},["ShallowReactive",2],{"bootstrap":3,"blog-a-comprehensive-guide-to-commerce-layer-webhooks":277},{"navigation":4,"globalConfig":196,"forms":218},{"headerSections":5,"headerFooterLinks":67,"footer":76,"legalLinks":153,"socialLinks":176},[6,39,44,50,57,62],{"hasSubMenu":7,"title":8,"links":9,"columns":38},true,"Product",[10,20,26,32],{"showTag":11,"_modelApiKey":12,"text":13,"subtitle":14,"icon":15,"isExternal":11,"link":16,"openForm":11},false,"navigation_link","Universal checkout","Sell anywhere","globe-simple",{"_modelApiKey":17,"slug":18,"title":19},"page","universal-checkout","Universal Checkout",{"showTag":11,"_modelApiKey":12,"text":21,"subtitle":22,"icon":23,"isExternal":11,"link":24,"openForm":11},"Distributed OMS","Manage orders","package",{"_modelApiKey":17,"slug":25,"title":21},"distributed-oms",{"showTag":11,"_modelApiKey":12,"text":27,"subtitle":28,"icon":29,"isExternal":11,"link":30,"openForm":11},"Promotion engine","Automated discounts","seal-percent",{"_modelApiKey":17,"slug":31,"title":27},"promotion-engine",{"showTag":11,"_modelApiKey":12,"text":33,"subtitle":34,"icon":35,"isExternal":11,"link":36,"openForm":11},"POS system","Operate stores","devices",{"_modelApiKey":17,"slug":37,"title":33},"pos-system",2,{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":40,"isExternal":11,"link":41,"openForm":11,"title":40},"Pricing",{"_modelApiKey":42,"slug":43},"pricing_page","pricing",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":45,"isExternal":11,"link":46,"openForm":11,"title":45},"Customers",{"_modelApiKey":47,"slug":48,"title":49},"customer_landing_page","customers","Customers page",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":51,"isExternal":11,"link":52,"openForm":11,"form":54,"title":51},"Partners",{"_modelApiKey":17,"slug":53,"title":51},"partners",{"_modelApiKey":55,"slug":53,"name":56},"form","PartnersForm",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":58,"label":59,"isExternal":7,"url":60,"openForm":11,"title":61},"Docs Hub","Learn more","https:\u002F\u002Fdocs.commercelayer.io\u002F","Docs",{"hasSubMenu":11,"showTag":11,"_modelApiKey":12,"text":63,"isExternal":11,"link":64,"openForm":11,"title":63},"Blog",{"_modelApiKey":65,"slug":66},"blog_landing_page","blog",[68,72],{"text":69,"link":70},"Sign in",{"_modelApiKey":12,"text":69,"isExternal":7,"url":71,"openForm":11},"https:\u002F\u002Fdashboard.commercelayer.io\u002Fsign_in",{"text":73,"link":74},"Sign up for free",{"_modelApiKey":12,"text":73,"isExternal":7,"url":75,"openForm":11},"https:\u002F\u002Fdashboard.commercelayer.io\u002Fsign_up",[77,89,109,132],{"hasSubMenu":7,"title":8,"links":78},[79,81,83,85,87],{"showTag":11,"_modelApiKey":12,"text":13,"subtitle":14,"icon":15,"isExternal":11,"link":80,"openForm":11},{"_modelApiKey":17,"slug":18,"title":19},{"showTag":11,"_modelApiKey":12,"text":21,"subtitle":22,"icon":23,"isExternal":11,"link":82,"openForm":11},{"_modelApiKey":17,"slug":25,"title":21},{"showTag":11,"_modelApiKey":12,"text":27,"subtitle":28,"icon":29,"isExternal":11,"link":84,"openForm":11},{"_modelApiKey":17,"slug":31,"title":27},{"showTag":11,"_modelApiKey":12,"text":33,"subtitle":34,"icon":35,"isExternal":11,"link":86,"openForm":11},{"_modelApiKey":17,"slug":37,"title":33},{"showTag":11,"_modelApiKey":12,"text":40,"isExternal":11,"link":88,"openForm":11},{"_modelApiKey":42,"slug":43},{"hasSubMenu":7,"title":90,"links":91},"Resources",[92,94,99,104,107],{"showTag":11,"_modelApiKey":12,"text":93,"isExternal":7,"url":60,"openForm":11},"Documentation",{"showTag":11,"_modelApiKey":12,"text":95,"label":95,"isExternal":11,"link":96,"openForm":11},"Agentic Commerce",{"_modelApiKey":17,"slug":97,"title":98},"agentic-commerce-whitepaper","Agentic Commerce Whitepaper",{"showTag":11,"_modelApiKey":12,"text":100,"isExternal":11,"link":101,"openForm":11},"Core concepts",{"_modelApiKey":17,"slug":102,"title":103},"headless-commerce","Headless commerce",{"showTag":11,"_modelApiKey":12,"text":105,"isExternal":7,"url":106,"openForm":11},"Changelog","https:\u002F\u002Fdocs.commercelayer.io\u002Fchangelog\u002F",{"showTag":11,"_modelApiKey":12,"text":63,"isExternal":11,"link":108,"openForm":11},{"_modelApiKey":65,"slug":66},{"hasSubMenu":7,"title":110,"links":111},"Company",[112,116,118,121,126],{"showTag":11,"_modelApiKey":12,"text":113,"isExternal":11,"link":114,"openForm":11},"Vision",{"_modelApiKey":17,"slug":115,"title":113},"vision",{"showTag":11,"_modelApiKey":12,"text":45,"isExternal":11,"link":117,"openForm":11},{"_modelApiKey":47,"slug":48,"title":49},{"showTag":11,"_modelApiKey":12,"text":51,"isExternal":11,"link":119,"openForm":11,"form":120},{"_modelApiKey":17,"slug":53,"title":51},{"_modelApiKey":55,"slug":53,"name":56},{"showTag":11,"_modelApiKey":12,"text":122,"isExternal":11,"link":123,"openForm":11},"Security",{"_modelApiKey":17,"slug":124,"title":125},"security","Security at Commerce Layer",{"showTag":11,"_modelApiKey":12,"text":127,"label":128,"isExternal":11,"openForm":7,"form":129},"Giveback","Giveback program",{"_modelApiKey":55,"slug":130,"name":131},"giveback","GivebackForm",{"hasSubMenu":7,"title":133,"links":134},"Get in touch",[135,140,145,149],{"showTag":11,"_modelApiKey":12,"text":136,"isExternal":11,"openForm":7,"form":137},"Contact",{"_modelApiKey":55,"slug":138,"name":139},"contact","ContactUsForm",{"showTag":11,"_modelApiKey":12,"text":141,"isExternal":11,"openForm":7,"form":142},"Book a demo",{"_modelApiKey":55,"slug":143,"name":144},"demo","RequestDemoForm",{"showTag":11,"_modelApiKey":12,"text":146,"label":147,"isExternal":7,"url":148,"openForm":11},"Support","Email support","mailto:support@commercelayer.io",{"showTag":11,"_modelApiKey":12,"text":150,"label":151,"isExternal":7,"url":152,"openForm":11},"Community","Discord community","https:\u002F\u002Fdiscord.gg\u002Fcommercelayer",{"hasSubMenu":7,"title":154,"links":155},"Legal",[156,161,165,169,173],{"showTag":11,"_modelApiKey":12,"text":157,"label":158,"isExternal":7,"url":159,"openForm":11,"htmlClassNames":160},"Terms","Terms and conditions","\u002Flegal-embed\u002Fterms-of-service","iubenda-nostyle no-brand iubenda-noiframe iubenda-embed",{"showTag":11,"_modelApiKey":12,"text":162,"label":163,"isExternal":7,"url":164,"openForm":11,"htmlClassNames":160},"Privacy","Privacy policy","\u002Flegal-embed\u002Fprivacy-policy",{"showTag":11,"_modelApiKey":12,"text":166,"label":167,"isExternal":7,"url":168,"openForm":11,"htmlClassNames":160},"Cookies","Cookie policy","\u002Flegal-embed\u002Fcookie-policy",{"showTag":11,"_modelApiKey":12,"text":170,"isExternal":7,"url":171,"openForm":11,"htmlClassNames":172},"Notice at collection","#","iubenda-cs-uspr-link",{"showTag":11,"_modelApiKey":12,"text":174,"isExternal":7,"url":171,"openForm":11,"htmlClassNames":175},"Privacy preferences","iubenda-cs-preferences-link",[177,180,184,188,192],{"title":178,"type":179,"url":152,"isExternal":7},"Discord","discord-logo",{"title":181,"type":182,"url":183,"isExternal":7},"Github","github","https:\u002F\u002Fgithub.com\u002Fcommercelayer",{"title":185,"type":186,"url":187,"isExternal":7},"Bluesky","bluesky-logo","https:\u002F\u002Fbsky.app\u002Fprofile\u002Fcommercelayer.io",{"title":189,"type":190,"url":191,"isExternal":7},"X","x-logo","https:\u002F\u002Fx.com\u002Fcommercelayer",{"title":193,"type":194,"url":195,"isExternal":7},"LinkedIn","linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fcommerce-layer",{"pagesWithoutCtaPanel":197,"ctaPanel":198,"notification":208,"showApiResponseTime":11,"newsletterSignup":216},[],{"title":199,"subtitle":200,"ctas":201},"Ready to get started?","Discover how we can help your business.",[202,205],{"_modelApiKey":203,"text":204,"isExternal":7,"url":75,"openForm":11},"link","Get started for free",{"_modelApiKey":203,"text":206,"isExternal":11,"openForm":7,"form":207},"Contact us",{"_modelApiKey":55,"slug":138,"name":139},{"showNotification":7,"link":209,"linkText":210,"text":215},{"_modelApiKey":203,"text":210,"isExternal":11,"link":211,"openForm":11},"Read article",{"_modelApiKey":212,"slug":213,"title":214},"blog_post","payment-api-redesigned","Introducing our new Payments API. For humans and agents.","\u003Cp>Introducing our new Payments API. For humans and agents.\u003C\u002Fp>\n",{"ctaText":217},"Subscribe",[219,225,229,236,240,246,249,253,261,262,267,272,274],{"_modelApiKey":55,"slug":220,"pardotFormEmbedCode":221,"formEmbedMinHeight":222,"successTitle":223,"successCopy":224},"agentic-commerce","https:\u002F\u002Fcommercelayer.fillout.com\u002Ft\u002F5w4Khwgxr6us?whitepaper=agentic",520,"Thank you for your request!","We’ll be in touch soon to arrange a date and time for your personalized demo.",{"_modelApiKey":55,"slug":226,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"successTitle":223,"successCopy":224},"shopify","https:\u002F\u002Fform.fillout.com\u002Ft\u002FgVnLSmKZwRus",850,{"_modelApiKey":55,"slug":130,"pardotFormEmbedCode":230,"formEmbedMinHeight":231,"displayTitle":232,"copy":233,"successTitle":234,"successCopy":235},"https:\u002F\u002Fform.fillout.com\u002Ft\u002FmVDF8aAiofus",500,"We give back.","\u003Cp>Part of Commerce Layer&#39;s company ethos is to empathize and support one another: co-workers, customers, and community. We want to do our part to help nonprofit organizations and small businesses who may feel adversely affected by the current global economic climate, and as a result, need in-kind support to reach their customers.\u003C\u002Fp>\n\n\u003Cp>If this general description matches your organization’s needs, please tell us your story by completing the following form so we can consider helping your cause.\u003C\u002Fp>\n","Thank you!","We will contact you soon to learn more about your story.",{"_modelApiKey":55,"slug":237,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"displayTitle":238,"copy":239},"book-an-onboarding-session","Book an onboarding session","\u003Cp>Schedule some time and our devs will help you set up a Commerce Layer + Sanity store.\u003C\u002Fp>\n",{"_modelApiKey":55,"slug":241,"pardotFormEmbedCode":242,"formEmbedMinHeight":243,"displayTitle":244,"successTitle":234,"successCopy":245},"download-our-whitepaper","https:\u002F\u002Fform.fillout.com\u002Ft\u002F5YPWmy8oT7us?whitepaper=ComposableCommerce",450,"Download our whitepaper.","Check your inbox. You should receive a download link soon.",{"_modelApiKey":55,"slug":247,"pardotFormEmbedCode":248,"formEmbedMinHeight":243,"displayTitle":244,"successTitle":234,"successCopy":245},"download-the-content-and-commerce-whitepaper","https:\u002F\u002Fform.fillout.com\u002Ft\u002F5YPWmy8oT7us?whitepaper=ContentAndCommerce",{"_modelApiKey":55,"slug":250,"pardotFormEmbedCode":251,"formEmbedMinHeight":243,"displayTitle":244,"copy":252,"successTitle":234,"successCopy":245},"whitepaper","https:\u002F\u002Fform.fillout.com\u002Ft\u002F5YPWmy8oT7us?whitepaper=Jamstack","\u003Cp>Commerce Layer is the perfect platform for building commerce on the Jamstack. Convert any design into pixel perfect HTML pages. Connect a best-of-breed headless CMS. Go serverless and forget the hassle of managing complex infrastructures.\u003C\u002Fp>\n",{"_modelApiKey":55,"slug":254,"pardotFormEmbedCode":255,"formEmbedMinHeight":256,"displayTitle":257,"copy":258,"successTitle":259,"successCopy":260},"contact-links","https:\u002F\u002Fform.fillout.com\u002Ft\u002FeWPyhHGHT7us",750,"Contact us.","\u003Cp>Tell us about your project. Our team will reach out to you for a personalized offer.\u003C\u002Fp>\n","Thanks for your message!","We’ll be in touch soon to discuss your project details.",{"_modelApiKey":55,"slug":138,"pardotFormEmbedCode":255,"formEmbedMinHeight":256,"displayTitle":257,"copy":258,"successTitle":259,"successCopy":260},{"_modelApiKey":55,"slug":263,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"displayTitle":264,"successTitle":265,"successCopy":266},"demo-embed","Want to see it in action? Request a demo.","Thanks for your request!","We’ll be in touch soon to arrange a date and time for your free live demo.",{"_modelApiKey":55,"slug":53,"pardotFormEmbedCode":268,"formEmbedMinHeight":228,"displayTitle":269,"copy":270,"successTitle":234,"successCopy":271},"https:\u002F\u002Fform.fillout.com\u002Ft\u002F9MTkDWMUSqus","Become our partner.","\u003Cp>Join us and get our guidance in helping your clients succeed. Our partners are our ambassadors. We are committed to your success as much as you are.\u003C\u002Fp>\n","We will contact you soon to discuss the details of our partnership.",{"_modelApiKey":55,"slug":273,"pardotFormEmbedCode":268,"formEmbedMinHeight":228,"displayTitle":269,"copy":270,"successTitle":234,"successCopy":271},"partners-embed",{"_modelApiKey":55,"slug":143,"pardotFormEmbedCode":227,"formEmbedMinHeight":228,"displayTitle":275,"copy":276,"successTitle":265,"successCopy":266},"Get a free live demo.","\u003Cp>Get a personalized demo and learn more about what Commerce Layer can do for your company.\u003C\u002Fp>\n",{"_modelApiKey":212,"link":278,"subtitle":283,"date":283,"author":284,"additionalAuthors":294,"icon":295,"abstract":296,"tag":297,"displayTitle":279,"cardRatio":300,"featured":11,"seoMetaTags":301,"layout":365,"blogPostCarousel":562,"_seoMetaTags":627,"authors":661},{"text":279,"isExternal":11,"url":280,"link":281},"A comprehensive guide to Commerce Layer webhooks.","",{"_modelApiKey":212,"slug":282},"a-comprehensive-guide-to-commerce-layer-webhooks","June 9, 2022",{"name":285,"picture":286},"Bolaji Ayodeji",{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":291,"customData":293},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1643036479-bolaji.jpg","Bolaji Ayodeji — Developer Advocate at Commerce Layer",1280,"jpg",{"x":292,"y":292},0.5,{},[],"webhooks-logo","We provides a list of specific events you can monitor and transmit real-time data from using webhooks. In this article, we will introduce our webhooks mechanism and guide you through a couple of simple demo examples so that you can see it in action.",{"color":298,"name":299},"gray","Tutorials","portrait",[302,306,310,313,317,320,323,327,331,335,338,342,346,350,354,357,361],{"attributes":303,"tag":304,"content":305},null,"title","A Comprehensive Guide to Commerce Layer Webhooks",{"attributes":307,"tag":309,"content":303},{"property":308,"content":305},"og:title","meta",{"attributes":311,"tag":309,"content":303},{"name":312,"content":305},"twitter:title",{"attributes":314,"tag":309,"content":303},{"name":315,"content":316},"description","Commerce Layer's webhooks mechanism makes it easier for you to increase business flexibility, customer retention, and developer experience.",{"attributes":318,"tag":309,"content":303},{"property":319,"content":316},"og:description",{"attributes":321,"tag":309,"content":303},{"name":322,"content":316},"twitter:description",{"attributes":324,"tag":309,"content":303},{"property":325,"content":326},"og:image","https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654677460-a-comprehensive-guide-to-commerce-layer-webhooks.jpg?auto=format&fit=max&w=1200",{"attributes":328,"tag":309,"content":303},{"property":329,"content":330},"og:image:width","1200",{"attributes":332,"tag":309,"content":303},{"property":333,"content":334},"og:image:height","630",{"attributes":336,"tag":309,"content":303},{"name":337,"content":326},"twitter:image",{"attributes":339,"tag":309,"content":303},{"property":340,"content":341},"og:locale","en",{"attributes":343,"tag":309,"content":303},{"property":344,"content":345},"og:type","article",{"attributes":347,"tag":309,"content":303},{"property":348,"content":349},"og:site_name","Commerce Layer",{"attributes":351,"tag":309,"content":303},{"property":352,"content":353},"article:modified_time","2025-10-08T16:22:26Z",{"attributes":355,"tag":309,"content":303},{"property":356,"content":280},"article:publisher",{"attributes":358,"tag":309,"content":303},{"name":359,"content":360},"twitter:card","summary_large_image",{"attributes":362,"tag":309,"content":303},{"name":363,"content":364},"twitter:site","@commercelayer",[366,372,378,381,391,394,401,404,407,412,415,417,420,422,425,427,430,438,441,448,451,453,456,460,463,471,474,476,479,481,484,486,489,491,494,497,500,502,505,507,514,517,519,527,530,532,535,537,540,542,545,547,550,559],{"_modelApiKey":367,"copy":368,"listStyle":369,"darkTheme":11,"buttons":370,"color":371,"indent":7},"wysiwyg","\u003Cp>More than just delivering a robust API with hundreds of endpoints, Commerce Layer also provides an API mechanism that allows developers to send data to other applications in real-time. This mechanism is called \u003Cstrong>webhooks\u003C\u002Fstrong> (also referred to as &quot;reverse APIs&quot;), and with it, you can use a push strategy to trigger actions outside of Commerce Layer either for integration with transactional emails, CRMs, ERPs, fulfillment services, couriers, etc. In this tutorial, we will demystify webhooks, show you how it works, and help you get started.\u003C\u002Fp>\n","directional",[],"red",{"_modelApiKey":373,"title":374,"preTitle":375,"linkText":59,"darkTheme":11,"link":376},"link_block","Real-time webhooks.","From the docs",{"_modelApiKey":203,"text":59,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":377,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Freal-time-webhooks",{"_modelApiKey":367,"copy":379,"listStyle":369,"darkTheme":11,"buttons":380,"color":371,"indent":11},"\u003Chr>\n\n\u003Ch3>Prerequisites\u003C\u002Fh3>\n\n\u003Cul>\n\u003Cli>A general understanding of how APIs and the command-line work.\u003C\u002Fli>\n\u003Cli>Some prior knowledge of the JavaScript programming language.\u003C\u002Fli>\n\u003Cli>A \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdashboard.commercelayer.io\u002Fsign_up\">Commerce Layer account\u003C\u002Fa>. You should have set up your organization, and created the required commerce data resources for your market. You can follow the \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fwelcome\u002Fonboarding-tutorial\">onboarding tutorial\u003C\u002Fa> or \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fwelcome\u002Fmanual-configuration\">manual configuration guide\u003C\u002Fa> to achieve this.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Chr>\n\n\u003Ch3>Introduction to webhooks\u003C\u002Fh3>\n\n\u003Cp>The term &quot;webhook&quot; was first used by \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fprogrium.github.io\u002Fblog\u002F2007\u002F05\u002F03\u002Fweb-hooks-to-revolutionize-the-web\u002F\">Jeff Lindsay in 2007\u003C\u002Fa> in an attempt to introduce a mechanism that allows users to push out data wherever they want to. \u003Cstrong>The entire concept of webhooks aims to ensure data transmission from one application to another when certain events occur.\u003C\u002Fstrong> For example, Commerce Layer and Slack can be two applications you want to transmit some information across. If a customer purchases an order in your store, you can send some data with all the details of that order to Slack immediately after the order is placed. This explains why webhooks are triggered by &quot;events&quot; and what follows is the transmission of some data in real-time to the &quot;handler&quot; via a specified URL endpoint (from Slack in this case). One event can be an order placement, another can be customer creation or parcel shipment. With webhooks, the possibilities are numerous, and you can do so much more with data to improve your business.\u003C\u002Fp>\n",[],{"_modelApiKey":382,"border":11,"caption":280,"image":383,"size":390,"darkTheme":11,"rounded":11,"color":371},"image_block",{"url":384,"alt":385,"title":385,"width":386,"height":387,"format":388,"focalPoint":303,"customData":389},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654535077-webhooks.svg","How webhooks work",1375,215,"svg",{},"standard",{"_modelApiKey":367,"copy":392,"listStyle":369,"darkTheme":11,"buttons":393,"color":371,"indent":11},"\u003Ch3>Commerce Layer webhooks\u003C\u002Fh3>\n\n\u003Cp>Commerce Layer provides a \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Freal-time-webhooks#supported-events\">list of specific events\u003C\u002Fa> you can monitor and transmit real-time data from using webhooks. Each time a subscribed event occurs, we trigger a POST request to the endpoint you will specify in a \u003Ccode>callback_url\u003C\u002Fcode> field. The  POST request contains a JSON payload in the same format that you get when fetching the same resource through the \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fv\u002Fapi-reference\u002F\">REST API\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Cp>When you create a new webhook, a \u003Cstrong>shared secret\u003C\u002Fstrong> is automatically generated and you can find this on the admin dashboard. This secret will be used each time the webhook is triggered to sign the payload. For security reasons, when sending and receiving data to and from a webhook, \u003Cstrong>we recommend verifying the callback authenticity\u003C\u002Fstrong> by signing the payload with the shared secret and comparing the result with the \u003Ccode>X-CommerceLayer-Signature\u003C\u002Fcode> callback header. You can \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fcallbacks-security\">learn more about this\u003C\u002Fa> and how to verify callback authenticity in the documentation.\u003C\u002Fp>\n\n\u003Cp>If a webhook fails, Commerce Layer will retry it again up to \u003Cstrong>10 times\u003C\u002Fstrong>. After \u003Cstrong>30 consecutive failures,\u003C\u002Fstrong> no further calls will be made to the related endpoint, and you will need to reset the webhook to trigger it again.\u003C\u002Fp>\n",[],{"_modelApiKey":382,"border":11,"caption":280,"image":395,"size":390,"darkTheme":11,"rounded":11,"color":371},{"url":396,"alt":397,"title":397,"width":398,"height":399,"format":388,"focalPoint":303,"customData":400},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654771092-commerce-layer-webhooks.svg","How Commerce Layer webhooks work",2330,630,{},{"_modelApiKey":367,"copy":402,"listStyle":369,"darkTheme":11,"buttons":403,"color":371,"indent":11},"\u003Ch3>Commerce Layer webhooks use cases\u003C\u002Fh3>\n\n\u003Cp>There’s a lot you can do with webhooks ranging from email notifications to data transmission. For example, when a customer places a new order, you can send them an email based on any order status of your choosing or even send an update to your internal team Slack channel\u002Fexternal fulfillment system using the \u003Ccode>orders.place\u003C\u002Fcode> event. Or, when a customer’s order is shipped, you can send them an email or SMS notification using the \u003Ccode>shipments.ship\u003C\u002Fcode> event connected to a tool like Sendgrid or Twilio. The possibilities are numerous, and here’s a list of some popular use cases:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Send email confirmation on order placement, order cancellation, order return, shipping confirmation on shipment shipping, delivery confirmations, etc.\u003C\u002Fli>\n\u003Cli>Send a reminder to customers when they abandon some items in their cart.\u003C\u002Fli>\n\u003Cli>Send a new customer to a Customer relationship management tool (CRM).\u003C\u002Fli>\n\u003Cli>Notify a customer when a specific item is back in stock.\u003C\u002Fli>\n\u003Cli>Send sales data to an accounting system when an order is successfully paid.\u003C\u002Fli>\n\u003Cli>Notify the warehouse when a shipment is ready to be shipped, or move it to an external third-party logistics system.\u003C\u002Fli>\n\u003Cli>Send a purchased gift card to a customer, either via email or physically.\u003C\u002Fli>\n\u003Cli>Notify customers that a new coupon code has been created for them.\u003C\u002Fli>\n\u003Cli>Notify a customer if there is an issue with their payment.\u003C\u002Fli>\n\u003Cli>Notify customers of available discounts and promotions.\u003C\u002Fli>\n\u003Cli>Notify your internal team when an item runs out of stock.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>... and much more\u003C\u002Fp>\n\n\u003Cp>Do check \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Freal-time-webhooks#supported-events\">our documentation\u003C\u002Fa> to find the complete list of all the resources and events you can monitor with Commerce Layer webhooks and choose any that works for your use case.\u003C\u002Fp>\n",[],{"_modelApiKey":367,"copy":405,"listStyle":369,"darkTheme":11,"buttons":406,"color":371,"indent":11},"\u003Ch3>Getting Started with Commerce Layer webhooks\u003C\u002Fh3>\n\n\u003Cp>Now that you understand what our webhooks are and how they work, let’s show you how to create them using either the CLI or our dashboard. It’s a straightforward and fun process, so let’s get right into it.\u003C\u002Fp>\n\n\u003Ch4>Command Line Interface (CLI)\u003C\u002Fh4>\n\n\u003Cp>The \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-cli\">Commerce Layer CLI\u003C\u002Fa> helps you to manage your Commerce Layer applications, including webhooks, right from the terminal. Follow the steps below to install the CLI and create a new webhook:\u003C\u002Fp>\n\n\u003Ch5>\u003Cstrong>1. Install the CLI\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>You can install our CLI using your favorite package manager:\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":409,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"code_block","\u002F\u002Fnpm\nnpm install -g @commercelayer\u002Fcli\n\n\u002F\u002Fyarn\nyarn global add @commercelayer\u002Fcli","shell","Standard",{"_modelApiKey":367,"copy":413,"listStyle":369,"darkTheme":11,"buttons":414,"color":371,"indent":11},"\u003Ch5>\u003Cstrong>2. Create an application\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>Follow \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fwelcome\u002Fmanual-configuration#create-an-application\">this guide\u003C\u002Fa> in the documentation to create an \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Froles-and-permissions#integration\">integration application\u003C\u002Fa> and save the provided \u003Cstrong>client ID\u003C\u002Fstrong>, \u003Cstrong>client secret\u003C\u002Fstrong>, and \u003Cstrong>base endpoint\u003C\u002Fstrong> credentials.\u003C\u002Fp>\n\n\u003Ch5>\u003Cstrong>3. Log into your application\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>You can use those credentials to log into the application via the CLI like so:\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":416,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"cl applications:login -o \u003CorganizationSlug> -i \u003CclientId> -s \u003CclientSecret> -a \u003CapplicationAlias>",{"_modelApiKey":367,"copy":418,"listStyle":369,"darkTheme":11,"buttons":419,"color":371,"indent":11},"\u003Cp>The application alias can be named anything (e.g., \u003Ccode>webhooks-demo\u003C\u002Fcode>). It will be associated with the application you want to log into on your terminal (this is useful when switching between multiple applications).\u003C\u002Fp>\n\n\u003Ch5>\u003Cstrong>4. Install the webhooks plugin\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>To install the \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-cli-plugin-webhooks\">webhooks plugin\u003C\u002Fa> use the command below:\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":421,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"cl plugins:install webhooks",{"_modelApiKey":367,"copy":423,"listStyle":369,"darkTheme":11,"buttons":424,"color":371,"indent":11},"\u003Ch5>\u003Cstrong>5. Create a new webhook\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>To create a new webhook use the command below:\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":426,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"cl webhooks:create \\\n\t-n \"Order Alerts\" \\\n\t-t \"orders.create\" \\\n\t-u \"https:\u002F\u002Fcallback.url.io\" \\\n\t-i \"customer_email,skus_count,line_items,status,payment_status,fulfillment_status,formatted_subtotal_amount\"",{"_modelApiKey":367,"copy":428,"listStyle":369,"darkTheme":11,"buttons":429,"color":371,"indent":11},"\u003Cp>Here’s a breakdown of each of the command options:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>The \u003Ccode>cl webhooks:create\u003C\u002Fcode> command creates a new webhook.\u003C\u002Fli>\n\u003Cli>The \u003Ccode>-n\u003C\u002Fcode> flag defines the name of the webhook.\u003C\u002Fli>\n\u003Cli>The \u003Ccode>-t\u003C\u002Fcode> flag defines the topic of the webhook.\u003C\u002Fli>\n\u003Cli>The \u003Ccode>-u\u003C\u002Fcode> flag defines the callback URL.\u003C\u002Fli>\n\u003Cli>The \u003Ccode>-i\u003C\u002Fcode> flag defines the webhook relationships that will be included in the sent payload.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>When you successfully create a new webhook, you can use the plugin to check created webhooks and events like so:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Ccode>cl webhooks\u003C\u002Fcode> to show a list of all created webhooks.\u003C\u002Fli>\n\u003Cli>\u003Ccode>cl webhooks:events &lt;webhook-id&gt;\u003C\u002Fcode> to show a list of the latest triggered events for a specific webhook.\u003C\u002Fli>\n\u003Cli>\u003Ccode>cl webhooks:event &lt;event-id&gt;\u003C\u002Fcode> to show details about an event.\u003C\u002Fli>\n\u003Cli>\u003Ccode>cl webhooks:payload &lt;event-id&gt;\u003C\u002Fcode> to show the payload associated with an event.\u003C\u002Fli>\n\u003Cli>\u003Ccode>cl webhooks:listen &lt;webhook-id&gt;\u003C\u002Fcode> to listen to a webhook for outgoing callbacks.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>To learn how to perform more actions on your webhooks with the CLI like updating, deleting, resetting, listening, etc., kindly read the documentation \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-cli-plugin-webhooks#commands\">on GitHub\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch4>Dashboard\u003C\u002Fh4>\n\n\u003Cp>Our dashboard also allows you to manage your organization and resources, including webhooks. We’re working on a new dashboard that will be released soon. For now, you can follow the steps below to create a new webhook on the existing dashboard interface:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Create an account or log into your Commerce Layer account \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdashboard.commercelayer.io\u002F\">here\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>Select your organization or follow our \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fwelcome\u002F\">onboarding guides\u003C\u002Fa> to set up a new organization.\u003C\u002Fli>\n\u003Cli>Click the \u003Cem>Go to admin area\u003C\u002Fem> button in the dashboard to head over to the current OMS.\u003C\u002Fli>\n\u003Cli>Head to \u003Cem>Settings &gt; Webhook\u003C\u002Fem> page.\u003C\u002Fli>\n\u003Cli>Create a new webhook and add the following:\n\n\u003Col>\n\u003Cli>A \u003Cstrong>name\u003C\u002Fstrong> of your choosing (e.g. &quot;Orders Notifications&quot;).\u003C\u002Fli>\n\u003Cli>A \u003Cstrong>topic\u003C\u002Fstrong> which is the \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Freal-time-webhooks#supported-events\">resource and event\u003C\u002Fa> you want to monitor (e.g.  \u003Ccode>orders.create\u003C\u002Fcode>).\u003C\u002Fli>\n\u003Cli>A \u003Cstrong>callback URL\u003C\u002Fstrong> which is the endpoint that will be called on each event (you can get this from the third-party app you want to connect to).\u003C\u002Fli>\n\u003Cli>A list of extra resource \u003Cstrong>relationships\u003C\u002Fstrong> you want to \u003Cem>include\u003C\u002Fem> in the webhook payload separated by a comma (e.g., \u003Ccode>skus_count,status,payment_status,fulfillment_status\u003C\u002Fcode>).\u003C\u002Fli>\n\u003C\u002Fol>\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>Once created, you can go back to edit the webhook, reset the circuit, or view the payload from the latest event callbacks triggered by the webhook.\u003C\u002Fp>\n\n\u003Ch3>Webhooks demo\u003C\u002Fh3>\n\n\u003Cp>Now that you know how to create a webhook on Commerce Layer. Let’s test this live and see how webhooks work in real-time. For this tutorial, we will cover two quick demos:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>In the first one, we will use \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fwebhook.site\u002F\">Webhook.site\u003C\u002Fa> to instantly get a unique, random URL that we can use to test and debug webhooks and HTTP requests. We will use the random URL as the callback URL, and we will be able to preview the sent payload and see what the data sent looks like.\u003C\u002Fli>\n\u003Cli>For the second demo, we will build a local server and show you how to connect our webhooks to external services like Twilio for a start.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Alternatively, you can use the CLI to \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fcommercelayer-cli-plugin-webhooks#commercelayer-whlisten-id\">listen for outgoing callbacks\u003C\u002Fa> from a webhook using the command \u003Ccode>cl webhooks:listen &lt;webhook-id&gt;\u003C\u002Fcode> on the terminal.\u003C\u002Fp>\n\n\u003Cp>Let’s roll!\u003C\u002Fp>\n\n\u003Ch4>Sending new order notifications to Webhooks.site\u003C\u002Fh4>\n\n\u003Cp>All you have to do here is head to \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fwebhook.site\u002F\">Webhook.site\u003C\u002Fa>, and a unique URL will be automatically generated for you, as seen in the screenshot below. Kindly copy it to your clipboard and use it as your callback URL when creating a webhook, as explained in the steps above.\u003C\u002Fp>\n",[],{"_modelApiKey":382,"border":7,"caption":280,"image":431,"size":390,"darkTheme":11,"rounded":7,"color":371},{"url":432,"alt":433,"title":433,"width":434,"height":435,"format":290,"focalPoint":436,"customData":437},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654610509-webhooks-site.jpg","Webhooks.site screenshot",1920,1228,{"x":292,"y":292},{},{"_modelApiKey":367,"copy":439,"listStyle":369,"darkTheme":11,"buttons":440,"color":371,"indent":11},"\u003Cp>To test this, you can use the \u003Ccode>orders.create\u003C\u002Fcode> topic and head to the \u003Cem>Orders\u003C\u002Fem> page in the OMS to create a new test order. Select a market, enter your email address (this would be a test customer), and click the \u003Cem>Create\u003C\u002Fem> button. As soon as the order is created successfully, head back to the \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fwebhook.site\u002F\">Webhook.site\u003C\u002Fa> page, and you will see it update in real-time with some payload data from the webhook, as seen in the screenshot below.\u003C\u002Fp>\n",[],{"_modelApiKey":382,"border":7,"caption":280,"image":442,"size":390,"darkTheme":11,"rounded":7,"color":371},{"url":443,"alt":444,"title":444,"width":434,"height":445,"format":290,"focalPoint":446,"customData":447},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654610859-webhooks-site-payload.jpg","Webhooks.site payload",1058,{"x":292,"y":292},{},{"_modelApiKey":367,"copy":449,"listStyle":369,"darkTheme":11,"buttons":450,"color":371,"indent":11},"\u003Cp>The sent payload data for \u003Ccode>orders.create\u003C\u002Fcode> will look like \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdata.commercelayer.app\u002Ftutorial_assets\u002Fcreate_orders.json\">this JSON file\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Cp>A different topic will return different JSON data, and you can easily use this method to explore and test each of them as you desire and all for free. You should also add at least one SKU to the order you created in the OMS — we will need this for the next demo test.\u003C\u002Fp>\n\n\u003Ch4>Sending a &quot;back in stock&quot; notification using Twilio SMS\u003C\u002Fh4>\n\n\u003Cp>\u003Ca target=\"_blank\" href=\"https:\u002F\u002Ftwilio.com\">Twilio\u003C\u002Fa> is a customer engagement platform that allows you to build seamless conversations using several messaging solutions. With the \u003Cstrong>Twilio SMS\u003C\u002Fstrong> channel, you can send and receive text messages using their API. For example, you can decide to send a notification to your customers when an SKU that had finished is back in stock. Let&#39;s see how to do it:\u003C\u002Fp>\n\n\u003Ch5>\u003Cstrong>1. Create a new customer subscription\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>The &quot;back in stock&quot; notification works using the \u003Ccode>in_stock_subscriptions\u003C\u002Fcode> \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fv\u002Fapi-reference\u002Fin_stock_subscriptions\">resource\u003C\u002Fa> that tracks a customer’s interest in an SKU that has gone out of stock in a given market. When the SKU returns back in stock (i.e. the quantity is now greater than zero), all the active subscriptions status will change and receive a &quot;notify&quot; event. To make this demo work, you can create a customer subscription using the CLI as described in the steps below.\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Follow the \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fwelcome\u002Fonboarding-tutorial\">onboarding guide\u003C\u002Fa> to create, set up, and configure your organization with the required resources.\u003C\u002Fli>\n\u003Cli>Follow \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fwelcome\u002Fmanual-configuration#install-the-commerce-layer-cli\">this guide\u003C\u002Fa> to install the CLI and resources plugin and login into your application with the required credentials.\u003C\u002Fli>\n\u003Cli>Ensure you have a registered customer in one of your markets. You can read the API documentation to see \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fdevelopers\u002Fv\u002Fapi-reference\u002Fcustomers\u002Fcreate\">how to create one\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>Create a new in-stock subscription associated with some custom metadata (telephone number and customer name) and required relationships (market ID, customer’s ID, and SKU ID). Ensure to use an SKU with available stock quantity of zero.\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":452,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"cl resources:create in_stock_subscriptions -m \\\n\tcustomer_telephone=\"+12345678910\" \\\n\tcustomer_name=\"Bolaji Ayodeji\" -r \\\n\tmarket=\"VgKNLhKGBj\" \\\n\tcustomer=\"OwyehaRvJX\" \\\n\tsku=\"ZrxeSKVNRB\"",{"_modelApiKey":367,"copy":454,"listStyle":369,"darkTheme":11,"buttons":455,"color":371,"indent":11},"\u003Cp>This will create the in-stock subscription resource as seen in \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdata.commercelayer.app\u002Ftutorial_assets\u002Fin_stock_subscriptions.json\">this JSON file\u003C\u002Fa>. Running \u003Ccode>cl resources:list in_stock_subscriptions\u003C\u002Fcode> will return all available subscriptions and the data returned is what we will use for the webhook.\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":457,"showLineNumbers":11,"highlightLines":280,"language":458,"size":459},"[\n  {\n    id: 'JGayIryawQ',\n    type: 'in_stock_subscriptions',\n    status: 'active',\n    customer_email: 'bolaji@commercelayer.io',\n    sku_code: 'TOTEXXAUFFFFFF000000XXXX',\n    stock_threshold: 1,\n    created_at: '2022-05-31T11:24:11.637Z',\n    updated_at: '2022-05-31T11:24:11.637Z',\n    reference: null,\n    reference_origin: null,\n    metadata: { customer_telephone: 12345678910, customer_name: Bolaji Ayodeji }\n  }\n]","json","Wide",{"_modelApiKey":367,"copy":461,"listStyle":369,"darkTheme":11,"buttons":462,"color":371,"indent":11},"\u003Ch5>\u003Cstrong>2. Set up Twilio\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>Kindly follow the steps below to set up your Twilio account for the messaging integration:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>First, \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fconsole.twilio.com\">create a Twilio account\u003C\u002Fa> if you don’t have one already and verify it.\u003C\u002Fli>\n\u003Cli>Generate a Twilio virtual telephone number.\u003C\u002Fli>\n\u003Cli>If you are on a trial account, you can only send messages to \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fconsole.twilio.com\u002Fus1\u002Fdevelop\u002Fphone-numbers\u002Fmanage\u002Fverified?frameUrl=%2Fconsole%2Fphone-numbers%2Fverified%3Fx-target-region%3Dus1\">verified phone numbers\u003C\u002Fa> (this is typically the number you verified during the account creation and you can equally add more).\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":382,"border":7,"caption":280,"image":464,"size":390,"darkTheme":11,"rounded":7,"color":371},{"url":465,"alt":466,"title":466,"width":467,"height":468,"format":290,"focalPoint":469,"customData":470},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654614353-twilio-account.jpg","Twilio account screenshot",1210,790,{"x":292,"y":292},{},{"_modelApiKey":367,"copy":472,"listStyle":369,"darkTheme":11,"buttons":473,"color":371,"indent":11},"\u003Ch5>\u003Cstrong>3. Set up a local server\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>Remember that we need a callback URL where the payload data will be sent? So we need to set up a local server that can receive the payload for us and then we take the data we need and use \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Ftwilio\u002Ftwilio-node\">Twilio’s Node.js library\u003C\u002Fa> to send the message. We will use \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fnodejs.org\">Node.js\u003C\u002Fa> (a back-end JavaScript runtime environment) and \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fexpressjs.com\">Express.js\u003C\u002Fa> (a minimal and flexible Node.js web application framework) to create a local server. Then we will use \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fngrok.com\">ngrok\u003C\u002Fa> (a distributed reverse proxy fronting web services running in any cloud or private network, or a local machine) to run the local server on the internet through an HTTP tunnel without having to deploy our code. Follow the steps below to set this up in a few minutes.\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdocs.npmjs.com\u002Fdownloading-and-installing-node-js-and-npm\">Install Node.js\u003C\u002Fa> if you don’t have it yet.\u003C\u002Fli>\n\u003Cli>Install Express if you don’t have it yet with the command below:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":475,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"\u002F\u002Fnpm\nnpm install express --save\n\n\u002F\u002Fyarn\nyarn add express",{"_modelApiKey":367,"copy":477,"listStyle":369,"darkTheme":11,"buttons":478,"color":371,"indent":11},"\u003Cul>\n\u003Cli>Install ngrok using the commands below or \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fngrok.com\u002Fdownload\">download it\u003C\u002Fa> for any operating system:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":480,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"\u002F\u002Fmac\nbrew install ngrok\n\n\u002F\u002Flinux\nsnap install ngrok\n\n\u002F\u002Fwindows\nchoco install ngrok",{"_modelApiKey":367,"copy":482,"listStyle":369,"darkTheme":11,"buttons":483,"color":371,"indent":11},"\u003Cul>\n\u003Cli>\u003Ca target=\"_blank\" href=\"https:\u002F\u002Fdashboard.ngrok.com\">Create a new ngrok account\u003C\u002Fa> if you don’t have one yet.\u003C\u002Fli>\n\u003Cli>Create a new API key and copy the generated token.\u003C\u002Fli>\n\u003Cli>Configure ngrok with the auth token using the command below:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":485,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"ngrok config add-authtoken 49wLG5z1gTCKPsYphK3g2FGKk4s_3gyhbxPuGAmBEBtGs5JzJ",{"_modelApiKey":367,"copy":487,"listStyle":369,"darkTheme":11,"buttons":488,"color":371,"indent":11},"\u003Cul>\n\u003Cli>Install \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fbrix\u002Fcrypto-js\">CryptoJS\u003C\u002Fa> (we will use this to verify the callback authenticity from Commerce Layer):\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":490,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"npm install crypto-js",{"_modelApiKey":367,"copy":492,"listStyle":369,"darkTheme":11,"buttons":493,"color":371,"indent":11},"\u003Cul>\n\u003Cli>Create a \u003Ccode>server.js\u003C\u002Fcode> file and add the code below:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":495,"showLineNumbers":11,"highlightLines":280,"language":496,"size":459},"const express = require('express')\nconst app = express()\nconst port = 9000\n\n\u002F\u002F Parse incoming JSON requests and put the parsed data in req.body\napp.use(express.json());\n\napp.post('\u002Fcallback', (req, res) => {\n  console.log(req.body)\n  res.sendStatus(200)\n})\n\napp.listen(port, () => {\n  console.log(`Listening at http:\u002F\u002Flocalhost:${port}`)\n})","javascript",{"_modelApiKey":367,"copy":498,"listStyle":369,"darkTheme":11,"buttons":499,"color":371,"indent":11},"\u003Cul>\n\u003Cli>Start the local Node.js server to begin listening on port 9000 like so:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":501,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"node server.js",{"_modelApiKey":367,"copy":503,"listStyle":369,"darkTheme":11,"buttons":504,"color":371,"indent":11},"\u003Cul>\n\u003Cli>Start an HTTP tunnel listening for HTTP\u002FHTTPS traffic on port 9000:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":506,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"ngrok http 9000",{"_modelApiKey":382,"border":11,"caption":280,"image":508,"size":390,"darkTheme":11,"rounded":7,"color":371},{"url":509,"alt":510,"title":510,"width":434,"height":511,"format":290,"focalPoint":512,"customData":513},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654618053-ngrok-9000.jpg","Ngrok localhost:9000",891,{"x":292,"y":292},{},{"_modelApiKey":367,"copy":515,"listStyle":369,"darkTheme":11,"buttons":516,"color":371,"indent":11},"\u003Cp>Now we can use \u003Ccode>https:\u002F\u002F39cb-8-21-8-251.eu.ngrok.io\u002Fcallback\u003C\u002Fcode> to receive the payload from Commerce Layer (please note that the URL will be different when you do this yourself and it will change every time you restart the ngrok tunnel). You can quickly test this by sending a POST request to the endpoint using curl like so:\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":518,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"curl -X POST \\ \n  https:\u002F\u002F39cb-8-21-8-251.eu.ngrok.io\u002Fcallback \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\n    \"data\": {\n      \"id\": \"testID\",\n      \"company\": \"Commerce Layer\"\n    },\n    \"message\": {\n      \"id\": \"fakeID\",\n      \"text\": \"Good day!\"\n    }\n  }'",{"_modelApiKey":382,"border":11,"caption":280,"image":520,"size":390,"darkTheme":11,"rounded":7,"color":371},{"url":521,"alt":522,"title":522,"width":523,"height":524,"format":290,"focalPoint":525,"customData":526},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654618598-ngrok-tunnel.jpg","Ngrok tunnel",1148,188,{"x":292,"y":292},{},{"_modelApiKey":367,"copy":528,"listStyle":369,"darkTheme":11,"buttons":529,"color":371,"indent":11},"\u003Ch5>\u003Cstrong>4. Create a new webhook\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>Run the command below to create a new \u003Ccode>in_stock_subscriptions\u003C\u002Fcode> webhook (including the callback URL and \u003Ccode>sku\u003C\u002Fcode> resource relationship) using the CLI:\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":531,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"cl webhooks:create \\\n  -n \"Back In Stock Notifications\" \\\n  -t \"in_stock_subscriptions.notify\" \\\n  -u \"https:\u002F\u002F39cb-8-21-8-251.eu.ngrok.io\u002Fcallback\" \\\n  -i \"sku\"",{"_modelApiKey":367,"copy":533,"listStyle":369,"darkTheme":11,"buttons":534,"color":371,"indent":11},"\u003Cp>Now when any SKU that is associated with a customer subscription is re-stocked, an event will be triggered and some data will be sent.\u003C\u002Fp>\n\n\u003Ch5>\u003Cstrong>5. Sending the message with Twilio SMS\u003C\u002Fstrong>\u003C\u002Fh5>\n\n\u003Cp>Now, let’s complete the integration with our webhooks and Twilio SMS. The Commerce Layer webhook will be the trigger event, and the corresponding action is to send a message to the customer’s telephone number. \u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>First, you need to install the Twilio Node.js library like so:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":536,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"npm install twilio",{"_modelApiKey":367,"copy":538,"listStyle":369,"darkTheme":11,"buttons":539,"color":371,"indent":11},"\u003Cul>\n\u003Cli>Create a \u003Ccode>.env\u003C\u002Fcode> file and add the following credentials:\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":408,"code":541,"showLineNumbers":11,"highlightLines":280,"language":410,"size":411},"TWILIO_ACCOUNT_SID=\"\"\nTWILIO_AUTH_TOKEN=\"\"\nTWILIO_PHONE_NUMBER=\"\"\nCL_SHARED_SECRET=\"\"",{"_modelApiKey":367,"copy":543,"listStyle":369,"darkTheme":11,"buttons":544,"color":371,"indent":11},"\u003Cp>Then update the \u003Ccode>server.js\u003C\u002Fcode> file earlier created to the code below and restart the server (you can explore the complete code \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Ftree\u002Fmain\u002Fwebhooks\u002Ftwilio-sms-notification\">on GitHub\u003C\u002Fa> too).\u003C\u002Fp>\n",[],{"_modelApiKey":408,"code":546,"showLineNumbers":11,"highlightLines":280,"language":496,"size":459},"require(\"dotenv\").config();\nconst express = require(\"express\");\nconst CryptoJS = require(\"crypto-js\");\nconst hmacSHA256 = require(\"crypto-js\u002Fhmac-sha256\");\n\nconst app = express();\nconst port = 9000;\n\n\u002F\u002F Define Twilio credentials\nconst accountSid = process.env.TWILIO_ACCOUNT_SID;\nconst authToken = process.env.TWILIO_AUTH_TOKEN;\nconst client = require(\"twilio\")(accountSid, authToken);\n\n\u002F\u002F Parse incoming JSON requests and put the parsed data in req.body\napp.use(express.json());\n\napp.post(\"\u002Fcallback\", (req, res) => {\n  \u002F\u002F Verify the payload coming from Commerce Layer\n  const signature = req.headers[\"x-commercelayer-signature\"];\n  const hash = hmacSHA256(\n    JSON.stringify(req.body),\n    process.env.CL_SHARED_SECRET\n  );\n  const encode = hash.toString(CryptoJS.enc.Base64);\n  if (req.method === \"POST\" && signature === encode) {\n    const payload = req.body;\n\n    \u002F\u002F Fetch the customer's name and telephone number from the custom metadata\n    const customerName = payload.data.attributes.metadata.customer_name;\n    const customerTelephone = payload.data.attributes.metadata.customer_telephone;\n\n    \u002F\u002F Fetch the SKU name from the included sku relationship\n    const skuName = payload.included.map((item) => item.attributes.name);\n\n    \u002F\u002F Fetch the SKU code from the payload's default attributes\n    const skuCode = payload.data.attributes.sku_code;\n\n    \u002F\u002F Send SMS with Twilio\n    client.messages\n      .create({\n        body: `Hi ${customerName}!\\n\\nThe ${skuName} (${skuCode}) is now back in stock 🎉. Cheers!`,\n        from: process.env.TWILIO_PHONE_NUMBER,\n        to: `+${customerTelephone}`,\n      })\n      .then((message) => console.log(\"Message sent!\", message))\n      .catch((err) => console.error(\"Error sending message\", err));\n    res.status(200).json({\n      message: \"Message sent to customer!\",\n    });\n  } else {\n    res.status(401).json({\n      error: \"Unauthorized: Invalid signature\",\n    });\n  }\n});\n\napp.listen(port, () => {\n  console.log(`Listening at http:\u002F\u002Flocalhost:${port}`);\n});",{"_modelApiKey":367,"copy":548,"listStyle":369,"darkTheme":11,"buttons":549,"color":371,"indent":11},"\u003Cp>Now to test this — head to the inventory section of the current dashboard, search for the SKU code we used to create the subscription for the \u003Ccode>bolaji@commercelayer.io\u003C\u002Fcode> customer earlier, and increase the quantity in the stock location associated with the market you used earlier (for the demo, it’s a US Warehouse stock location in a US market). Once this is done, the event will be triggered, \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Ftree\u002Fmain\u002Fwebhooks\u002Ftwilio-sms-notification\u002Fpayload.json\">the payload\u003C\u002Fa> will be sent to the defined callback URL, and the message will be sent using Twilio SMS.\u003C\u002Fp>\n",[],{"_modelApiKey":382,"border":11,"caption":280,"image":551,"size":390,"darkTheme":11,"rounded":11,"color":371},{"url":552,"alt":553,"title":553,"width":554,"height":555,"format":556,"focalPoint":557,"customData":558},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1654620944-twilio-response-sms.png","Twilio response + SMS",1195,514,"png",{"x":292,"y":292},{},{"_modelApiKey":367,"copy":560,"listStyle":369,"darkTheme":11,"buttons":561,"color":371,"indent":11},"\u003Cp>And that’s it! If you intend to use the SMS notification in production, you will need to deploy the local server we built so you can get a permanent URL endpoint and it’s runs 24\u002F7.\u003C\u002Fp>\n\n\u003Cp>For further customization and to optimize your business branding, you can register an alphanumeric sender ID. This makes it easier to deal with filters and increase the chances of customers trusting your messages. You can read \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fsupport.twilio.com\u002Fhc\u002Fen-us\u002Farticles\u002F223133767-International-support-for-Alphanumeric-Sender-ID\">this guide\u003C\u002Fa> to learn the regulations for each country you intend to send messages to and \u003Ca target=\"_blank\" href=\"https:\u002F\u002Ftwiliodoer.secure.force.com\u002FSenderId\">register a sender ID\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch3>Conclusion\u003C\u002Fh3>\n\n\u003Cp>Now you have an idea of what it feels like when we say Commerce Layer is the commerce API for everything brands need. More than just providing you with APIs and the right tools to build the perfect infrastructure for your ecommerce business. \u003Cstrong>Our webhooks technology makes it easier for you to increase business flexibility, customer experience, customer retention, and developer experience.\u003C\u002Fstrong>\u003C\u002Fp>\n\n\u003Cp>In the next tutorial part of our \u003Cem>Webhook series\u003C\u002Fem>, we will take you on another tour where you will learn how to use our webhooks to send order confirmation emails to customers. Sounds like what you’ve wanted to learn, right? Then \u003Ca target=\"_blank\" href=\"https:\u002F\u002Fslack.commercelayer.app\u002F\">join our Slack community\u003C\u002Fa> to get notified when we publish.\u003C\u002Fp>\n",[],{"displayTitle":563,"cta":303,"ctaText":280,"cards":564},"Your next read",[565,580,595,609],{"_modelApiKey":212,"link":566,"subtitle":570,"date":570,"author":571,"additionalAuthors":575,"icon":576,"abstract":577,"tag":578,"displayTitle":567,"cardRatio":300,"featured":579},{"text":567,"isExternal":11,"url":280,"link":568},"Getting started with Commerce Layer JavaScript SDK.",{"_modelApiKey":212,"slug":569},"getting-started-with-commerce-layer-javascript-sdk","April 14, 2022",{"name":285,"picture":572},{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":573,"customData":574},{"x":292,"y":292},{},[],"code-block","Commerce Layer provides a JavaScript SDK that makes it quick and easy for developers to interact with our commerce APIs. In this article, we’ll look at some fundamental technical details about how it works.",{"color":298,"name":299},0,{"_modelApiKey":212,"link":581,"subtitle":585,"date":585,"author":586,"additionalAuthors":590,"icon":591,"abstract":592,"tag":593,"displayTitle":582,"cardRatio":11,"featured":594},{"text":582,"isExternal":11,"url":280,"link":583},"How to make any website shoppable with Commerce Layer.",{"_modelApiKey":212,"slug":584},"how-to-make-any-website-shoppable-with-commerce-layer","February 14, 2022",{"name":285,"picture":587},{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":588,"customData":589},{"x":292,"y":292},{},[],"eyedropper","The fastest way to get started with headless commerce and Commerce Layer. Let's build a simple ecommerce product page with static content, make it shoppable using Commerce Layer's dropin javascript library, and deploy the application to the cloud.",{"color":298,"name":299},1,{"_modelApiKey":212,"link":596,"subtitle":600,"date":600,"author":601,"additionalAuthors":605,"icon":606,"abstract":607,"tag":608,"displayTitle":597,"cardRatio":11,"featured":38},{"text":597,"isExternal":11,"url":280,"link":598},"How to build an international ecommerce website with Sanity and Commerce Layer.",{"_modelApiKey":212,"slug":599},"how-to-build-an-international-ecommerce-website-with-sanity-and-commerce-layer","April 6, 2022",{"name":285,"picture":602},{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":603,"customData":604},{"x":292,"y":292},{},[],"shapes","Learn how to integrate Sanity with Commerce Layer by looking at how we built our starter template using Sanity Studio, Next.js, and our React components library.",{"color":298,"name":299},{"_modelApiKey":212,"link":610,"subtitle":614,"date":614,"author":615,"additionalAuthors":622,"icon":623,"abstract":624,"tag":625,"displayTitle":611,"cardRatio":11,"featured":626},{"text":611,"isExternal":11,"url":280,"link":612},"How to sell internationally with a single Shopify store and Commerce Layer.",{"_modelApiKey":212,"slug":613},"how-to-sell-internationally-with-a-single-shopify-store-and-commerce-layer","February 22, 2022",{"name":616,"picture":617},"Filippo Conforti",{"url":618,"alt":619,"title":619,"width":289,"height":289,"format":556,"focalPoint":620,"customData":621},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1614874449-commercelayeravatarsquare212f3f.png","Filippo Conforti — CEO at Commerce Layer",{"x":292,"y":292},{},[],"globe","Shopify is a popular ecommerce platform that helps merchants grow their businesses, until it comes to expanding internationally. Learn how to extend Shopify with Commerce Layer, enabling brands to scale internationally without the trade-offs.",{"color":298,"name":8},3,[628,629,631,633,635,637,639,641,643,645,647,649,651,653,655,657,659],{"attributes":303,"tag":304,"content":305},{"attributes":630,"tag":309,"content":303},{"property":308,"content":305},{"attributes":632,"tag":309,"content":303},{"name":312,"content":305},{"attributes":634,"tag":309,"content":303},{"name":315,"content":316},{"attributes":636,"tag":309,"content":303},{"property":319,"content":316},{"attributes":638,"tag":309,"content":303},{"name":322,"content":316},{"attributes":640,"tag":309,"content":303},{"property":325,"content":326},{"attributes":642,"tag":309,"content":303},{"property":329,"content":330},{"attributes":644,"tag":309,"content":303},{"property":333,"content":334},{"attributes":646,"tag":309,"content":303},{"name":337,"content":326},{"attributes":648,"tag":309,"content":303},{"property":340,"content":341},{"attributes":650,"tag":309,"content":303},{"property":344,"content":345},{"attributes":652,"tag":309,"content":303},{"property":348,"content":349},{"attributes":654,"tag":309,"content":303},{"property":352,"content":353},{"attributes":656,"tag":309,"content":303},{"property":356,"content":280},{"attributes":658,"tag":309,"content":303},{"name":359,"content":360},{"attributes":660,"tag":309,"content":303},{"name":363,"content":364},[662],{"name":285,"picture":663},{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":664,"customData":665},{"x":292,"y":292},{},1790593730244]