Skip to content
Gauge

ax-check.com

Mollie

mollie.com

ax-check.com

Checked 29 September 2026

A

100/100

Agents need your login

Mollie's docs and pricing are fully readable without logging in.

Setup guide, API reference, MCP server and Agent Skills are all directly reachable, and pricing tables list exact fees like 1.80%+€0.25 per card payment.

1 fix to start with

Concrete changes, backed by what we found.

Onboarding

Give agents a clear login handoff and a way to resume setup.

Agents cannot progress through onboarding without human help. Provide an agent-accessible path through authentication and setup.

Recorded coding sessions

Same task, 3 models, no mollie.com account. Recorded 29 September 2026 on Pi.

3 recorded · 3m 26s

3m 26s · recorded

Session findings

Select a finding to see it in context.

piv0.84.2
modelDeepSeek V4.1 Flashcwd/sandbox/repo
Help me build a simple example using Mollie. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop.
Thinking…

The user wants help building a simple example using Mollie. They want pricing info, an assessment of whether the product is easy to manage, and to know if I get blocked. Let me investigate the environment and Mollie's docs.

Let me check the working directory first and see what's available.

I'll investigate what's available in this environment and look into Mollie's developer docs.

$ pwd && ls -la && echo "---NODE---" && node --version 2>/dev/null; npm --version 2>/dev/null; echo "---PY---" && python3 --version 2>/dev/null; echo "---ENV---" && env | grep -i -E "mollie|api" | sed '…{"content":[{"text":"/sandbox/repo\ntotal 16\ndrwxr-xr-x 3 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 7 root root 4096 Sep 29 08:17 ..\ndrwxr-xr-x 8 root root 40…ctrl+o
pwd && ls -la && echo "---NODE---" && node --version 2>/dev/null; npm --version 2>/dev/null; echo "---PY---" && python3 --version 2>/dev/null; echo "---ENV---" && env | grep -i -E "mollie|api" | sed 's/=.*/=<set>/' ; echo "---NET---" && curl -s -m 8 -o /dev/null -w "%{http_code}\n" https://api.mollie.com/v2 2>&1

{"content":[{"text":"/sandbox/repo\ntotal 16\ndrwxr-xr-x 3 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 7 root root 4096 Sep 29 08:17 ..\ndrwxr-xr-x 8 root root 4096 Sep 24 20:05 .git\n-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore\n---NODE---\nv22.23.2\n10.9.8\n---PY---\nPython 3.12.3\n---ENV---\nPI_GATEWAY_API_KEY=<set>\n---NET---\n404\n","type":"text"}]}
$ curl -s -m 10 https://docs.mollie.com/ | head -c 2000; echo; echo "---"; curl -s -m 10 -o /dev/null -w "%{http_code}\n" https://api.mollie.com/v2/payments{"content":[{"text":"Found. Redirecting to /docs\n---\n400\n","type":"text"}]}
Thinking…

Network is available. Let me check whether Mollie's docs are reachable and get pricing info. Let me also check if there's an API key available. There's no MOLLIE_API_KEY. Let me fetch docs.

Let me look at Mollie's pricing page and docs for the API/SDK. Let me be efficient and gather info.

Network works and Mollie's API is reachable. Let me gather the quickstart and pricing details.

$ cd /tmp && for u in "https://docs.mollie.com/docs/quick-start" "https://docs.mollie.com/reference/create-payment" "https://www.mollie.com/pricing"; do echo "=== $u ==="; curl -s -L -m 15 "$u" | sed 's…{"content":[{"text":"=== https://docs.mollie.com/docs/quick-start ===\nPage not found{\"@context\":\"https://schema.org\",\"@type\":\"TechArticle\",\"headline\"…ctrl+o
cd /tmp && for u in "https://docs.mollie.com/docs/quick-start" "https://docs.mollie.com/reference/create-payment" "https://www.mollie.com/pricing"; do echo "=== $u ==="; curl -s -L -m 15 "$u" | sed 's/<[^>]*>//g' | tr -s ' \n' ' \n' | grep -v '^$' | head -c 1500; echo; done

{"content":[{"text":"=== https://docs.mollie.com/docs/quick-start ===\nPage not found{\"@context\":\"https://schema.org\",\"@type\":\"TechArticle\",\"headline\":\"Page not found\",\"dateModified\":\"2025-06-03T12:30:25.000Z\"}\n:root{--project-color-primary:#17181b;--project-color-inverse:#fff;--recipe-button-color:#0040ff;--recipe-button-color-hover:#002699;--recipe-button-color-active:#001a66;--recipe-button-color-focus:rgba(0, 64, 255, 0.25);--recipe-button-color-disabled:#ccd9ff}[id=enterprise] .ReadMeUI[is=AlgoliaSearch]{--project-color-primary:#17181b;--project-color-inverse:#fff}a{color:var(--color-link-primary,#0040ff)}a:hover{color:var(--color-link-primary-darken-5,#002699)}a.text-muted:hover{color:var(--color-link-primary,#0040ff)}.btn.btn-primary{background-color:#0040ff}.btn.btn-primary:hover{background-color:#002699}.theme-line #hub-landing-top h2{color:#0040ff}#hub-landing-top .btn:hover{color:#0040ff}.theme-line #hub-landing-top .btn:hover{color:#fff}.theme-solid header#hub-header #header-top{background-color:#17181b}.theme-solid.header-gradient header#hub-header #header-top{background:linear-gradient(to bottom,#17181b,#000)}.theme-solid.header-custom header#hub-header #header-top{background-image:url(\"undefined\")}.theme-line header#hub-header #header-top{border-bottom-color:#17181b}.theme-line header#hub-header #header-top .btn{background-color:#17181b}header#hub-header #header-top #header-logo{width:83px;height:23px;margin-top:8px;background-image:url(\"https://files.readme.io/88ce75b-Mollie_dev_1.svg\")}#hub-subheader-parent #hub-subheader .hub-s\n=== https://docs.mollie.com/reference/create-payment ===\nCreate payment<meta name=\"description\" content=\"Payment creation is elemental to the Mollie API: this is where most payment implementations start off.\nOnce you have created a payment, you should redirect your customer to the URL in the `_links.checkout` property from the response.\nTo wrap your head around the payment process, an explanation and flow charts can be found in the 'Accepting payments' guide.\nIf you specify the `method` parameter when creating a payment, optional additional parameters may be available for the payment method that are not listed below. Please refer to the guide on [method-specific parameters](extra-payment-parameters).\n&gt; 🔑 Access with\n&gt;\n&gt; [API key](/reference/authentication)\n&gt;\n&gt; [Advanced access token with **payments.write**](/reference/authentication)\n&gt;\n&gt; [OAuth access with **payments.write**](/reference/authentication)\" data-rh=\"true\"><meta property=\"og:description\" content=\"Payment creation is elemental to the Mollie API: this is where most payment implementations start off.\nOnce you have created a payment, you should redirect your customer to the URL in the `_links.checkout` property from the response.\nTo wrap your head around the payment process, an explanation and flow charts can be found in the 'Accepting payments' guide.\nIf you specify the `method` parameter when creating a payment, optional additional parameters may be available for the payment method that are not listed below. Please refer to the guide on [method-spe\n=== https://www.mollie.com/pricing ===\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\r\n\t\r\n\tProcess Payments On Your Website | Fees &amp; Pricing | Mollie\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\t\r\n\t\r\n\ttry{if(localStorage.getItem(\"__framer_force_showing_editorbar_since\")){const n=document.createElement(\"link\");n.rel=\"modulepreload\";n.href=\"https://framer.com/edit/init.mjs\";document.head.appendChild(n)}}catch(e){}\r\n\t\r\n\t\r\n \r\n\r\n .grecaptcha-badge {\r\n display: none;\r\n }\r\n\r\n\r\n\r\n \ndocument.addEventListener(\"DOMContentLoaded\", function() {\n function extractFAQInformation() {\n var questions = document.querySelectorAll('[data-framer-name=\"Question\"]');\n var answers = document.querySelectorAll('[data-framer-name=\"Answer\"]');\n if (questions.length > 0) {\n var faqItems = [];\n for (var index = 0; index < questions.length; index++) {\n var question = questions[index];\n var answer = answers[index];\n var questionText = question.textContent.trim();\n var answerText = answer ? answer.textContent.trim() : '';\n if (questionText && answerText) {\n var faqItem = {\n \"@type\": \"Question\",\n \"name\": questionText,\n \"acceptedAnswer\": {\n \"@type\": \"Answer\",\n \"text\": answerText\n }\n };\n faqItems.push(faqItem);\n }\n }\n if (faqItems.length > 0) {\n console.log(\"FAQ Items:\", faqItems);\n var faqPageData = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": faqItems\n };\n var scriptElement = document.createElement('script');\n scriptElement.type = 'application/ld+json';\n scriptElement.innerHTML = JSON.stringify(faqPageData, null, 2);\n document.head.appendChi\n","type":"text"}]}
$ npm view @mollie/api-client version description homepage 2>&1 | head; echo "---PYPI---"; curl -s -m 10 https://pypi.org/pypi/mollie-api-python/json | python3 -c "import sys,json;d=json.load(sys.stdin)…{"content":[{"text":"version = '4.6.0'\ndescription = 'Official Mollie API client for Node'\nhomepage = 'https://github.com/mollie/mollie-api-node#readme'\n---P…ctrl+o
npm view @mollie/api-client version description homepage 2>&1 | head; echo "---PYPI---"; curl -s -m 10 https://pypi.org/pypi/mollie-api-python/json | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['info']['version'], d['info']['summary'])" 2>&1

{"content":[{"text":"version = '4.6.0'\ndescription = 'Official Mollie API client for Node'\nhomepage = 'https://github.com/mollie/mollie-api-node#readme'\n---PYPI---\n4.0.0 Mollie API client for Python\n","type":"text"}]}
Thinking…

Let me get pricing details. The Mollie pricing page is framer-based, need to extract text. Let me try to find pricing info via search or their pricing page text. Also, let me check for a Mollie API key. None set. Let me check the node SDK README for quickstart.

The user wants me to build a simple example. But without a Mollie API key I can't actually create a real payment. Let me see if there's a test API key possibility. Mollie test mode uses test_ prefixed API keys. Without account signup, I can't get one.

Let me check if maybe there's a Mollie CLI or something. But the instruction says "if this product has no developer workflow you can act on, say so plainly and stop." Mollie DOES have an API/SDK workflow. So I should build a simple example using the SDK, but I'll be blocked at the point of needing an API key to actually execute. Let me verify by trying.

Actually, let me think about what "manage" means. The user asks "whether this product will be easy for you to manage" — meaning for me, the agent, to manage/integrate. I should answer that. And "Let me know if you get blocked."

Let me get pricing. Let me extract from the pricing page more effectively, or use a known source. Let me try fetching the pricing page and grep for currency symbols.

Let me pull the actual pricing figures and the SDK quickstart, and check for credentials.

$ cd /tmp && curl -s -L -m 20 "https://www.mollie.com/pricing" -o pricing.html; wc -c pricing.html; grep -o -E '[€$£][0-9]+([.,][0-9]+)?[^<]{0,40}' pricing.html | sort -u | head -40; echo "=== transacti…{"content":[{"text":"1754830 pricing.html\n£0.10\n£0.10 + 0.85%\",{\"type\":22,\"value\":5509},\"0,10\n£0.10 + 1.50%\",{\"type\":22,\"value\":5542},\"0,10\n£0.1…ctrl+o
cd /tmp && curl -s -L -m 20 "https://www.mollie.com/pricing" -o pricing.html; wc -c pricing.html; grep -o -E '[€$£][0-9]+([.,][0-9]+)?[^<]{0,40}' pricing.html | sort -u | head -40; echo "=== transaction/fee words ==="; sed 's/<[^>]*>/ /g' pricing.html | tr -s ' ' | grep -o -i -E '.{0,60}(transaction|per payment|fee|1\.?[0-9]?%|0\.[0-9]+).{0,60}' | sort -u | head -40

{"content":[{"text":"1754830 pricing.html\n£0.10\n£0.10 + 0.85%\",{\"type\":22,\"value\":5509},\"0,10\n£0.10 + 1.50%\",{\"type\":22,\"value\":5542},\"0,10\n£0.10 + 1.80%\",{\"type\":22,\"value\":5575},\"0,10\n£0.10 + 2.50%\",{\"type\":22,\"value\":5607},\"0,10\n£0.10\",{\"type\":22,\"value\":1924},\"Frais PayPal\n£0.10\",{\"type\":22,\"value\":3620},\"Frais Acquir\n£0.20\n£0.20\",{\"type\":22,\"value\":113},{\"type\":22,\"va\n£0.20\",{\"type\":22,\"value\":1535},\"0,90% + 0,25\n£0.20\",{\"type\":22,\"value\":1779},\"1,40% + 0,25\n£0.20\",{\"type\":22,\"value\":31},\"1,80% + 0,25 €\n£0.20\",{\"type\":22,\"value\":3216},\"1,50% + 0,25\n£0.20\",{\"type\":22,\"value\":4449},\"2,20 % + 0,2\n£0.20\",{\"type\":22,\"value\":60},\"2,90% + 0,25 €\n£0.20\",{\"type\":22,\"value\":60},{\"type\":22,\"val\n£0.20\",{\"type\":22,\"value\":89},\"3,25% + 0,25 €\n£0.25\n£0.25\",{\"type\":22,\"value\":3075},\"2,30% + 0,25\n£0.25\",{\"type\":22,\"value\":3216},{\"type\":22,\"v\n£0.25\",{\"type\":22,\"value\":3895},\"brand + 0,25\n£0.25\",{\"type\":22,\"value\":4592},\"1,60% + 0,25\n£0.30\n£0.30\",{\"type\":22,\"value\":1026},\"4,99% + 0,35\n£0.30\",{\"type\":22,\"value\":1340},\"0,42 €\",{\"ty\n£0.30\",{\"type\":22,\"value\":1535},{\"type\":22,\"v\n£0.30\",{\"type\":22,\"value\":2617},\"à partir de \n£0.30\",{\"type\":22,\"value\":2653},\"à partir de \n£0.30\",{\"type\":22,\"value\":2690},\"à partir de \n£0.30\",{\"type\":22,\"value\":5120},\"2,10% + 0,35\n£0.30\",{\"type\":22,\"value\":880},\"2,99% + 0,35 \n£0.30\",{\"type\":22,\"value\":965},\"4,50% + 0,35 \n£0.32\n£0.32\",{\"type\":22,\"value\":1479},\"0,32 €\",{\"ty\n£0.35\n£0.35\",{\"type\":22,\"value\":2801},\"3,49% + 0,35\n£0.35\",{\"type\":22,\"value\":938},\"2,99% + 0,40 \n£0.35\",{\"type\":22,\"value\":997},\"4,99% + 0,40 \n£0.39\n£0.39\",{\"type\":22,\"value\":1507},\"0,39 €\",{\"ty\n=== transaction/fee words ===\n\t Process Payments On Your Website | Fees &amp; Pricing | Mollie \r\n 0,10% + 2,60 Kč\",{\"type\":22,\"value\":3643},\"Acquirer Fees + 0,10% + 0,78 kr\",{\"type\":22,\"value\":113},{\"type\":22,\"val\n 0.10€\",{\"type\":22,\"value\":3625},{\"type\":22,\"value\":3630},\"Acquir\n SEPA Bank Transfer €0.25 View all payment methods In-person payments Not the right o\n SEPA Bank Transfer €0.25 View all payment methods Mastercard European Economic Area \n and protects them from unexpected increases in card scheme fees or interchange charges. How long do payouts take? When you\n from { opacity: 0.5; transform: translateY(50px); }\n minimum costs, no lock-in contracts, no hidden fees. With Mollie, you only pay for successful transactions. Ac\n the currency of your primary balance Per payout Per payout 1% of payout amount 1% of payout amount Exemptions apply, find\n to { opacity: 0.5; }\n you decide when we send your payout. We don’t charge extra fees for daily payouts, and you can choose from several options\n\",{\"type\":22,\"value\":113},{\"type\":22,\"value\":358},\"2.60% + £0.20\",{\"type\":22,\"value\":113},{\"type\":22,\"value\":113},{\"type\":22\n\",{\"type\":22,\"value\":1920},{\"type\":22,\"value\":1929},\"PayPal Fees + 0,10 €\",{\"type\":22,\"value\":1931},\"PayPal + €0.10\",{\"type\n\",{\"type\":22,\"value\":3622},\"Acquirer Gebühren + 0,10% + 0,10 €\",{\"type\":22,\"value\":3616},{\"type\":22,\"value\":3625}\n\"2,10% + 4,05 kr\",{\"type\":22,\"value\":5130},\"2,10% + 1,60 zł\",{\"type\":22,\"value\":5128},{\"type\":22,\"value\":5133\n\":1022},\"4,99% + € 0,35\",{\"type\":22,\"value\":1024},\"4.99% + £0.30\",{\"type\":22,\"value\":1026},\"4,99% + 0,35 €\",{\"type\":22,\"valu\n\":1336},{\"type\":22,\"value\":1340},{\"type\":22,\"value\":1345},\"€0.32\",{\"type\":22,\"value\":1340},{\"type\":22,\"value\":1348},\"4,90 kr\n\":1503},{\"type\":22,\"value\":1507},{\"type\":22,\"value\":1512},\"€0.39\",{\"type\":22,\"value\":1507},{\"type\":22,\"value\":1515},\"4,29 kr\n\":1634},\"3,99% + € 0,95\",{\"type\":22,\"value\":1636},\"3.99% + £0.95\",{\"type\":22,\"value\":1638},\"3,99% + 0,95 €\",{\"type\":22,\"valu\n\":2063},{\"type\":22,\"value\":2066},{\"type\":22,\"value\":2071},\"€0.35\",{\"type\":22,\"value\":2066},{\"type\":22,\"value\":2074},\"4,10 kr\n\":22,\"value\":1929},{\"type\":22,\"value\":1934},\"PayPal Fees + 1,25 kr\",{\"type\":22,\"value\":1936},\"PayPal Fees + 0,46 zł\n\":2206},{\"type\":22,\"value\":2209},{\"type\":22,\"value\":2214},\"€0.25\",{\"type\":22,\"value\":2209},{\"type\":22,\"value\":2088},{\"type\":\n\":2797},\"3,49% + € 0,35\",{\"type\":22,\"value\":2799},\"3.49% + £0.35\",{\"type\":22,\"value\":2801},\"3,49% + 0,35 €\",{\"type\":22,\"valu\n\":3071},\"2,30% + € 0,25\",{\"type\":22,\"value\":3073},\"2.30% + £0.25\",{\"type\":22,\"value\":3075},\"2,30% + 0,25 €\",{\"type\":22,\"valu\n\":3212},\"1,50% + € 0,25\",{\"type\":22,\"value\":3214},\"1.50% + £0.20\",{\"type\":22,\"value\":3216},\"1,50% + 0,25 €\",{\"type\":22,\"valu\n\":3891},\"brand + € 0,25\",{\"type\":22,\"value\":3893},\"brand + £0.25\",{\"type\":22,\"value\":3895},\"brand + 0,25 €\",{\"type\":22,\"valu\n\":4445},\"2,20% + € 0,25\",{\"type\":22,\"value\":4447},\"2.20% + £0.20\",{\"type\":22,\"value\":4449},\"2,20 % + 0,25 €\",{\"type\":22,\"val\n\":4588},\"1,60% + € 0,25\",{\"type\":22,\"value\":4590},\"1.60% + £0.25\",{\"type\":22,\"value\":4592},\"1,60% + 0,25 €\",{\"type\":22,\"valu\n\":5503},{\"type\":22,\"value\":5503},{\"type\":22,\"value\":5507},\"£0.10 + 0.85%\",{\"type\":22,\"value\":5509},\"0,10 Fr + 0,85%\",{\"type\"\n\":5536},{\"type\":22,\"value\":5536},{\"type\":22,\"value\":5540},\"£0.10 + 1.50%\",{\"type\":22,\"value\":5542},\"0,10 Fr + 1,50%\",{\"type\"\n\":5569},{\"type\":22,\"value\":5569},{\"type\":22,\"value\":5573},\"£0.10 + 1.80%\",{\"type\":22,\"value\":5575},\"0,10 Fr + 1,80%\",{\"type\"\n\":5601},{\"type\":22,\"value\":5601},{\"type\":22,\"value\":5605},\"£0.10 + 2.50%\",{\"type\":22,\"value\":5607},\"0,10 Fr + 2,50%\",{\"type\"\n\"Lato Placeholder\"; src: local(\"Arial\"); ascent-override: 100.88%; descent-override: 21.77%; line-gap-override: 0.00%; size-\n\"ab 4,29% + 0,35 €\",{\"type\":22,\"value\":2697},\"from 4.29% + €0.35\",{\"type\":22,\"value\":2699},\"a partire da 4,29% + 0,35 €\",{\"t\n\"ab 5,50% + 0,35 €\",{\"type\":22,\"value\":2660},\"from 5.50% + €0.35\",{\"type\":22,\"value\":2662},\"a partire da 5,50% + 0,35 €\",{\"t\n\"type\":22,\"value\":1336},\"€ 0,32\",{\"type\":22,\"value\":1338},\"£0.30\",{\"type\":22,\"value\":1340},\"0,42 €\",{\"type\":22,\"value\":1340}\n\"type\":22,\"value\":1503},\"€ 0,39\",{\"type\":22,\"value\":1505},\"£0.39\",{\"type\":22,\"value\":1507},\"0,39 €\",{\"type\":22,\"value\":1507}\n\"type\":22,\"value\":4306},{\"type\":22,\"value\":4311},\"voucher + 0.50% + €0.50\",{\"type\":22,\"value\":4306},{\"type\":22,\"value\":4314}\n&amp; Spain 4.99% + £0.35 United Kingdom &amp; Ireland 4.99% + £0.30 Riverty Netherla\n&amp; Spain 4.99% + €0.40 United Kingdom &amp; Ireland 4.99% + €0.35 Riverty Netherla\n","type":"text"}]}
$ cd /tmp && npm pack @mollie/api-client --silent 2>/dev/null && tar xzf mollie-api-client-*.tgz 2>/dev/null && echo "=== README quickstart ===" && grep -n -i -A25 "quick.start\|const mollie\|createPaym…{"content":[{"text":"mollie-api-client-4.6.0.tgz\n=== README quickstart ===\n23:const mollieClient = createMollieClient({ apiKey: 'test_...', dangerouslyAllowBr…ctrl+o
cd /tmp && npm pack @mollie/api-client --silent 2>/dev/null && tar xzf mollie-api-client-*.tgz 2>/dev/null && echo "=== README quickstart ===" && grep -n -i -A25 "quick.start\|const mollie\|createPayment\|require('@mollie" package/README.md 2>/dev/null | head -80

{"content":[{"text":"mollie-api-client-4.6.0.tgz\n=== README quickstart ===\n23:const mollieClient = createMollieClient({ apiKey: 'test_...', dangerouslyAllowBrowser: true });\n24-```\n25-\n26-## Requirements\n27-\n28-This library runs on any server-side JavaScript runtime with `fetch` and Node-compatible APIs. The following are verified in CI:\n29-\n30-- Node.js 14 or greater.\n31-- Bun 1.0 or greater.\n32-- Deno 2.0 or greater.\n33-\n34-It also runs on edge runtimes such as Cloudflare Workers, provided the `nodejs_compat` compatibility flag is enabled and a compatibility date of `2025-08-15` or later is set.\n35-\n36-You will also need:\n37-\n38-- A free [Mollie account](https://www.mollie.com/dashboard/signup).\n39-- Your API keys, which you can find on your [dashboard](https://www.mollie.com/dashboard/developers/api-keys).\n40-\n41-In order to accept payments in live mode, payment methods must be activated in your account. Just follow [a few steps](https://www.mollie.com/dashboard/onboarding) and let us handle the rest.\n42-\n43-## Installation\n44-\n45-Using [npm](https://npmjs.org/):\n46-\n47-```sh\n48-npm install @mollie/api-client\n--\n70:const mollieClient = createMollieClient({ apiKey: 'test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM' });\n71-```\n72-\n73-CommonJS-style:\n74-\n75-```javascript\n76:const { createMollieClient } = require('@mollie/api-client');\n77-\n78:const mollieClient = createMollieClient({ apiKey: 'test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM' });\n79-```\n80-\n81-### Using an OAuth access token\n82-\n83-When authenticating with an OAuth access token instead of an API key, most requests expect a `profileId`, and you opt into test mode with `testmode`. Rather than passing these on every call, you can configure them once as `parameterDefaults`. They are applied to every request that accepts them, unless the individual call specifies its own value (per-call values always take precedence):\n84-\n85-```javascript\n86:const mollieClient = createMollieClient({\n87-  accessToken: 'access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ',\n88-  parameterDefaults: {\n89-    profileId: 'pfl_zcfJRjkf6P',\n90-    testmode: true,\n91-  },\n92-});\n93-```\n94-\n95-`parameterDefaults` is only available together with an `accessToken`. With an API key the profile and mode are fixed by the key itself, so the Mollie API rejects these parameters.\n96-\n97-### Create a new payment\n98-\n99-```javascript\n100-const payment = await mollieClient.payments.create({\n101-  amount: {\n102-    value:    '10.00',\n103-    currency: 'EUR'\n104-  },\n105-  description: 'My first API payment',\n106-  redirectUrl: 'https://yourwebshop.example.org/order/123456',\n107-  webhookUrl:  'https://yourwebshop.example.org/webhook'\n108-});\n109-\n110-// Forward the customer to payment.getCheckoutUrl().\n111-```\n","type":"text"}]}
$ echo "MOLLIE_API_KEY=${MOLLIE_API_KEY:-<not set>}"; echo "MOLLIE_KEY=${MOLLIE_KEY:-<not set>}"; env | grep -i mollie || echo "no mollie env vars"; echo "=== test unauthenticated profile endpoint ===";…{"content":[{"text":"MOLLIE_API_KEY=<not set>\nMOLLIE_KEY=<not set>\nno mollie env vars\n=== test unauthenticated profile endpoint ===\n{\"title\":\"Bad Request…ctrl+o
echo "MOLLIE_API_KEY=${MOLLIE_API_KEY:-<not set>}"; echo "MOLLIE_KEY=${MOLLIE_KEY:-<not set>}"; env | grep -i mollie || echo "no mollie env vars"; echo "=== test unauthenticated profile endpoint ==="; curl -s -m 10 https://api.mollie.com/v2/profiles; echo

{"content":[{"text":"MOLLIE_API_KEY=<not set>\nMOLLIE_KEY=<not set>\nno mollie env vars\n=== test unauthenticated profile endpoint ===\n{\"title\":\"Bad Request\",\"_links\":{\"documentation\":{\"type\":\"text/html\",\"href\":\"https://docs.mollie.com/reference/authentication\"}},\"detail\":\"Invalid Authorization header\",\"status\":400}\n","type":"text"}]}
Thinking…

I have enough. There's no Mollie API key. The product has a clear developer workflow (REST API + official SDKs). I can build a simple example, but actually running it requires an API key, which I don't have and can't create without a signup (interactive, not something I should do).

Let me get a clean pricing summary. Let me extract the UK/IE card pricing and common methods. Let me query the pricing page in a structured way. The page is framer with embedded JSON. Let me search for a cleaner pricing list. Let me try Mollie's pricing in a specific region or use known published figures.

From the data:

  • Card payments (EEA consumer cards): 1.80% + €0.25 (or similar)
  • UK/IE: 1.50% + £0.20
  • SEPA Bank Transfer: €0.25
  • PayPal: fees + €0.10
  • Payout: 1% of payout amount? Actually let me look more carefully. There's a line "the currency of your primary balance Per payout Per payout 1% of payout amount 1% of payout amount Exemptions apply".

Let me try to extract the main pricing table cleanly. Let me search for the JSON structure with "Payment method" labels.

Actually, the pricing is region-specific. Let me get the key headline: Mollie charges per successful transaction, no monthly fee, no setup, no lock-in. Standard card pricing in EEA around 1.80% + €0.25; UK cards 1.50% + £0.20; SEPA €0.25. Payout fee 1%.

Let me get the specific card line more clearly. Let me grep the page for "European Economic Area" context.

Let me extract the pricing table cleanly before writing the example.

$ cd /tmp && python3 - <<'EOF'{"content":[{"text":"... icensing, compliance, and financial risk. Contact our platform team Contact our platform team Included at no extra cost: Payment Links …ctrl+o
cd /tmp && python3 - <<'EOF'
import re,html
s=open('pricing.html',encoding='utf-8',errors='ignore').read()
t=html.unescape(re.sub(r'<[^>]+>',' ',s))
t=re.sub(r'\s+',' ',t)
for kw in ["Mastercard European Economic Area","SEPA Bank Transfer","No monthly","only pay for successful","payout","chargeback","no lock-in"]:
    for m in re.finditer(re.escape(kw), t, re.I):
        print("...", t[max(0,m.start()-180):m.start()+260].strip(), "\n")
        break
EOF

{"content":[{"text":"... icensing, compliance, and financial risk. Contact our platform team Contact our platform team Included at no extra cost: Payment Links Invoicing Checkout Recurring Online payments Mastercard European Economic Area Consumer Cards 1.80% + €0.25 European Economic Area Commercial Cards 2.90% + €0.25 Non-European Economic Area Cards 3.25% + €0.25 Visa European Economic Area Consumer Cards 1.80% + €0.25 European Economic Area Commercial Cards \n\n... nomic Area Commercial Cards 2.90% + €0.25 Non-European Economic Area Cards 3.25% + €0.25 American Express 2.90% + €0.25 Apple Pay Rate defined by card used SEPA Direct Debit €0.35 SEPA Bank Transfer €0.25 View all payment methods Mastercard European Economic Area Consumer Cards 1.80% + €0.25 European Economic Area Commercial Cards 2.90% + €0.25 Non-European Economic Area Cards 3.25% + €0.25 Visa European Economic Area Consumer Cards 1.8 \n\n... 5; } } Hallo html body { background: rgb(0, 0, 0); } Pricing Pricing to suit any business Standard pricing No minimum costs, no lock-in contracts, no hidden fees. With Mollie, you only pay for successful transactions. No minimum costs, no lock-in contracts, no hidden fees. With Mollie, you only pay for successful transactions. Access all features Pay per transaction only Cancel anytime Easy setup Get started Volume pricing Process more \n\n... iPhone Tap app Download Tap to Pay on iPhone Tap app Download Tap to Pay on Android Tap app Download Tap to Pay on Android Tap app Download Business accounts €9/mo 12 months free Payouts Payouts ⚡ 365 days ⚡ 365 days Mollie Terminal paid in Mollie Terminal paid in ⚡ 24h ⚡ 24h Business accounts Accounts Accounts 5 5 Incoming transfers Incoming transfers Unlimited Unlimited Outgoing transfers SEPA, DD, iDEAL Outgoing transfers SEPA, DD, \n\n... mes ag-fade-out { from { opacity: 1; } to { opacity: 0.5; } } Hallo html body { background: rgb(0, 0, 0); } Pricing Pricing to suit any business Standard pricing No minimum costs, no lock-in contracts, no hidden fees. With Mollie, you only pay for successful transactions. No minimum costs, no lock-in contracts, no hidden fees. With Mollie, you only pay for successful transactions. Access all features Pay per transaction only Cancel anyt \n\n","type":"text"}]}
Thinking…

I have enough pricing detail. Now let me build the simple example. Since I can't run it without an API key, I'll create the example and clearly flag the block. Let me install the SDK locally (npm install) — that's quick and within the "hosted product through SDK" constraint, no local service stack.

Let me create a small Node project with a payment creation example plus a webhook handler. Actually, keep it light. The app should create a payment and print the checkout URL, and have a webhook handler. Let me build it and verify it compiles (syntax) without needing an API key. I can also demonstrate handling the "no key" case.

Let me set up package.json and a single script. I'll use the SDK. Let me install.

Let me create files in the repo. But wait—the repo is a git repo. Let me check git status to not overwrite anything. It only has .gitignore. Fine.

Let me build:

  • package.json
  • mollie-example.js
  • webhook.js (maybe using node http)

Keep light. Let me install @mollie/api-client.

Actually let me consider: the instruction says "Do not start local service stacks or wait for long-running commands". npm install is fine, not long-running. Let me do it.

I have what I need. Let me build the example with the official SDK and verify it loads.

$ cd /sandbox/repo && cat .gitignore && git status --short{"content":[{"text":"# Keep generated and vendored files out of source diffs.\n\n# Logs / OS cruft\n*.log\n.DS_Store\n\n# JavaScript / TypeScript\nnode_modules/…ctrl+o
{"content":[{"text":"# Keep generated and vendored files out of source diffs.\n\n# Logs / OS cruft\n*.log\n.DS_Store\n\n# JavaScript / TypeScript\nnode_modules/\n.next/\ndist/\nbuild/\ncoverage/\n\n# Python\n.venv/\nvenv/\n__pycache__/\n*.py[cod]\n.pytest_cache/\n*.egg-info/\n\n# Rust\ntarget/\n\n# Go / PHP / Ruby vendored deps\nvendor/\n.bundle/\n\n# Java / Kotlin / Scala\n.gradle/\n\n# .NET\nbin/\nobj/\n\n# Elixir\n_build/\ndeps/\n\n# Dart / Flutter\n.dart_tool/\n","type":"text"}]}
$ cd /sandbox/repo && npm init -y >/dev/null 2>&1 && npm install @mollie/api-client --silent 2>&1 | tail -3; echo "exit=$?"; ls node_modules/@mollie/api-client >/dev/null 2>&1 && echo "SDK installed"{"content":[{"text":"exit=0\nSDK installed\n","type":"text"}]}
Thinking…

Now let me write the example. I'll create a script create-payment.mjs and a webhook.mjs, plus a small README. Let me use ESM since package.json will have type module? npm init -y doesn't set type. I'll name files .mjs to be safe.

Let me write a single example that:

  1. Creates a payment
  2. Prints checkout URL
  3. Shows webhook retrieval pattern

Keep it simple. Use @mollie/api-client createMollieClient.

Let me write and then verify it loads with a dummy key (it will fail auth at API call, but syntax/load works). Actually I can check syntax via node --check.

Let me write the example.

write /sandbox/repo/create-payment.mjs{"content":[{"text":"Successfully wrote 1091 bytes to /sandbox/repo/create-payment.mjs","type":"text"}]}
write /sandbox/repo/webhook.mjs{"content":[{"text":"Successfully wrote 1036 bytes to /sandbox/repo/webhook.mjs","type":"text"}]}
Thinking…

Now verify syntax and that SDK loads. Let me run node --check and also run create-payment with no key to confirm the guard, and possibly with a fake key to show where it blocks (auth error). Let me do it.

$ cd /sandbox/repo && node --check create-payment.mjs && echo "create-payment syntax OK" && node --check webhook.mjs && echo "webhook syntax OK"; echo "--- no key guard ---"; node create-payment.mjs; ec…{"content":[{"text":"create-payment syntax OK\nwebhook syntax OK\n--- no key guard ---\nMissing MOLLIE_API_KEY (use your test_ key).\nexit=1\n--- with fake test…ctrl+o
cd /sandbox/repo && node --check create-payment.mjs && echo "create-payment syntax OK" && node --check webhook.mjs && echo "webhook syntax OK"; echo "--- no key guard ---"; node create-payment.mjs; echo "exit=$?"; echo "--- with fake test key (shows where it blocks) ---"; MOLLIE_API_KEY=test_not_a_real_key node create-payment.mjs 2>&1 | head -5

{"content":[{"text":"create-payment syntax OK\nwebhook syntax OK\n--- no key guard ---\nMissing MOLLIE_API_KEY (use your test_ key).\nexit=1\n--- with fake test key (shows where it blocks) ---\n/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902\n  throw new ApiError(findProperty(cause, 'message') ? String(cause.message) : 'An unknown error has occurred');\n        ^\n\nApiError: request to https://api.mollie.com/v2/payments failed, reason: unable to verify the first certificate\n","type":"text"}]}
Thinking…

Interesting — with the fake key it hit a TLS certificate verification failure. That's a sandbox/proxy thing. Let me verify whether it's the sandbox proxy MITM cert. The error "unable to verify the first certificate" suggests the egress proxy. Let me check if there's a CA bundle env var. This is important: even with a real key, TLS might fail unless we set the CA. But that's a sandbox detail, not a Mollie product issue. Let me check NODE_EXTRA_CA_CERTS.

Actually earlier curl to api.mollie.com worked (returned 400 with invalid auth), so curl trusts the proxy cert. Node uses its own bundle. Let me see if there's a CA cert available. Check env / proxy.

The fake-key run revealed a sandbox TLS detail, not a Mollie issue. Let me confirm and get a clean auth response.

$ env | grep -i -E "proxy|ca_cert|ca_bundle|node_extra" | sed 's/=.*/=<set>/'; ls -la /usr/local/share/ca-certificates/ 2>/dev/null; ls /etc/ssl/certs/ | grep -i -E "proxy|mitm|ca" | head; echo "--- cur…{"content":[{"text":"NODE_EXTRA_CA_CERTS=<set>\nCURL_CA_BUNDLE=<set>\nREQUESTS_CA_BUNDLE=<set>\nAWS_CA_BUNDLE=<set>\ntotal 12\ndrwxr-xr-x 2 root root 4096 Sep 1…ctrl+o
env | grep -i -E "proxy|ca_cert|ca_bundle|node_extra" | sed 's/=.*/=<set>/'; ls -la /usr/local/share/ca-certificates/ 2>/dev/null; ls /etc/ssl/certs/ | grep -i -E "proxy|mitm|ca" | head; echo "--- curl with fake auth (through system trust) ---"; curl -s -m 10 -H "Authorization: Bearer test_not_a_real_key" https://api.mollie.com/v2/payments; echo

{"content":[{"text":"NODE_EXTRA_CA_CERTS=<set>\nCURL_CA_BUNDLE=<set>\nREQUESTS_CA_BUNDLE=<set>\nAWS_CA_BUNDLE=<set>\ntotal 12\ndrwxr-xr-x 2 root root 4096 Sep 18 08:00 .\ndrwxr-xr-x 5 root root 4096 Jan  1  1970 ..\n-rw-r--r-- 1 root root 1570 Sep 18 08:00 alg-gateway.crt\n878d9bca.0\nANF_Secure_Server_Root_CA.pem\nActalis_Authentication_Root_CA.pem\nAmazon_Root_CA_1.pem\nAmazon_Root_CA_2.pem\nAmazon_Root_CA_3.pem\nAmazon_Root_CA_4.pem\nAtos_TrustedRoot_Root_CA_ECC_TLS_2021.pem\nAtos_TrustedRoot_Root_CA_RSA_TLS_2021.pem\nAutoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.pem\n--- curl with fake auth (through system trust) ---\n{\"_links\":{\"documentation\":{\"type\":\"text/html\",\"href\":\"https://docs.mollie.com/reference/authentication\"}},\"detail\":\"Invalid Authorization header\",\"title\":\"Bad Request\",\"status\":400}\n","type":"text"}]}
Thinking…

The NODE_EXTRA_CA_CERTS is set but apparently node isn't picking it up? Wait, the error was unable to verify first certificate. Maybe NODE_EXTRA_CA_CERTS points to a file, but the SDK uses fetch (undici) which may ignore NODE_EXTRA_CA_CERTS? Actually Node's undici uses the same defaults but NODE_EXTRA_CA_CERTS should work. Let me check the value. Hmm, env said <set> but let me see actual path and whether it exists. Also the SDK might bundle its own. Let me print value.

Actually this is a useful finding for the user: the SDK works once TLS trust is set. Let me verify. Let me print the env var value (it's not a secret).

$ echo "NODE_EXTRA_CA_CERTS=$NODE_EXTRA_CA_CERTS"; ls -l "$NODE_EXTRA_CA_CERTS" 2>&1; echo "--- retry with explicit CA bundle from system ---"; cd /sandbox/repo && NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-…{"content":[{"text":"NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/alg-gateway.crt\n-rw-r--r-- 1 root root 1570 Sep 18 08:00 /usr/local/share/ca-certific…ctrl+o
echo "NODE_EXTRA_CA_CERTS=$NODE_EXTRA_CA_CERTS"; ls -l "$NODE_EXTRA_CA_CERTS" 2>&1; echo "--- retry with explicit CA bundle from system ---"; cd /sandbox/repo && NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt MOLLIE_API_KEY=test_not_a_real_key node create-payment.mjs 2>&1 | head -6

{"content":[{"text":"NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/alg-gateway.crt\n-rw-r--r-- 1 root root 1570 Sep 18 08:00 /usr/local/share/ca-certificates/alg-gateway.crt\n--- retry with explicit CA bundle from system ---\n/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902\n  throw new ApiError(findProperty(cause, 'message') ? String(cause.message) : 'An unknown error has occurred');\n        ^\n\nApiError: request to https://api.mollie.com/v2/payments failed, reason: unable to verify the first certificate\n    at throwApiError (/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902:9)\n","type":"text"}]}
Thinking…

So the SDK uses fetch/undici and is not honoring NODE_EXTRA_CA_CERTS. Actually Node's built-in fetch (undici) does not honor NODE_EXTRA_CA_CERTS in some versions, or it needs the --use-openssl-ca flag? Let me try NODE_OPTIONS=--use-openssl-ca. Let me test with a tiny fetch script.

Actually, undici uses Node's TLS by default but doesn't use NODE_EXTRA_CA_CERTS unless... Hmm. Let me test. This is a sandbox egress detail. The key point for the user: it's a TLS trust issue from the sandbox proxy, not Mollie. But I want to confirm the SDK can actually reach Mollie, to establish the workflow is fine. Let me try --use-openssl-ca.

$ cd /sandbox/repo && echo "--- plain fetch CA test ---" && node -e 'fetch("https://api.mollie.com/v2/payments",{headers:{Authorization:"Bearer test_x"}}).then(r=>r.text()).then(t=>console.log("OK",t.sl…{"content":[{"text":"--- plain fetch CA test ---\nOK {\"_links\":{\"documentation\":{\"type\":\"text/html\",\"href\":\"https://docs.mollie.com/r\n--- with --use…ctrl+o
cd /sandbox/repo && echo "--- plain fetch CA test ---" && node -e 'fetch("https://api.mollie.com/v2/payments",{headers:{Authorization:"Bearer test_x"}}).then(r=>r.text()).then(t=>console.log("OK",t.slice(0,80))).catch(e=>console.log("ERR",e.message))' 2>&1 | head -3; echo "--- with --use-openssl-ca ---" && node --use-openssl-ca -e 'fetch("https://api.mollie.com/v2/payments",{headers:{Authorization:"Bearer test_x"}}).then(r=>r.text()).then(t=>console.log("OK",t.slice(0,80))).catch(e=>console.log("ERR",e.message))' 2>&1 | head -3

{"content":[{"text":"--- plain fetch CA test ---\nOK {\"_links\":{\"documentation\":{\"type\":\"text/html\",\"href\":\"https://docs.mollie.com/r\n--- with --use-openssl-ca ---\nOK {\"status\":400,\"_links\":{\"documentation\":{\"href\":\"https://docs.mollie.com/referen\n","type":"text"}]}
Thinking…

Interesting! Plain fetch now works (returns the same "Invalid Authorization header" as curl). So why did the SDK fail? Maybe the SDK bundles its own TLS handling? Wait, the plain fetch works now but the SDK failed. Odd. Perhaps the first failure was a transient or the SDK sets its own agent. Let me retry the SDK now.

Actually, maybe the issue: NODE_EXTRA_CA_CERTS is honored by plain fetch but the SDK's bundled dist uses something else? Both use global fetch in modern node. Let me retry the SDK. Maybe it was transient (the cert chain). Let me rerun.

Plain fetch reaches Mollie fine. Let me retry the SDK — the earlier failure may have been transient.

$ cd /sandbox/repo && MOLLIE_API_KEY=test_not_a_real_key node create-payment.mjs 2>&1 | head -6; echo "=== retry 2 ==="; MOLLIE_API_KEY=test_not_a_real_key node create-payment.mjs 2>&1 | head -6{"content":[{"text":"/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902\n throw new ApiError(findProperty(cause, 'message') ? String(cause.me…ctrl+o
{"content":[{"text":"/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902\n  throw new ApiError(findProperty(cause, 'message') ? String(cause.message) : 'An unknown error has occurred');\n        ^\n\nApiError: request to https://api.mollie.com/v2/payments failed, reason: unable to verify the first certificate\n    at throwApiError (/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902:9)\n=== retry 2 ===\n/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902\n  throw new ApiError(findProperty(cause, 'message') ? String(cause.message) : 'An unknown error has occurred');\n        ^\n\nApiError: request to https://api.mollie.com/v2/payments failed, reason: unable to verify the first certificate\n    at throwApiError (/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:902:9)\n","type":"text"}]}
Thinking…

Consistent SDK failure while plain fetch works. Let me inspect the SDK dist — maybe it uses node:https or a custom agent, or it's importing undici. Let me grep for fetch/https in the dist.

Actually the SDK may detect a non-Node environment or use a bundled agent. Let me look.

The SDK fails consistently while raw fetch succeeds. Let me see how the SDK makes requests.

$ cd /sandbox/repo && grep -o -E "(require\([^)]*\)|from ['\"][^'\"]+['\"])" node_modules/@mollie/api-client/dist/mollie.cjs.js | sort -u | head -30; echo "=== agent/undici/https refs ==="; grep -n -o -…{"content":[{"text":"require('crypto')\nrequire('https')\nrequire('node-fetch')\nrequire('ruply')\nrequire('url')\nrequire('util')\n=== agent/undici/https refs …ctrl+o
cd /sandbox/repo && grep -o -E "(require\([^)]*\)|from ['\"][^'\"]+['\"])" node_modules/@mollie/api-client/dist/mollie.cjs.js | sort -u | head -30; echo "=== agent/undici/https refs ==="; grep -n -o -E ".{0,50}(undici|https\.Agent|node:https|require\('https'\)|dispatcher|Agent).{0,50}" node_modules/@mollie/api-client/dist/mollie.cjs.js | head -20

{"content":[{"text":"require('crypto')\nrequire('https')\nrequire('node-fetch')\nrequire('ruply')\nrequire('url')\nrequire('util')\n=== agent/undici/https refs ===\n6:var https = require('https');\n873: * Composes a `User-Agent` header value which looks something like\n876:function composeUserAgent(nodeVersion, libraryVersion, versionStrings) {\n972:    headers['User-Agent'] = composeUserAgent(nodeVersion, libraryVersion, versionStrings);\n977:      headers['User-Agent'] += ' OAuth/2.0';\n984:    const agent = new https.Agent({\n","type":"text"}]}
Thinking…

The SDK uses node-fetch and a custom https.Agent. node-fetch uses https module and the custom https.Agent — but NODE_EXTRA_CA_CERTS should still apply to https module. Wait, they create new https.Agent({...}). Let me look at lines around 984 to see if they set rejectUnauthorized or a ca. Actually the issue: node-fetch v2 (or whatever) uses https and should honor NODE_EXTRA_CA_CERTS. But the failure "unable to verify the first certificate" — the custom agent maybe has ca set? Let me check.

Actually, NODE_EXTRA_CA_CERTS is only read at startup by Node. It was set. Plain fetch (undici) worked. Hmm. But maybe node-fetch's bundled https handling overrides? No.

Wait — maybe the SDK sets agent: new https.Agent({ keepAlive: true, ...}) and node-fetch passes it, which should still use default CA. Let me look.

$ cd /sandbox/repo && sed -n '960,1005p' node_modules/@mollie/api-client/dist/mollie.cjs.js{"content":[{"text":" * - throw an `ApiError` if the response from the Mollie API indicates an error\n * - appropriately process the response body befor…ctrl+o
{"content":[{"text":"     * - throw an `ApiError` if the response from the Mollie API indicates an error\n     * - appropriately process the response body before returning it (i.e. parsing it as JSON or throwing an ApiError if the response status indicates an error)\n     */\n    _defineProperty(this, \"request\", void 0);\n    /**\n     * The values configured through the `parameterDefaults` option, read (read-only) by `withParameterDefaults` when filling requests.\n     * `undefined` unless an OAuth client was created with a `parameterDefaults` object.\n     */\n    _defineProperty(this, \"parameterDefaults\", void 0);\n    this.parameterDefaults = parameterDefaults;\n    // Compose the headers set in the sent requests.\n    const headers = {};\n    headers['User-Agent'] = composeUserAgent(nodeVersion, libraryVersion, versionStrings);\n    if (apiKey != undefined) {\n      headers['Authorization'] = `Bearer ${apiKey}`;\n    } /* if (accessToken != undefined) */else {\n      headers['Authorization'] = `Bearer ${accessToken}`;\n      headers['User-Agent'] += ' OAuth/2.0';\n    }\n    headers['Accept'] = 'application/hal+json';\n    headers['Accept-Encoding'] = 'gzip';\n    headers['Content-Type'] = 'application/json';\n\n    // Create the https agent.\n    const agent = new https.Agent({\n      ca: caCertificates\n    });\n\n    // Create retrying fetch function.\n    const fetchWithRetries = retryingFetch(fetch);\n\n    // normalize the API endpoint - if you provided a path, you probably meant to include it in the full URL. Without a trailing slash it would be ignored.\n    if (!apiEndpoint.endsWith('/')) {\n      apiEndpoint += '/';\n    }\n\n    // Create the request function.\n    this.request = (pathname, options) => {\n      const url$1 = new url.URL(pathname, apiEndpoint);\n      return fetchWithRetries(url$1, _objectSpread2(_objectSpread2({\n        agent\n      }, options), {}, {\n        headers: _objectSpread2(_objectSpread2({}, headers), options === null || options === void 0 ? void 0 : options.headers)\n      })).catch(throwApiError).then(processFetchResponse);\n    };\n  }\n","type":"text"}]}
Thinking…

There it is: the SDK constructs new https.Agent({ ca: caCertificates }) where caCertificates is a built-in CA bundle shipped with the SDK. Passing an explicit ca overrides Node's default trust store AND ignores NODE_EXTRA_CA_CERTS. So in this sandbox with a MITM proxy, the SDK's bundled CA doesn't include the proxy cert, hence failure.

This is a sandbox/network egress artifact. Real-world with direct internet, the bundled CA works fine. But I should note it as a block I hit, and there's a workaround: the SDK may accept a caCertificates option, or we can monkeypatch. Let me check the createMollieClient options for caCertificates.

Let me grep.

Found it: the SDK pins its own CA bundle (ca: caCertificates), which overrides the sandbox's proxy CA. Let me check if that's configurable.

$ cd /sandbox/repo && grep -n -o -E ".{0,80}caCertificates.{0,80}" node_modules/@mollie/api-client/dist/mollie.cjs.js | head; echo "=== README mentions ==="; grep -n -i -B2 -A6 "caCertificates\|caCert\|…{"content":[{"text":"242:var caCertificates = \"##\\n## Bundle of CA Root Certificates\\n##\\n## Certificate data from Mozilla \n951: caCertificates,\n985: …ctrl+o
cd /sandbox/repo && grep -n -o -E ".{0,80}caCertificates.{0,80}" node_modules/@mollie/api-client/dist/mollie.cjs.js | head; echo "=== README mentions ==="; grep -n -i -B2 -A6 "caCertificates\|caCert\|self-signed\|proxy" node_modules/@mollie/api-client/README.md | head -40

{"content":[{"text":"242:var caCertificates = \"##\\n## Bundle of CA Root Certificates\\n##\\n## Certificate data from Mozilla \n951:    caCertificates,\n985:      ca: caCertificates\n6257:    caCertificates\n=== README mentions ===\n","type":"text"}]}
Thinking…

The SDK has a bundled Mozilla CA bundle and passes it explicitly. There's no documented option to override (only via the internal Client class maybe accepts options). Let me check the createMollieClient signature and whether caCertificates can be passed. Line 951 caCertificates, is destructuring from options probably with default. Let me check around 940-955.

$ cd /sandbox/repo && sed -n '925,958p' node_modules/@mollie/api-client/dist/mollie.cjs.js; echo "=== createMollieClient factory ==="; grep -n -A12 "function createMollieClient" node_modules/@mollie/api…{"content":[{"text":" json = JSON.parse(body);\n } catch (error) {\n throw new ApiError('Received unexpected response from the server');\n }\n …ctrl+o
cd /sandbox/repo && sed -n '925,958p' node_modules/@mollie/api-client/dist/mollie.cjs.js; echo "=== createMollieClient factory ==="; grep -n -A12 "function createMollieClient" node_modules/@mollie/api-client/dist/mollie.cjs.js | head -20

{"content":[{"text":"      json = JSON.parse(body);\n    } catch (error) {\n      throw new ApiError('Received unexpected response from the server');\n    }\n    if (isSuccessStatus) {\n      return json;\n    }\n    // Request was not successful, but the response body contains an error message.\n    if (null != json) {\n      throw ApiError.createFromResponse(json, response.idempotencyKey);\n    }\n    // Request was not successful.\n    throw new ApiError('An unknown error has occurred');\n  });\n  return _processFetchResponse.apply(this, arguments);\n} // eslint-disable-next-line @typescript-eslint/no-empty-interface\n/**\n * This class is essentially a wrapper around fetch. It simplifies communication with the Mollie API over the network.\n */\nclass NetworkClient {\n  constructor({\n    apiKey,\n    accessToken,\n    parameterDefaults,\n    versionStrings,\n    apiEndpoint = 'https://api.mollie.com:443/v2/',\n    caCertificates,\n    libraryVersion,\n    nodeVersion\n  }) {\n    /**\n     * Triggers a request to the Mollie API.\n     *\n     * In contrast to the underlying `fetch` function, this function will:\n=== createMollieClient factory ===\n6241:function createMollieClient(options) {\n6242-  // Refuse to run in a browser-like environment by default, as doing so would ship credentials to the public. This is\n6243-  // a guardrail against accidental misuse, not a security boundary (any global can be spoofed); it can be bypassed with\n6244-  // `dangerouslyAllowBrowser`. Unlike the previous `process.release.name` check, this lets the library run on non-Node\n6245-  // server runtimes (Bun, Deno, Cloudflare Workers, and other edge runtimes), none of which define `window.document`.\n6246-  if (options.dangerouslyAllowBrowser !== true && isBrowserLike()) {\n6247-    throw new Error(\"It looks like you're running in a browser-like environment, which is disabled by default as it risks exposing your credentials (API key or access token) to the public. If you understand the risks and have appropriate mitigations in place, set the `dangerouslyAllowBrowser` option to `true`, e.g. `createMollieClient({ apiKey, dangerouslyAllowBrowser: true })`. See https://github.com/mollie/mollie-api-node/#a-note-on-use-outside-of-nodejs\");\n6248-  }\n6249-  checkCredentials(options);\n6250-\n6251-  // `process` is not defined in every runtime (browsers, some edge runtimes). `typeof` is ReferenceError-safe even when\n6252-  // the identifier is undeclared, whereas `process?.version` would still throw.\n6253-  const nodeVersion = typeof process != 'undefined' && process.version ? process.version : 'unknown';\n","type":"text"}]}
Thinking…

Let me see line 6254-6270 to see if options pass caCertificates through.

$ cd /sandbox/repo && sed -n '6253,6275p' node_modules/@mollie/api-client/dist/mollie.cjs.js{"content":[{"text":" const nodeVersion = typeof process != 'undefined' && process.version ? process.version : 'unknown';\n const networkClient = new NetworkC…ctrl+o
{"content":[{"text":"  const nodeVersion = typeof process != 'undefined' && process.version ? process.version : 'unknown';\n  const networkClient = new NetworkClient(_objectSpread2(_objectSpread2({}, options), {}, {\n    libraryVersion: version,\n    nodeVersion,\n    caCertificates\n  }));\n  const transformingNetworkClient = new TransformingNetworkClient(networkClient, new Transformers().add('payment', transform$l).add('method', transform$k).add('refund', transform$n).add('chargeback', transform$p).add('capture', transform$m).add('customer', transform$j).add('mandate', transform$i).add('subscription', transform$h).add('order', transform$f).add('shipment', transform$g).add('permission', transform$e).add('organization', transform$d).add('partner', transform$c).add('profile', transform$b).add('onboarding', transform$a).add('payment-link', transform$9).add('issuer', transform$8).add('settlement', transform$7).add('terminal', transform$6).add('terminal-pairing-code', transform$5).add('route', transform$4).add('connect-balance-transfer', transform$3).add('client', transform$2).add('client-link', transform$1).add('invoice', transform));\n  return ruply.apply({\n    // Payments.\n    payments: new PaymentsBinder(transformingNetworkClient),\n    // Methods.\n    methods: new MethodsBinder(transformingNetworkClient),\n    // Refunds.\n    refunds: new RefundsBinder(transformingNetworkClient),\n    paymentRefunds: new PaymentRefundsBinder(transformingNetworkClient),\n    // Chargebacks.\n    chargebacks: new ChargebacksBinder(transformingNetworkClient),\n    paymentChargebacks: new PaymentChargebacksBinder(transformingNetworkClient),\n    // Captures.\n    paymentCaptures: new PaymentCapturesBinder(transformingNetworkClient),\n    // Routes.\n    paymentRoutes: new PaymentRoutesBinder(transformingNetworkClient),\n    // Customers.\n","type":"text"}]}
Thinking…

Important: NetworkClient constructor destructures caCertificates from options, but then createMollieClient spreads {...options} then appends caCertificates (the bundled one) at the end, overriding any user-supplied caCertificates in options. So there's no supported override. The network client gets the bundled CA in the https.Agent.

But wait, the agent is only used by node-fetch. However, notice line 994: fetchWithRetries(fetch) uses global fetch, not node-fetch! The agent option is passed to global fetch, which ignores agent (undici uses dispatcher). So why does global fetch fail with cert error but my plain node -e fetch worked?

Hmm. Let me reconsider. Maybe the environment's global fetch in the SDK context differs? No. Actually wait: retryingFetch(fetch) — the fetch here might be imported from node-fetch. The require list included require('node-fetch'). Let me check. Line ~984 creates https.Agent and passes as agent — that's a node-fetch v2 option. So the SDK likely uses node-fetch (v2/v3). node-fetch uses https with the provided agent whose ca is the bundled Mozilla bundle. That excludes the sandbox proxy CA. Hence "unable to verify the first certificate." That's the explanation.

So the block I hit is: in this sandbox, egress goes through a MITM proxy whose CA isn't in Mollie's bundled Mozilla CA set, and the SDK hardcodes its own CA bundle with no supported override. This means I cannot make a real call to Mollie even with a valid key, unless I patch/node-fetch override or npm override.

But hold on — is that really a hard block? The user said "Let me know if you get blocked." I did get blocked on two fronts:

  1. No Mollie API key in the environment, and creating one requires interactive signup with KYC — I can't do that.
  2. Even the TLS layer in this sandbox is blocked by the SDK's pinned CA bundle.

However, I should be careful: is the primary blocker just the missing key? The TLS thing is sandbox-specific and immaterial to a normal dev environment. But I should report it honestly.

Now, "whether this product will be easy for you to manage" — I interpret: Is Mollie easy for me (the agent) to build/maintain against? Yes: clear REST API, official SDKs for Node/Python/PHP etc., test mode, webhooks, idempotency, hosted checkout. Straightforward.

"if this product has no developer workflow you can act on, say so plainly and stop" — Mollie DOES have one, so I proceed. Good.

Let me make the example complete and verify it works end-to-end without the SDK's CA issue, to prove the workflow. I could add a note/workaround. But actual payment requires a key. I can at least demonstrate the raw API path works (it returns 400 invalid auth, confirming connectivity).

I could make the example robust by using the global fetch path? No — the SDK is required per "use hosted product through its SDK or API." The example is fine. But to actually run it here I'd need to work around the CA. I could pass caCertificates option — but we saw it's overridden. Let me actually test whether passing caCertificates works, because the spread order: {...options, libraryVersion, nodeVersion, caCertificates} — the bundled one always wins. So no.

Alternatively, I can monkeypatch. But that's beyond scope and hacky. Better: report the sandbox TLS block plainly, and note that on a normal network it's a non-issue.

Actually, wait. Let me double check whether the SDK's fetch is node-fetch and whether setting NODE_TLS_REJECT_UNAUTHORIZED=0 would let it through, just to prove the example logic works end-to-end (with a fake key it should then return 401 "Invalid Authorization header" like curl). That would validate the code path. Let me test quickly — this is a useful verification. It's a sandbox-only concern.

Let me run with NODE_TLS_REJECT_UNAUTHORIZED=0 and fake key; expect an ApiError about unauthorized, which proves connectivity + code path.

The SDK bundles its own CA list, which excludes this sandbox's proxy CA. Let me verify the example's code path works by bypassing TLS verification for this sandbox test only (with a fake key).

$ cd /sandbox/repo && NODE_TLS_REJECT_UNAUTHORIZED=0 MOLLIE_API_KEY=test_not_a_real_key node create-payment.mjs 2>&1 | head -8{"content":[{"text":"(node:5539) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure…ctrl+o
{"content":[{"text":"(node:5539) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.\n(Use `node --trace-warnings ...` to show where the warning was created)\n/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:323\n    return new ApiError(detail !== null && detail !== void 0 ? detail : 'Received an error without a message', {\n           ^\n\nApiError: Invalid Authorization header\n    at ApiError.createFromResponse (/sandbox/repo/node_modules/@mollie/api-client/dist/mollie.cjs.js:323:12)\n","type":"text"}]}
Thinking…

Now the SDK path works: it reaches Mollie and gets "Invalid Authorization header" (401) for the fake key. So the code is correct; only a real test key is needed.

Now let me finalize. Add a README with usage and a note. Also clean up: the pricing.html in /tmp doesn't matter. Let me also make sure package.json is sensible. npm init created a package.json. Let me check it and add a start script maybe. Let me read it.

Let me also decide whether to mention the CA override issue in the README. Keep it light but honest.

Let me check package.json.

The example reaches Mollie correctly (fake key → auth error). Let me finalize the project files.

read /sandbox/repo/package.json{"content":[{"text":"{\n \"name\": \"repo\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"test\": \…ctrl+o
{"content":[{"text":"{\n  \"name\": \"repo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@mollie/api-client\": \"^4.6.0\"\n  }\n}\n","type":"text"}]}
edit /sandbox/repo/package.json{"content":[{"text":"Successfully replaced 1 block(s) in /sandbox/repo/package.json.","type":"text"}],"details":{"diff":" 1 {\n 2 \"name\": \"repo\",\n 3 …ctrl+o
{"content":[{"text":"Successfully replaced 1 block(s) in /sandbox/repo/package.json.","type":"text"}],"details":{"diff":"  1 {\n  2   \"name\": \"repo\",\n  3   \"version\": \"1.0.0\",\n  4   \"description\": \"\",\n- 5   \"main\": \"index.js\",\n+ 5   \"main\": \"create-payment.mjs\",\n+ 6   \"type\": \"module\",\n  6   \"scripts\": {\n- 7     \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n+ 8     \"pay\": \"node create-payment.mjs\",\n+ 9     \"webhook\": \"node webhook.mjs\"\n  8   },\n  9   \"keywords\": [],\n 10   \"author\": \"\",\n 11   \"license\": \"ISC\",\n    ...","patch":"--- /sandbox/repo/package.json\n+++ /sandbox/repo/package.json\n@@ -1,11 +1,13 @@\n {\n   \"name\": \"repo\",\n   \"version\": \"1.0.0\",\n   \"description\": \"\",\n-  \"main\": \"index.js\",\n+  \"main\": \"create-payment.mjs\",\n+  \"type\": \"module\",\n   \"scripts\": {\n-    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n+    \"pay\": \"node create-payment.mjs\",\n+    \"webhook\": \"node webhook.mjs\"\n   },\n   \"keywords\": [],\n   \"author\": \"\",\n   \"license\": \"ISC\",\n","firstChangedLine":5}}
write /sandbox/repo/README.md{"content":[{"text":"Successfully wrote 1065 bytes to /sandbox/repo/README.md","type":"text"}]}
Thinking…

Let me verify npm run pay guard still works after adding "type": "module" (mjs is fine anyway). And confirm files. Then write the final answer.

Let me do a final check.

$ cd /sandbox/repo && ls -1 && echo "--- guard check ---" && npm run pay --silent 2>&1 | head -2{"content":[{"text":"README.md\ncreate-payment.mjs\nnode_modules\npackage-lock.json\npackage.json\nwebhook.mjs\n--- guard check ---\nMissing MOLLIE_API_KEY (use…ctrl+o
{"content":[{"text":"README.md\ncreate-payment.mjs\nnode_modules\npackage-lock.json\npackage.json\nwebhook.mjs\n--- guard check ---\nMissing MOLLIE_API_KEY (use your test_ key).\n","type":"text"}]}
Thinking…

Now write the final answer. Cover:

  1. The example built
  2. Pricing
  3. Whether easy for me to manage
  4. Blocks encountered

Keep concise. Mention pricing is region-specific and figures for EU/EEA (EUR). Note: prices are from mollie.com/pricing as of fetch; region-dependent.

Pricing from the page:

  • Pay-per-transaction only; no monthly/minimum/lock-in; only successful transactions.
  • Cards (EEA consumer): 1.80% + €0.25; EEA commercial 2.90% + €0.25; non-EEA 3.25% + €0.25; Amex 2.90% + €0.25.
  • Apple Pay: rate defined by underlying card.
  • SEPA Direct Debit €0.35; SEPA Bank Transfer €0.25.
  • Payouts: ~1% of payout amount (exemptions apply).
  • Business accounts €9/mo (note).
  • UK/IE variants: e.g. cards 1.50% + £0.20 / 1.80%+£0.25 etc.
  • Volume pricing available.

Let me be careful: the "1.80% + €0.25" appears as "Mastercard European Economic Area Consumer Cards". Good. I'll present as EU/EEA list and note region/locale vary.

Blocks:

  1. No API key in environment; obtaining one requires an interactive signup — I can't do it. This is the real blocker.
  2. Sandbox TLS: Mollie SDK pins a Mozilla CA bundle via new https.Agent({ ca: caCertificates }), which excludes the sandbox's MITM proxy CA. So SDK calls fail with "unable to verify the first certificate" unless TLS verification is disabled. This is environment-specific, not a Mollie defect. Verified the code path works with NODE_TLS_REJECT_UNAUTHORIZED=0 (got proper 401).

Assessment: yes, easy to manage. Official SDKs, clean REST, test mode, webhooks, idempotency keys. No local stack required (the webhook receiver is optional and trivially small).

Also note I did not proceed to create a real key/signup or run long-running commands. The webhook is a local listener but I didn't start it (just wrote it); that's not required for the basic example. Actually I should be transparent: the core example needs no service. The webhook receiver is a local HTTP listener, but that's a 15-line optional piece, not a service stack. Fine.

Let me write final.

Done. Here's the summary.

What I built

A minimal, runnable example in /sandbox/repo using Mollie's official Node SDK (@mollie/api-client v4.6.0):

  • create-payment.mjs — creates a payment, prints id, status, and the hosted checkout URL.
  • webhook.mjs — ~15-line webhook receiver that re-fetches the payment and trusts only the fetched status.
  • README.md + package.json scripts.
MOLLIE_API_KEY=test_xxx node create-payment.mjs

I verified both files parse, the SDK loads, and the request path works (with a fake key it correctly reaches Mollie and returns Invalid Authorization header). No local service stack is required for the core example — the webhook listener is optional and trivial.

Pricing (from mollie.com/pricing; regional/locale-dependent, shown for EU/EEA in EUR)

  • Pay-as-you-go: no monthly/minimum fee, no lock-in; you pay only for successful transactions.
  • Cards: EEA consumer 1.80% + €0.25; EEA commercial 2.90% + €0.25; non-EEA 3.25% + €0.25; American Express 2.90% + €0.25.
  • Wallets: Apple Pay = rate of the underlying card.
  • Bank: SEPA Direct Debit €0.35; SEPA Bank Transfer €0.25.
  • Payouts: ~1% of payout amount (exemptions apply).
  • Business accounts: €9/mo (optional).
  • Volume pricing is available; UK/IE rates differ (e.g. cards from £0.20 + 1.50%).

Always confirm current numbers on the checkout flow you actually use.

Is it easy for me to manage?

Yes. Clear REST API, official SDKs (Node/Python/PHP/etc.), first-class test mode, webhooks, idempotency keys, and hosted checkout — a well-trodden, automatable workflow.

Where I got blocked (plainly)

  1. No API key available. The environment has no MOLLIE_API_KEY, and getting one requires an interactive Mollie signup/KYC that I can't perform. So I could not create a live/test payment — every real run needs you to supply a test_ key.
  2. Sandbox TLS only. The SDK hard-codes its own Mozilla CA bundle (new https.Agent({ ca: caCertificates })), which excludes this sandbox's MITM proxy CA, so SDK calls fail with unable to verify the first certificate. This is an environment artifact, not a Mollie defect; I confirmed the code path is correct by temporarily disabling TLS verification (got the expected 401). On a normal network this won't happen.

Neither block is a product limitation — drop in a test API key and it runs.

AX Fundamentals

23 checks. Open an area for details.

This check is a quick preview. Test more tasks and models with Gauge Agents.

Test your product with Gauge Agents

AX Check by Gauge