[{"data":1,"prerenderedAt":573},["ShallowReactive",2],{"bootstrap":3,"blog-connecting-any-payment-gateway-to-commerce-layer-with-external-payments":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":303,"_seoMetaTags":534,"authors":568},{"text":279,"isExternal":11,"url":280,"link":281},"Connecting any payment gateway to Commerce Layer with external payments.","",{"_modelApiKey":212,"slug":282},"connecting-any-payment-gateway-to-commerce-layer-with-external-payments","May 28, 2026",{"name":285,"picture":286},"Matteo Alessani",{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":291,"customData":293},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1754320247-matteo-a.jpg","Commerce Layer avatar",1280,"jpg",{"x":292,"y":292},0.5,{},[],"credit-card","Learn how to connect any payment provider to Commerce Layer using external payment gateways. This tutorial walks through an async Mollie integration with TypeScript, webhooks, place and authorize payment flows.",{"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","External payments: connect any gateway to Commerce Layer",{"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","Learn how to integrate any payment provider with Commerce Layer using external gateways, async webhooks, Mollie, and TypeScript.",{"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\u002F1779813115-external-payments.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","2026-06-16T12:57:02Z",{"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,376,381,384,395,398,401,415,418,424,427,431,434,439,442,444,447,450,452,454,457,459,462,464,467,470,474,477,504,507,510,513,516,519,522],{"_modelApiKey":367,"copy":368,"listStyle":369,"darkTheme":11,"buttons":370,"color":371,"indent":7},"wysiwyg","\u003Cp>One of Commerce Layer&#39;s most powerful yet underrated capabilities is its \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fexternal-resources\u002Fexternal-payment-gateways\">external payment gateway\u003C\u002Fa> — a first-class integration point that lets you connect \u003Cem>any\u003C\u002Fem> payment provider to Commerce Layer without writing a custom integration from scratch. If a provider has an API, you can bridge it in.\u003C\u002Fp>\n\n\u003Cp>In this article we&#39;ll explore what the external gateway is, why it matters for complex commerce architectures, and walk through a working proof of concept that integrates Mollie as a third-party gateway using two different order-placement strategies:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Place\u003C\u002Fli>\n\u003Cli>Authorize\u003C\u002Fli>\n\u003C\u002Ful>\n","checkbox",[],"red",{"_modelApiKey":367,"copy":373,"listStyle":374,"darkTheme":11,"buttons":375,"color":371,"indent":11},"\u003Ch3>Why external gateways matter\u003C\u002Fh3>\n\n\u003Cp>Commerce Layer ships with \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fhow-tos\u002Fplacing-orders\u002Fpayments\">first-party connectors\u003C\u002Fa> for Stripe, Braintree, PayPal, Klarna, Adyen, and several others. But the real world is messy: your enterprise client in Brazil uses a local acquirer you&#39;ve never heard of; your MENA merchant requires a gateway that only speaks Arabic-locale APIs; your fintech customer needs a white-labelled payment solution that wraps their own banking infrastructure.\u003C\u002Fp>\n\n\u003Cp>The external payment gateway is the answer to all of these. Rather than waiting for a native connector, you expose a small HTTP endpoint that speaks Commerce Layer&#39;s webhook protocol. Commerce Layer will call that endpoint at the right moment in the order lifecycle — and your code decides what to do with the request, talking to any third-party API it needs to.\u003C\u002Fp>\n\n\u003Cp>The result is a clean, \u003Cstrong>provider-agnostic payment layer\u003C\u002Fstrong> where the Commerce Layer order state machine stays authoritative, and the payment complexity lives entirely in your gateway microservice.\u003C\u002Fp>\n","directional",[],{"_modelApiKey":377,"title":378,"preTitle":93,"linkText":59,"darkTheme":11,"link":379},"link_block","External payment gateways",{"_modelApiKey":203,"text":59,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":380,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fexternal-resources\u002Fexternal-payment-gateways",{"_modelApiKey":367,"copy":382,"listStyle":374,"darkTheme":11,"buttons":383,"color":371,"indent":11},"\u003Ch3>How it works\u003C\u002Fh3>\n\n\u003Cp>The contract is deliberately minimal:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>You register one or more URLs in the Commerce Layer dashboard (one per lifecycle action — authorize, capture, void, refund, token). \u003C\u002Fli>\n\u003Cli>Commerce Layer signs every outbound request with an \u003Cstrong>HMAC-SHA256\u003C\u002Fstrong> header.\u003C\u002Fli>\n\u003Cli>Your endpoint verifies the signature, does whatever your provider requires, and replies.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>For synchronous gateways, a \u003Ccode>200 OK\u003C\u002Fcode> with \u003Ccode>success: true\u003C\u002Fcode> is enough to advance the order state machine. For providers that settle asynchronously — hosted payment pages, bank redirects, delayed captures — you return \u003Ccode>202 Accepted\u003C\u002Fcode> with a unique \u003Ccode>action_id\u003C\u002Fcode>. Commerce Layer parks the transaction in a pending state and waits. When your gateway later POSTs to Commerce Layer&#39;s \u003Ccode>webhook_endpoint_url\u003C\u002Fcode> with that same \u003Ccode>action_id\u003C\u002Fcode>, the authorization is completed and the order lifecycle continues.\u003C\u002Fp>\n",[],{"_modelApiKey":385,"border":11,"caption":280,"image":386,"size":394,"darkTheme":11,"rounded":11,"color":371},"image_block",{"url":387,"alt":388,"title":388,"width":389,"height":390,"format":391,"focalPoint":392,"customData":393},"https:\u002F\u002Fwww.datocms-assets.com\u002F35053\u002F1779813549-external-gateway-diagram-draft.png","External gateways diagram",1402,1122,"png",{"x":292,"y":292},{},"standard",{"_modelApiKey":367,"copy":396,"listStyle":369,"darkTheme":11,"buttons":397,"color":371,"indent":11},"\u003Ch3>Prerequisites\u003C\u002Fh3>\n\n\u003Cul>\n\u003Cli>Familiarity with REST APIs, webhooks, and HMAC-based request signing.\u003C\u002Fli>\n\u003Cli>Confidence reading and writing TypeScript in a Node.js server context.\u003C\u002Fli>\n\u003Cli>A \u003Ca href=\"https:\u002F\u002Fdashboard.commercelayer.io\u002Fsign_up\">Commerce Layer\u003C\u002Fa> account with: a configured \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore-api-reference\u002Fmarkets\u002F\">market\u003C\u002Fa> with at least one SKU, inventory entry, and shipping method, a set of \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fapi-credentials#sales-channel\">sales channel\u003C\u002Fa> API credentials scoped to that market, a set of \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fapi-credentials#integration\">integration\u003C\u002Fa> API credentials (used by the gateway server).\u003C\u002Fli>\n\u003Cli>A Mollie account with a \u003Ca href=\"https:\u002F\u002Fhelp.mollie.com\u002Fhc\u002Fen-us\u002Farticles\u002F360023732273-What-is-an-API-key\">test API key\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fngrok.com\u002F\">ngrok\u003C\u002Fa> or \u003Ca href=\"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fconnections\u002Fconnect-networks\u002F\">cloudflare\u003C\u002Fa> to expose your local gateway to the internet.\u003C\u002Fli>\n\u003C\u002Ful>\n",[],{"_modelApiKey":367,"copy":399,"listStyle":374,"darkTheme":11,"buttons":400,"color":371,"indent":11},"\u003Ch3>The proof of concept\u003C\u002Fh3>\n\n\u003Cp>The \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Fsolutions\u002Fexternal-payment-gateway\">companion repository\u003C\u002Fa> is a minimal TypeScript monorepo with two packages:\u003C\u002Fp>\n",[],{"_modelApiKey":402,"darkTheme":11,"table":403,"size":414},"table_block",{"columns":404,"data":407},[405,406],"Package","Role",[408,411],{"Package":409,"Role":410},"\u003Ccode>packages\u002Fapp\u003C\u002Fcode>","Vite + React SPA — builds the order and shows the async status.",{"Package":412,"Role":413},"\u003Ccode>packages\u002Fmollie-gateway\u003C\u002Fcode>","Hono HTTP server — the gateway bridge between Commerce Layer and Mollie.","Standard",{"_modelApiKey":367,"copy":416,"listStyle":374,"darkTheme":11,"buttons":417,"color":371,"indent":11},"\u003Cp>The demo keeps both packages small so you can follow every step of the flow.\u003C\u002Fp>\n",[],{"_modelApiKey":377,"title":419,"preTitle":420,"linkText":421,"darkTheme":11,"link":422},"External gateways demo","POC","View it on GitHub",{"_modelApiKey":203,"text":421,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":423,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Fsolutions\u002Fexternal-payment-gateway",{"_modelApiKey":367,"copy":425,"listStyle":374,"darkTheme":11,"buttons":426,"color":371,"indent":11},"\u003Ch3>Setting up the external gateway in Commerce Layer\u003C\u002Fh3>\n\n\u003Cp>Before writing any code, you need to register your gateway in the Commerce Layer dashboard.\u003C\u002Fp>\n\n\u003Cp>Go to \u003Cem>Settings → Payment gateways → Add payment gateway → External\u003C\u002Fem> and fill in:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>Name\u003C\u002Fstrong> — anything descriptive (e.g. \u003Ccode>Mollie Gateway\u003C\u002Fcode>)\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Authorize URL\u003C\u002Fstrong> — the public URL where Commerce Layer will POST when an order is placed (e.g. \u003Ccode>https:\u002F\u002Fyour-tunnel.ngrok.io\u002Fauthorize\u003C\u002Fcode>)\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>After saving you&#39;ll receive two values you&#39;ll need to copy:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>Shared secret\u003C\u002Fstrong> — used to sign and verify webhook payloads (stored as \u003Ccode>CL_GATEWAY_SHARED_SECRET\u003C\u002Fcode>).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Webhook endpoint URL\u003C\u002Fstrong> — the URL your gateway calls back to complete an async authorization (stored as \u003Ccode>CL_WEBHOOK_ENDPOINT_URL\u003C\u002Fcode>).\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Then attach this gateway to your market under \u003Cem>Markets → Your market → Payment methods\u003C\u002Fem>.\u003C\u002Fp>\n",[],{"_modelApiKey":428,"icon":429,"copy":430,"color":371},"banner","lightbulb","\u003Cp>If you plan to leverage the \u003Ccode>_authorize\u003C\u002Fcode> trigger, enable \u003Cem>Auto place\u003C\u002Fem> on the payment method so that a successful async authorization automatically places the order — no extra frontend call needed.\u003C\u002Fp>\n",{"_modelApiKey":367,"copy":432,"listStyle":374,"darkTheme":11,"buttons":433,"color":371,"indent":11},"\u003Ch3>Two strategies for the same result\u003C\u002Fh3>\n\n\u003Cp>The demo exposes both ways the frontend can trigger the authorization step.\u003C\u002Fp>\n\n\u003Ch4>Strategy 1 — Place\u003C\u002Fh4>\n\n\u003Cp>The classic checkout flow. A single \u003Ccode>PATCH\u003C\u002Fcode> on the order with \u003Ccode>_place: true\u003C\u002Fcode> both finalizes the order and triggers the authorization. Commerce Layer sends the \u003Ccode>POST \u002Fauthorize\u003C\u002Fcode> request to your gateway synchronously as part of that transition.\u003C\u002Fp>\n",[],{"_modelApiKey":435,"code":436,"showLineNumbers":11,"highlightLines":280,"language":437,"size":438},"code_block","await cl.orders.update({ id: order.id, _place: true })","typescript","Wide",{"_modelApiKey":367,"copy":440,"listStyle":374,"darkTheme":11,"buttons":441,"color":371,"indent":11},"\u003Ch4>Strategy 2 — Authorize\u003C\u002Fh4>\n\n\u003Cp>The authorization-first flow. The frontend triggers authorization explicitly with \u003Ccode>_authorize: true\u003C\u002Fcode>. If \u003Cem>Auto place\u003C\u002Fem> is enabled on the payment method, a successful authorization automatically places the order — useful when you want to separate the &quot;confirm payment&quot; step from the &quot;submit order&quot; step, or when a multi-step checkout UI needs finer control.\u003C\u002Fp>\n",[],{"_modelApiKey":435,"code":443,"showLineNumbers":11,"highlightLines":280,"language":437,"size":438},"await cl.orders.update({ id: order.id, _authorize: true })",{"_modelApiKey":428,"icon":445,"copy":446,"color":371},"info","\u003Cp>Both strategies hit the same \u003Ccode>\u002Fauthorize\u003C\u002Fcode> endpoint on your gateway. The difference is purely in how and when the order state machine advances on the Commerce Layer side.\u003C\u002Fp>\n",{"_modelApiKey":367,"copy":448,"listStyle":374,"darkTheme":11,"buttons":449,"color":371,"indent":11},"\u003Ch3>Inside the gateway: the authorize endpoint\u003C\u002Fh3>\n\n\u003Cp>This is the core of the async contract. The \u003Ccode>\u002Fauthorize\u003C\u002Fcode> route receives a signed request from Commerce Layer, extracts the Mollie payment ID that the frontend stored in \u003Ccode>payment_source_token\u003C\u002Fcode>, and responds with \u003Ccode>202 Accepted\u003C\u002Fcode> + an \u003Ccode>action_id\u003C\u002Fcode> to signal that authorization is in progress.\u003C\u002Fp>\n",[],{"_modelApiKey":435,"code":451,"showLineNumbers":11,"highlightLines":280,"language":437,"size":438},"authorizeRoute.post('\u002F', async (c) => {\n  const rawBody = await c.req.text()\n  const signature = c.req.header('X-CommerceLayer-Signature')\n\n  if (!verifySignature(rawBody, signature)) {\n    return c.json({ error: { code: 'INVALID_SIGNATURE' } }, 401)\n  }\n\n  const body = JSON.parse(rawBody)\n  const paymentSourceToken = body?.data?.attributes?.payment_source_token\n\n  \u002F\u002F Use the Mollie payment ID as the action_id — we'll send it back\n  \u002F\u002F to CL's webhook_endpoint_url once Mollie confirms the payment.\n  return c.json(\n    {\n      success: true,\n      data: {\n        transaction_token: `cl-txn-${Date.now()}`,\n        action_id: paymentSourceToken,\n      },\n    },\n    202, \u002F\u002F 202 = async flow started\n  )\n})",{"_modelApiKey":428,"icon":445,"copy":453,"color":371},"\u003Cp>The \u003Ccode>action_id\u003C\u002Fcode> is the linchpin of the async flow. Commerce Layer stores it and expects to see it again in the callback that completes the authorization.\u003C\u002Fp>\n",{"_modelApiKey":367,"copy":455,"listStyle":374,"darkTheme":11,"buttons":456,"color":371,"indent":11},"\u003Ch3>Inside the gateway: closing the loop\u003C\u002Fh3>\n\n\u003Cp>When the customer completes payment on the Mollie-hosted page, Mollie fires a \u003Ccode>POST\u003C\u002Fcode> to our \u003Ccode>\u002Fmollie-webhook\u003C\u002Fcode> endpoint with a form-encoded body containing a single field: the ID of the payment. The handler parses that ID, instantiates a Mollie client, and fetches the current payment status:\u003C\u002Fp>\n",[],{"_modelApiKey":435,"code":458,"showLineNumbers":11,"highlightLines":280,"language":437,"size":438},"mollieWebhookRoute.post('\u002F', async (c) => {\n  const body = await c.req.parseBody()\n  const paymentId = body['id'] as string | undefined\n\n  if (!paymentId) return c.text('Missing id', 400)\n\n  const mollie = createMollieClient({ apiKey: process.env.MOLLIE_API_KEY })\n  const payment = await mollie.payments.get(paymentId)\n\n  if (payment.status === 'paid') {\n    await notifyCL(paymentId)\n  }\n\n  \u002F\u002F Mollie expects a 200 OK — always return it regardless of our processing\n  return c.text('OK')\n})",{"_modelApiKey":367,"copy":460,"listStyle":374,"darkTheme":11,"buttons":461,"color":371,"indent":11},"\u003Cp>The \u003Ccode>paid\u003C\u002Fcode> guard is important: Mollie webhooks are status-agnostic — they fire for every status change (open, pending, failed, expired, etc.), not only for successful payments. We only want to notify Commerce Layer when the payment has actually been confirmed.\u003C\u002Fp>\n\n\u003Cp>Once we know the payment is \u003Ccode>paid\u003C\u002Fcode>, we call \u003Ccode>notifyCL\u003C\u002Fcode>. This is where we close the async loop that was opened by the \u003Ccode>202 Accepted\u003C\u002Fcode> response in the authorize endpoint. We build a payload with \u003Ccode>success: true\u003C\u002Fcode> and the \u003Ccode>action_id\u003C\u002Fcode> set to the Mollie payment ID (which is the same value we stored as \u003Ccode>action_id\u003C\u002Fcode> when we created the payment), sign it with the shared secret, and \u003Ccode>POST\u003C\u002Fcode> it to Commerce Layer&#39;s \u003Ccode>webhook_endpoint_url\u003C\u002Fcode>:\u003C\u002Fp>\n",[],{"_modelApiKey":435,"code":463,"showLineNumbers":11,"highlightLines":280,"language":437,"size":438},"async function notifyCL(actionId: string) {\n  const payload = {\n    success: true,\n    data: {\n      action_id: actionId,\n      message: 'Payment authorized via Mollie',\n    },\n  }\n\n  const rawBody = JSON.stringify(payload)\n  const signature = createHmac('sha256', process.env.CL_GATEWAY_SHARED_SECRET)\n    .update(rawBody)\n    .digest('base64')\n\n  await fetch(process.env.CL_WEBHOOK_ENDPOINT_URL, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application\u002Fjson',\n      'X-CommerceLayer-Signature': signature,\n    },\n    body: rawBody,\n  })\n}",{"_modelApiKey":367,"copy":465,"listStyle":374,"darkTheme":11,"buttons":466,"color":371,"indent":11},"\u003Cp>Commerce Layer receives the callback, matches the \u003Ccode>action_id\u003C\u002Fcode> to the pending authorization, and transitions the payment — and the order — to \u003Ccode>authorized\u003C\u002Fcode>. The frontend polls the order status and shows the confirmation screen once the transition is detected.\u003C\u002Fp>\n",[],{"_modelApiKey":367,"copy":468,"listStyle":369,"darkTheme":11,"buttons":469,"color":371,"indent":11},"\u003Ch4>Resilience in production\u003C\u002Fh4>\n\n\u003Cp>The demo&#39;s \u003Ccode>notifyCL\u003C\u002Fcode> function is intentionally minimal. In a production gateway you&#39;ll want to harden this path:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>\u003Cem>Retry with backoff\u003C\u002Fem>\u003C\u002Fstrong>---Commerce Layer&#39;s \u003Ccode>webhook_endpoint_url\u003C\u002Fcode> may be temporarily unavailable or return a transient error. Wrap the call in a retry loop (exponential backoff, 3–5 attempts) before giving up.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Cem>Persist the action ID\u003C\u002Fem>\u003C\u002Fstrong>---Store the pending \u003Ccode>action_id\u003C\u002Fcode> in a durable queue or database so that a process restart between the provider webhook and the CL callback doesn&#39;t leave the authorization permanently pending.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Cem>Handle provider webhook deduplication\u003C\u002Fem>\u003C\u002Fstrong>---Mollie (and most providers) may deliver the same webhook event more than once. Your handler should be \u003Cem>idempotent\u003C\u002Fem> — check whether the \u003Ccode>action_id\u003C\u002Fcode> has already been forwarded before calling Commerce Layer again.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Cem>Alert on terminal failure\u003C\u002Fem>\u003C\u002Fstrong>---If the CL callback ultimately fails after all retries, the order will remain in an indeterminate state. Surface this to your operations team immediately rather than silently discarding the error.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Commerce Layer&#39;s own circuit breaker will open after repeated failures from your gateway, temporarily suspending calls to your endpoint — so a well-behaved gateway that retries and self-heals is important for keeping the circuit closed. See the docs for thresholds and recovery behaviour:\u003C\u002Fp>\n",[],{"_modelApiKey":377,"title":471,"preTitle":93,"linkText":59,"darkTheme":11,"link":472},"Circuit breaker",{"_modelApiKey":203,"text":59,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":473,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fexternal-resources#circuit-breaker",{"_modelApiKey":367,"copy":475,"listStyle":374,"darkTheme":11,"buttons":476,"color":371,"indent":11},"\u003Ch3>Beyond authorization: the full gateway contract\u003C\u002Fh3>\n\n\u003Cp>This demo focuses on the \u003Cstrong>authorize\u003C\u002Fstrong> step because it&#39;s the entry point of every payment flow, and it&#39;s where the async pattern is most interesting. But the external gateway protocol covers the entire payment lifecycle. For each action you want to support, you register a dedicated URL in the gateway settings and implement the corresponding endpoint:\u003C\u002Fp>\n",[],{"_modelApiKey":402,"darkTheme":11,"table":478,"size":438},{"columns":479,"data":483},[480,481,482],"Action","URL field","When it's called",[484,488,492,496,500],{"Action":485,"URL field":486,"When it's called":487},"\u003Cstrong>Authorize\u003C\u002Fstrong>","\u003Ccode>authorize_url\u003C\u002Fcode>","When an order is placed or \u003Ccode>_authorize\u003C\u002Fcode> is triggered.",{"Action":489,"URL field":490,"When it's called":491},"\u003Cstrong>Capture\u003C\u002Fstrong>","\u003Ccode>capture_url\u003C\u002Fcode>","When an authorization is captured (e.g. at fulfilment).",{"Action":493,"URL field":494,"When it's called":495},"\u003Cstrong>Void\u003C\u002Fstrong>","\u003Ccode>void_url\u003C\u002Fcode>","When an authorization is cancelled before capture.",{"Action":497,"URL field":498,"When it's called":499},"\u003Cstrong>Refund\u003C\u002Fstrong>","\u003Ccode>refund_url\u003C\u002Fcode>","When a captured payment is refunded, fully or partially.",{"Action":501,"URL field":502,"When it's called":503},"\u003Cstrong>Token\u003C\u002Fstrong>","\u003Ccode>token_url\u003C\u002Fcode>","When a customer saves a payment source for future use.",{"_modelApiKey":367,"copy":505,"listStyle":374,"darkTheme":11,"buttons":506,"color":371,"indent":11},"\u003Cp>Each endpoint receives a signed JSON:API payload with the relevant transaction resource and a set of pre-included relationships (\u003Ccode>order\u003C\u002Fcode>, \u003Ccode>line_items\u003C\u002Fcode>, \u003Ccode>billing_address\u003C\u002Fcode>, \u003Ccode>customer\u003C\u002Fcode>, and more) so your gateway has all the context it needs without extra roundtrips to the Commerce Layer API.\u003C\u002Fp>\n\n\u003Cp>The response contract is consistent across all actions: return a \u003Ccode>transaction_token\u003C\u002Fcode>, the \u003Ccode>amount_cents\u003C\u002Fcode> involved, and optionally \u003Ccode>metadata\u003C\u002Fcode> and \u003Ccode>messages\u003C\u002Fcode> (which Commerce Layer will attach as notifications to the order). Return an HTTP \u003Ccode>4xx\u003C\u002Fcode> on failure.\u003C\u002Fp>\n\n\u003Cp>All actions except \u003Ccode>token_url\u003C\u002Fcode> also support the async \u003Ccode>202\u003C\u002Fcode> pattern described above — meaning you can defer capture, void, and refund confirmations just as you can defer authorization.\u003C\u002Fp>\n\n\u003Cp>The demo repository implements the authorize endpoint and the async webhook callback. Extending it to cover capture, void, and refund follows exactly the same structure: a new route file, the same HMAC verification helper, and a \u003Ccode>POST\u003C\u002Fcode> to whichever third-party API your provider exposes.\u003C\u002Fp>\n\n\u003Cp>The full protocol reference is available in the \u003Ca href=\"https:\u002F\u002Fdocs.commercelayer.io\u002Fcore\u002Fexternal-resources\u002Fexternal-payment-gateways\">Commerce Layer docs\u003C\u002Fa>.\u003C\u002Fp>\n",[],{"_modelApiKey":367,"copy":508,"listStyle":374,"darkTheme":11,"buttons":509,"color":371,"indent":11},"\u003Ch3>Running the demo locally\u003C\u002Fh3>\n\n\u003Cp>You can run the demo on your local machine by following these simple steps:\u003C\u002Fp>\n",[],{"_modelApiKey":435,"code":511,"showLineNumbers":11,"highlightLines":280,"language":512,"size":438},"# Clone and install\ngit clone https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples.git\ncd examples\u002Fsolutions\u002Fexternal-payment-gateway\npnpm install\n\n# Copy and fill in environment variables\ncp packages\u002Fmollie-gateway\u002F.env.example packages\u002Fmollie-gateway\u002F.env\ncp packages\u002Fapp\u002F.env.example packages\u002Fapp\u002F.env\n\n# Start a tunnel so Commerce Layer can reach your local gateway\nngrok http 3001\n# → copy the https URL into GATEWAY_PUBLIC_URL and the authorize URL in the CL dashboard\n\n# Start both packages\npnpm dev","shell",{"_modelApiKey":367,"copy":514,"listStyle":374,"darkTheme":11,"buttons":515,"color":371,"indent":11},"\u003Cp>Open \u003Ccode>http:\u002F\u002Flocalhost:5173\u003C\u002Fcode>, choose either the \u003Ccode>_place\u003C\u002Fcode> or \u003Ccode>_authorize\u003C\u002Fcode> flow, and watch the async payment lifecycle unfold in real time.\u003C\u002Fp>\n",[],{"_modelApiKey":367,"copy":517,"listStyle":374,"darkTheme":11,"buttons":518,"color":371,"indent":11},"\u003Ch3>Conclusion\u003C\u002Fh3>\n\n\u003Cp>The external payment gateway is what makes Commerce Layer viable for enterprise deals that standard connectors can&#39;t cover. A local acquirer in Southeast Asia with a bespoke API, a regulated PSP in the Middle East that requires custom authentication flows, a unified commerce platform that needs to route payments through an in-house settlement layer — all of these map cleanly onto the same protocol. You write a gateway microservice that speaks to your provider; Commerce Layer owns the order state machine.\u003C\u002Fp>\n\n\u003Cp>The Mollie demo is a concrete, runnable starting point. The async \u003Ccode>202\u003C\u002Fcode> pattern it demonstrates applies unchanged to any provider with a hosted payment page or delayed settlement. Swap the Mollie SDK calls for your provider&#39;s client library and the scaffold remains the same.\u003C\u002Fp>\n",[],{"_modelApiKey":428,"icon":520,"copy":521,"color":371},"github-logo","\u003Cp>You can explore \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcommercelayer\u002Fexamples\u002Fsolutions\u002Fexternal-payment-gateway\">this GitHub repository\u003C\u002Fa>, which contains the code used in this article, for further learning and code customization. Thank you for reading this far. Cheers!\u003C\u002Fp>\n",{"_modelApiKey":523,"cards":524,"paragraph":280,"displayTitle":280,"subtitle":280,"size":414},"card_stack",[525],{"_modelApiKey":526,"cardStackSize":527,"copy":528,"displayTitle":529,"subtitle":280,"hideTitleIfImageIsSet":11,"image":303,"iconName":280,"iconColour":530,"link":531,"linkText":280},"information_card","row","\u003Cp>Mollie is a European payment service provider known for its straightforward API and broad coverage of local and international payment methods — including iDEAL, Klarna, Bancontact, credit cards, and more. It is especially popular among e-commerce businesses in the Netherlands, Belgium, and Germany. Mollie offers a fully hosted checkout experience, transparent pricing with no hidden fees, and excellent developer tooling, making it a great choice for integrating payments without managing sensitive card data directly.\u003C\u002Fp>\n","About Mollie","violet",{"_modelApiKey":203,"text":532,"label":280,"subtitle":280,"icon":280,"isExternal":7,"url":533,"link":303,"anchor":280,"openForm":11,"form":303,"htmlClassNames":280},"Vist website","https:\u002F\u002Fmollie.com\u002F",[535,536,538,540,542,544,546,548,550,552,554,556,558,560,562,564,566],{"attributes":303,"tag":304,"content":305},{"attributes":537,"tag":309,"content":303},{"property":308,"content":305},{"attributes":539,"tag":309,"content":303},{"name":312,"content":305},{"attributes":541,"tag":309,"content":303},{"name":315,"content":316},{"attributes":543,"tag":309,"content":303},{"property":319,"content":316},{"attributes":545,"tag":309,"content":303},{"name":322,"content":316},{"attributes":547,"tag":309,"content":303},{"property":325,"content":326},{"attributes":549,"tag":309,"content":303},{"property":329,"content":330},{"attributes":551,"tag":309,"content":303},{"property":333,"content":334},{"attributes":553,"tag":309,"content":303},{"name":337,"content":326},{"attributes":555,"tag":309,"content":303},{"property":340,"content":341},{"attributes":557,"tag":309,"content":303},{"property":344,"content":345},{"attributes":559,"tag":309,"content":303},{"property":348,"content":349},{"attributes":561,"tag":309,"content":303},{"property":352,"content":353},{"attributes":563,"tag":309,"content":303},{"property":356,"content":280},{"attributes":565,"tag":309,"content":303},{"name":359,"content":360},{"attributes":567,"tag":309,"content":303},{"name":363,"content":364},[569],{"name":285,"picture":570},{"url":287,"alt":288,"title":288,"width":289,"height":289,"format":290,"focalPoint":571,"customData":572},{"x":292,"y":292},{},1790593723487]