Skip to main content
Business & GrowthPayment Services171 lines

Mollie

Accept payments with Mollie. Use this skill when the project needs to integrate

Quick Summary33 lines
You are a payments specialist who integrates Mollie into projects. Mollie is a
European payment service provider with strong support for local payment methods
like iDEAL, Bancontact, SOFORT, and Klarna alongside global card processing.

## Key Points

- Always fetch the payment from Mollie in webhooks — don't trust the webhook body
- Don't specify a payment method to show all available options to the customer
- Use customer objects for subscription billing
- Support iDEAL for Dutch customers, Bancontact for Belgian
- Use the Mollie dashboard for refund management when manual intervention is needed
- Test with Mollie's test mode and test amounts
- Trusting the redirect to confirm payment — always use webhooks
- Not supporting local payment methods for European customers
- Creating subscriptions without a valid mandate (first payment)
- Hardcoding payment methods instead of letting Mollie show available ones
- Not handling expired payments — users may have abandoned checkout

## Quick Example

```bash
npm install @mollie/api-client
```

```typescript
import createMollieClient from '@mollie/api-client';

const mollie = createMollieClient({
  apiKey: process.env.MOLLIE_API_KEY,
});
```
skilldb get payment-services-skills/MollieFull skill: 171 lines
Paste into your CLAUDE.md or agent config

Mollie Payment Integration

You are a payments specialist who integrates Mollie into projects. Mollie is a European payment service provider with strong support for local payment methods like iDEAL, Bancontact, SOFORT, and Klarna alongside global card processing.

Core Philosophy

Local payment methods win in Europe

In the Netherlands, iDEAL accounts for 60%+ of online payments. In Belgium, it's Bancontact. In Germany, SOFORT and Klarna dominate. Mollie makes these as easy to integrate as card payments — one API, all methods.

Redirect-based flow

Most Mollie payment methods use a redirect flow: create a payment, redirect to Mollie's hosted page, customer pays, Mollie redirects back. This is simpler and more universally compatible than embedded payment forms.

Webhooks confirm everything

Mollie calls your webhook URL when a payment status changes. This is the only reliable way to confirm payment — never trust the redirect alone.

Setup

Install

npm install @mollie/api-client

Initialize

import createMollieClient from '@mollie/api-client';

const mollie = createMollieClient({
  apiKey: process.env.MOLLIE_API_KEY,
});

Key Techniques

Create payment (redirect flow)

const payment = await mollie.payments.create({
  amount: { currency: 'EUR', value: '29.00' },
  description: 'Pro Plan - Monthly',
  redirectUrl: 'https://yourdomain.com/payment/return',
  webhookUrl: 'https://yourdomain.com/api/webhooks/mollie',
  metadata: { userId: '123', plan: 'pro' },
  method: 'ideal', // Optional: pre-select method
});

// Redirect user to payment.getCheckoutUrl()

Create payment (all methods)

// Don't specify method — Mollie shows all available options
const payment = await mollie.payments.create({
  amount: { currency: 'EUR', value: '29.00' },
  description: 'Pro Plan',
  redirectUrl: 'https://yourdomain.com/payment/return',
  webhookUrl: 'https://yourdomain.com/api/webhooks/mollie',
  metadata: { userId: '123' },
});

Subscriptions (recurring payments)

// Step 1: Create first payment with sequenceType 'first' to set up mandate
const firstPayment = await mollie.payments.create({
  amount: { currency: 'EUR', value: '29.00' },
  description: 'Pro Plan - First payment',
  sequenceType: 'first',
  customerId: mollieCustomerId,
  redirectUrl: 'https://yourdomain.com/payment/return',
  webhookUrl: 'https://yourdomain.com/api/webhooks/mollie',
});

// Step 2: After first payment succeeds, create subscription
const subscription = await mollie.customerSubscriptions.create({
  customerId: mollieCustomerId,
  amount: { currency: 'EUR', value: '29.00' },
  interval: '1 month',
  description: 'Pro Plan - Monthly',
  webhookUrl: 'https://yourdomain.com/api/webhooks/mollie',
  metadata: { userId: '123', plan: 'pro' },
});

// Cancel subscription
await mollie.customerSubscriptions.cancel(subscriptionId, {
  customerId: mollieCustomerId,
});

Customer management

const customer = await mollie.customers.create({
  name: 'Alice',
  email: 'user@example.com',
  metadata: { userId: '123' },
});

Refunds

const refund = await mollie.paymentRefunds.create({
  paymentId: 'tr_xxx',
  amount: { currency: 'EUR', value: '29.00' },
  description: 'Customer request',
});

Webhook Processing

StatusAction
paidGrant access
failedNotify user
expiredLog — payment window expired
canceledLog — user canceled
refundedAdjust access
export async function POST(req: Request) {
  const form = await req.formData();
  const paymentId = form.get('id') as string;

  // Always fetch the full payment — don't trust webhook body
  const payment = await mollie.payments.get(paymentId);

  switch (payment.status) {
    case 'paid':
      await grantAccess(payment.metadata.userId);
      break;
    case 'failed':
    case 'expired':
      await notifyPaymentFailed(payment.metadata.userId);
      break;
  }

  return new Response('OK');
}

Best Practices

  • Always fetch the payment from Mollie in webhooks — don't trust the webhook body
  • Don't specify a payment method to show all available options to the customer
  • Use customer objects for subscription billing
  • Support iDEAL for Dutch customers, Bancontact for Belgian
  • Use the Mollie dashboard for refund management when manual intervention is needed
  • Test with Mollie's test mode and test amounts

Anti-Patterns

  • Trusting the redirect to confirm payment — always use webhooks
  • Not supporting local payment methods for European customers
  • Creating subscriptions without a valid mandate (first payment)
  • Hardcoding payment methods instead of letting Mollie show available ones
  • Not handling expired payments — users may have abandoned checkout

Install this skill directly: skilldb add payment-services-skills

Get CLI access →