Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Adyen

Integrate Adyen with Bolt.new by creating a Next.js API route that creates Adyen payment sessions server-side, then mounting the Adyen Drop-in React component on the frontend. Adyen serves Uber, Spotify, and Microsoft with 250+ payment methods globally. Store your API key and merchant account in environment variables. Webhooks require a deployed URL — test on Netlify before enabling notifications.

What you'll learn

  • How to create an Adyen test account and configure a merchant account with API credentials
  • How to build a server-side API route in Bolt.new that creates Adyen payment sessions
  • How to integrate the Adyen Web Drop-in component in a React frontend
  • How to handle Adyen webhook notifications for payment result confirmation on a deployed server
  • How to deploy your Adyen integration to Netlify and register webhook URLs
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read35 minutesPaymentApril 2026RapidDev Engineering Team
TL;DR

Integrate Adyen with Bolt.new by creating a Next.js API route that creates Adyen payment sessions server-side, then mounting the Adyen Drop-in React component on the frontend. Adyen serves Uber, Spotify, and Microsoft with 250+ payment methods globally. Store your API key and merchant account in environment variables. Webhooks require a deployed URL — test on Netlify before enabling notifications.

Add Enterprise Payments to Your Bolt.new App with Adyen

Adyen powers payments for some of the world's largest companies — Uber, Spotify, Microsoft, eBay, and McDonald's all run on Adyen infrastructure. Unlike consumer-focused payment processors, Adyen is built for businesses that need a unified payment solution spanning online checkout, in-store terminals, and marketplace payouts. Its single API handles over 250 payment methods including credit cards, digital wallets, BNPL, and local payment methods across 40+ currencies.

The Adyen Web Drop-in is the recommended integration for web applications. It is a pre-built React-compatible UI component that handles the entire payment flow — card form, 3DS authentication, redirect-based payment methods, and error states — without you needing to build payment UI from scratch. The Drop-in is PCI-compliant by design: sensitive card data is captured directly by Adyen's hosted fields, never touching your server. This significantly reduces your PCI scope compared to building a custom card form.

The integration architecture in Bolt.new follows a clean two-step pattern: your Next.js API route creates a payment session server-side (keeping your API key safe), and the Drop-in component on the frontend uses the session to render the payment UI and process the payment. For real-time payment result notifications, Adyen sends webhooks to your server — a pattern that requires a deployed URL since Bolt's WebContainer cannot accept incoming HTTP connections. You can build and test the checkout flow using Adyen's test environment before worrying about webhooks.

Integration method

Bolt Chat + API Route

Adyen payments require a server-side payment session to be created using your API key and merchant account — credentials that must never reach the client. In Bolt.new, a Next.js API route creates the session by calling the Adyen Checkout API, then the Adyen Web Drop-in component (@adyen/adyen-web) mounts in your React frontend using the session data. The Drop-in handles the payment UI across all 250+ payment methods. Webhook notifications require a deployed URL.

Prerequisites

  • An Adyen test account — create one free at https://www.adyen.com/signup (requires business email and takes about 2 minutes)
  • An API key generated in Adyen Customer Area → Developers → API Credentials → Create new credential → select Checkout role
  • Your Merchant Account name from the Adyen Customer Area (found in the top-left of the Customer Area under your company name)
  • A Bolt.new account with a Next.js project open
  • A Netlify account for deployment and webhook testing

Step-by-step guide

1

Set Up Adyen Test Account and Generate API Credentials

Create your Adyen test account at https://www.adyen.com/signup using a business email. Adyen typically approves test accounts within minutes. Once logged into the Adyen Customer Area (the test environment is at https://ca-test.adyen.com), navigate to the top-left dropdown to note your Merchant Account name — this looks like 'YourCompanyECOM' and is a required field in every API call. Next, generate an API key: go to Developers → API Credentials → Create a new API credential. Select the 'Checkout' role to allow creating payment sessions. Under Allowed Origins, add https://localhost:3000 for local development and your Bolt preview URL. Copy the API key immediately as it is only shown once. The test environment uses a separate set of credentials from production — your test API key starts with a long string beginning with 'AQE'. Never use production credentials during development. Adyen test card numbers include 4111 1111 1111 1111 (Visa success), 4988 4388 4388 4388 (Visa insufficient funds), and 5101 1800 0000 0007 (Mastercard). The test Customer Area is at https://ca-test.adyen.com while production is at https://ca-live.adyen.com.

.env
1# .env add to project root
2ADYEN_API_KEY=AQEyhmfxKIHdKL2bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3ADYEN_MERCHANT_ACCOUNT=YourCompanyECOM
4ADYEN_ENVIRONMENT=test
5ADYEN_CLIENT_KEY=test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Pro tip: The ADYEN_CLIENT_KEY is separate from the API key — it is the Client Key found in Developers → API Credentials → your credential → Client Key. The Client Key is safe to expose in frontend code (it is a public key); the API key is secret and must stay server-side.

Expected result: You have an Adyen test Merchant Account name, API key, and Client Key recorded. The .env file is created with these values.

2

Build the Payment Session API Route

The Adyen integration requires a server-side step to create a payment session before the Drop-in component can render. This is not optional — Adyen's security model requires the session to be created with your API key, which must never reach the browser. The API route calls the Adyen Checkout Sessions endpoint (POST /checkout/v71/sessions) with the payment amount, currency, country code, merchant account, and a return URL. The return URL is where Adyen redirects the user after redirect-based payment methods (like some BNPL schemes or bank transfers). For card payments, the Drop-in handles the result inline without a redirect. The sessions endpoint returns a session ID and session data string — both are needed by the Drop-in component. The amount must be in minor units: for USD, $29.99 is represented as 2999. For currencies without minor units like JPY, use the exact amount. Check Adyen's currency documentation for each currency's minor unit. Adyen's test and production APIs use different base URLs: test is https://checkout-test.adyen.com and production endpoints are region-specific (e.g., https://checkout-live.adyen.com for EU). Your API route should read the environment from ADYEN_ENVIRONMENT to select the correct base URL.

Bolt.new Prompt

Create an Adyen payment session API route at app/api/adyen/sessions/route.ts in this Next.js project. The route should accept a POST request with a JSON body containing amount (in minor units), currency, countryCode, and returnUrl. Use process.env.ADYEN_API_KEY in the X-API-Key header and process.env.ADYEN_MERCHANT_ACCOUNT in the request body. Call the Adyen test sessions endpoint at https://checkout-test.adyen.com/checkout/v71/sessions. Return the session id and sessionData. Include a TypeScript interface for the Adyen session request and response. Add error handling for invalid credentials and Adyen API errors.

Paste this in Bolt.new chat

app/api/adyen/sessions/route.ts
1// app/api/adyen/sessions/route.ts
2import { NextResponse } from 'next/server';
3
4interface AdyenSessionRequest {
5 amount: { value: number; currency: string };
6 merchantAccount: string;
7 countryCode: string;
8 returnUrl: string;
9 reference: string;
10 channel: string;
11}
12
13interface AdyenSessionResponse {
14 id: string;
15 sessionData: string;
16 amount: { value: number; currency: string };
17 expiresAt: string;
18}
19
20export async function POST(request: Request) {
21 const apiKey = process.env.ADYEN_API_KEY;
22 const merchantAccount = process.env.ADYEN_MERCHANT_ACCOUNT;
23 const environment = process.env.ADYEN_ENVIRONMENT || 'test';
24
25 if (!apiKey || !merchantAccount) {
26 return NextResponse.json(
27 { error: 'Adyen credentials not configured' },
28 { status: 500 }
29 );
30 }
31
32 const { amount, currency, countryCode, returnUrl } = await request.json();
33
34 const baseUrl =
35 environment === 'test'
36 ? 'https://checkout-test.adyen.com'
37 : 'https://checkout-live.adyen.com';
38
39 const payload: AdyenSessionRequest = {
40 amount: { value: amount, currency },
41 merchantAccount,
42 countryCode: countryCode || 'US',
43 returnUrl: returnUrl || `${process.env.NEXT_PUBLIC_BASE_URL}/checkout/result`,
44 reference: `order-${Date.now()}`,
45 channel: 'Web',
46 };
47
48 try {
49 const response = await fetch(`${baseUrl}/checkout/v71/sessions`, {
50 method: 'POST',
51 headers: {
52 'X-API-key': apiKey,
53 'Content-Type': 'application/json',
54 },
55 body: JSON.stringify(payload),
56 });
57
58 if (!response.ok) {
59 const error = await response.json();
60 return NextResponse.json(
61 { error: error.message || 'Adyen API error', adyenError: error },
62 { status: response.status }
63 );
64 }
65
66 const session: AdyenSessionResponse = await response.json();
67 return NextResponse.json({
68 sessionId: session.id,
69 sessionData: session.sessionData,
70 });
71 } catch (error) {
72 const message = error instanceof Error ? error.message : 'Unknown error';
73 return NextResponse.json({ error: message }, { status: 500 });
74 }
75}

Pro tip: Adyen uses 'reference' as a unique identifier for each payment attempt — store this in your database to reconcile webhook notifications with the original order. Use a combination of timestamp and order ID for uniqueness.

Expected result: The API route is created and accepts POST requests. Testing with a valid Adyen test API key returns a session ID and session data string.

3

Mount the Adyen Drop-in React Component

The Adyen Web Drop-in is a pre-built payment UI component available as an npm package. Install it with `npm install @adyen/adyen-web` in the Bolt terminal. The Drop-in requires the session data from your API route, your Client Key (a public key safe for frontend use), and the environment string ('test' or 'live'). The Drop-in handles all payment methods automatically based on what is available for the shopper's country and the payment methods you have enabled in the Adyen Customer Area. Card payments, Apple Pay, Google Pay, and all redirect-based payment methods (iDEAL, Bancontact, etc.) are all included. The Drop-in needs to mount into a DOM element — create a div with a specific ID and use a useEffect hook to initialize the Drop-in after the component mounts. Clean up the Drop-in instance in the useEffect cleanup function to avoid memory leaks. Adyen's Drop-in v6 uses a new API compared to v5 — make sure your npm install gets the latest version. The onPaymentCompleted callback fires when the payment result is available (for card payments that do not require a redirect); the result.resultCode will be 'Authorised' for successful payments. For redirect-based payments, Adyen redirects to your returnUrl with query parameters you need to handle on that page.

Bolt.new Prompt

Create a checkout page at app/checkout/page.tsx that integrates the Adyen Drop-in component. Install @adyen/adyen-web via npm. The page should: 1) Call /api/adyen/sessions on load with amount 2999, currency USD, countryCode US. 2) Mount the Adyen Drop-in in a useEffect using AdyenCheckout with the session data, clientKey from process.env.NEXT_PUBLIC_ADYEN_CLIENT_KEY, and environment 'test'. 3) Handle onPaymentCompleted to show a success or failure message. 4) Include a loading state while the session is being created. Use a clean checkout layout with an order summary and the Adyen Drop-in container.

Paste this in Bolt.new chat

app/checkout/page.tsx
1// app/checkout/page.tsx
2'use client';
3
4import { useEffect, useRef, useState } from 'react';
5import AdyenCheckout from '@adyen/adyen-web';
6import '@adyen/adyen-web/dist/adyen.css';
7import type { CoreOptions } from '@adyen/adyen-web/dist/types/core/types';
8
9type PaymentStatus = 'idle' | 'loading' | 'ready' | 'success' | 'failed' | 'error';
10
11export default function CheckoutPage() {
12 const dropinRef = useRef<HTMLDivElement>(null);
13 const [status, setStatus] = useState<PaymentStatus>('loading');
14 const [resultCode, setResultCode] = useState<string>('');
15
16 useEffect(() => {
17 let dropin: { unmount?: () => void } | null = null;
18
19 async function initCheckout() {
20 try {
21 // Step 1: Create payment session
22 const res = await fetch('/api/adyen/sessions', {
23 method: 'POST',
24 headers: { 'Content-Type': 'application/json' },
25 body: JSON.stringify({
26 amount: 2999,
27 currency: 'USD',
28 countryCode: 'US',
29 returnUrl: `${window.location.origin}/checkout/result`,
30 }),
31 });
32
33 if (!res.ok) throw new Error('Failed to create payment session');
34 const { sessionId, sessionData } = await res.json();
35
36 // Step 2: Initialize Adyen Checkout
37 const options: CoreOptions = {
38 environment: 'test',
39 clientKey: process.env.NEXT_PUBLIC_ADYEN_CLIENT_KEY!,
40 session: { id: sessionId, sessionData },
41 onPaymentCompleted: (result: { resultCode: string }) => {
42 setResultCode(result.resultCode);
43 setStatus(result.resultCode === 'Authorised' ? 'success' : 'failed');
44 },
45 onError: (error: Error) => {
46 console.error('Adyen error:', error);
47 setStatus('error');
48 },
49 };
50
51 const checkout = await AdyenCheckout(options);
52
53 if (dropinRef.current) {
54 dropin = checkout.create('dropin').mount(dropinRef.current);
55 setStatus('ready');
56 }
57 } catch (err) {
58 console.error(err);
59 setStatus('error');
60 }
61 }
62
63 initCheckout();
64 return () => { dropin?.unmount?.(); };
65 }, []);
66
67 if (status === 'success') {
68 return (
69 <div className="max-w-md mx-auto p-8 text-center">
70 <div className="text-5xl mb-4"></div>
71 <h2 className="text-2xl font-bold text-green-700">Payment Successful</h2>
72 <p className="text-gray-500 mt-2">Result: {resultCode}</p>
73 </div>
74 );
75 }
76
77 return (
78 <div className="max-w-md mx-auto p-8">
79 <h1 className="text-2xl font-bold mb-6">Checkout</h1>
80 <div className="bg-gray-50 rounded-lg p-4 mb-6">
81 <div className="flex justify-between">
82 <span>Order total</span>
83 <span className="font-semibold">$29.99</span>
84 </div>
85 </div>
86 {status === 'loading' && <p className="text-center text-gray-500">Loading payment methods...</p>}
87 {status === 'error' && <p className="text-red-600">Payment initialization failed. Please try again.</p>}
88 <div ref={dropinRef} />
89 </div>
90 );
91}

Pro tip: Import the Adyen CSS file (@adyen/adyen-web/dist/adyen.css) to apply the default Drop-in styles. You can override specific styles using CSS variables that Adyen exposes — search for '--adyen-' in the Adyen Web documentation.

Expected result: The checkout page renders the Adyen Drop-in component with card and wallet payment options. Test payments using Adyen's test card 4111 1111 1111 1111 with any future expiry and CVV 737 complete successfully.

4

Handle Adyen Webhooks After Deployment

Adyen uses webhooks (called 'notifications' in Adyen's documentation) to send reliable payment result confirmations to your server. While the Drop-in's onPaymentCompleted callback handles immediate results, webhooks are the authoritative source of truth for payment outcomes — especially for async payment methods like bank transfers, SEPA direct debit, and BNPL. Webhooks are also how you handle chargebacks, refund confirmations, and capture events. Critically: Adyen webhooks cannot be tested during development in Bolt's WebContainer because the WebContainer runs inside the browser and cannot accept incoming HTTP connections from the internet. You must deploy to Netlify first, then configure your webhook endpoint in the Adyen Customer Area. After deploying to Netlify, go to Adyen Customer Area → Developers → Webhooks → New Webhook → Standard Notification. Enter your deployed URL (https://yoursite.netlify.app/api/adyen/webhook) as the Server Communication URL. Generate an HMAC key in the webhook configuration and add it to your Netlify environment variables as ADYEN_HMAC_KEY. Always verify the HMAC signature before processing any webhook event — Adyen provides an HMAC validation library in @adyen/api-library.

Bolt.new Prompt

Create an Adyen webhook handler at app/api/adyen/webhook/route.ts. The endpoint accepts POST requests from Adyen. For each notification item in the request body, verify the HMAC signature using process.env.ADYEN_HMAC_KEY and the @adyen/api-library package. For valid notifications, log the event code, merchant reference, and success status. Handle AUTHORISATION, CAPTURE, REFUND, and CHARGEBACK event codes. Return [accepted] as the response body (this is what Adyen expects to stop retrying).

Paste this in Bolt.new chat

app/api/adyen/webhook/route.ts
1// app/api/adyen/webhook/route.ts
2import { NextResponse } from 'next/server';
3
4interface AdyenNotificationItem {
5 NotificationRequestItem: {
6 eventCode: string;
7 success: string;
8 merchantReference: string;
9 pspReference: string;
10 amount: { value: number; currency: string };
11 additionalData?: { hmacSignature?: string };
12 };
13}
14
15// Simple HMAC verification — install @adyen/api-library for full verification
16function verifyHmac(item: AdyenNotificationItem['NotificationRequestItem'], hmacKey: string): boolean {
17 // In production, use @adyen/api-library HmacValidator
18 // This is a placeholder — implement proper HMAC validation
19 const signature = item.additionalData?.hmacSignature;
20 return !!signature && !!hmacKey; // Replace with real validation
21}
22
23export async function POST(request: Request) {
24 const hmacKey = process.env.ADYEN_HMAC_KEY;
25
26 try {
27 const body = await request.json();
28 const notifications: AdyenNotificationItem[] = body.notificationItems || [];
29
30 for (const notification of notifications) {
31 const item = notification.NotificationRequestItem;
32
33 if (hmacKey && !verifyHmac(item, hmacKey)) {
34 console.warn('Invalid HMAC signature for notification:', item.pspReference);
35 continue;
36 }
37
38 const isSuccess = item.success === 'true';
39 console.log(`Adyen webhook: ${item.eventCode}`, {
40 reference: item.merchantReference,
41 pspReference: item.pspReference,
42 success: isSuccess,
43 amount: item.amount,
44 });
45
46 switch (item.eventCode) {
47 case 'AUTHORISATION':
48 // Payment authorized — update order status to 'paid'
49 if (isSuccess) console.log(`Order ${item.merchantReference} paid`);
50 break;
51 case 'CAPTURE':
52 console.log(`Capture ${isSuccess ? 'succeeded' : 'failed'}: ${item.pspReference}`);
53 break;
54 case 'REFUND':
55 console.log(`Refund ${isSuccess ? 'processed' : 'failed'}: ${item.pspReference}`);
56 break;
57 case 'CHARGEBACK':
58 console.log(`Chargeback received for: ${item.merchantReference}`);
59 break;
60 }
61 }
62
63 // Adyen expects this exact response to stop retrying
64 return new Response('[accepted]', {
65 status: 200,
66 headers: { 'Content-Type': 'text/plain' },
67 });
68 } catch (error) {
69 console.error('Webhook processing error:', error);
70 return NextResponse.json({ error: 'Webhook processing failed' }, { status: 500 });
71 }
72}

Pro tip: Adyen retries webhook notifications up to 10 times over 24 hours if your endpoint does not return '[accepted]'. Always return the accepted response quickly, then process the notification asynchronously to avoid timeouts.

Expected result: After deploying to Netlify and configuring the webhook URL in the Adyen Customer Area, test notifications arrive at your endpoint. The Adyen webhook configuration page shows 'Test notification sent successfully'.

Common use cases

SaaS Subscription Checkout

Add a checkout page to a SaaS application that lets users pay for subscriptions with credit card, Apple Pay, Google Pay, or local payment methods. Adyen's Drop-in automatically shows the payment methods available in the user's region, reducing cart abandonment for international customers.

Bolt.new Prompt

Add an Adyen payment checkout to this Next.js SaaS app. Create an API route at app/api/adyen/sessions/route.ts that calls the Adyen Checkout Sessions API to create a payment session. Use process.env.ADYEN_API_KEY and process.env.ADYEN_MERCHANT_ACCOUNT. Set amount to 2999 (in minor units, i.e. $29.99), currency to USD, and returnUrl to the current page. Create a checkout page at app/checkout/page.tsx that imports @adyen/adyen-web and mounts the Drop-in component using the session data from the API route. Handle payment result states: authorized, refused, and error.

Copy this prompt to try it in Bolt.new

Multi-Currency E-Commerce Checkout

Build a global e-commerce checkout that supports multiple currencies and local payment methods. Adyen automatically presents the right payment options based on the shopper's country — iDEAL in the Netherlands, SEPA in Europe, Alipay in China — from a single integration.

Bolt.new Prompt

Build a multi-currency checkout page in Next.js with Adyen. Create an API route at app/api/adyen/sessions/route.ts that accepts a JSON body with amount, currency, and countryCode, then creates an Adyen payment session. Add the countryCode to the session request to enable local payment methods for that region. On the checkout page, detect the user's locale using navigator.language and pass the matching currency code. Mount the Adyen Drop-in component and display a success page after payment.

Copy this prompt to try it in Bolt.new

Marketplace Payout Dashboard

Build a dashboard for a marketplace that uses Adyen's Transfers API to display payout history, balance information, and initiate payouts to sellers. Adyen's Balance Platform makes it straightforward to manage money movement between marketplace accounts.

Bolt.new Prompt

Create a marketplace payout dashboard in Next.js using the Adyen Balance Platform API. Build an API route at app/api/adyen/balances/route.ts that fetches the balance account summary using process.env.ADYEN_BALANCE_ACCOUNT_ID and process.env.ADYEN_API_KEY. Add a second route at app/api/adyen/transfers/route.ts that lists recent transfers. Display balances and transfer history in a clean dashboard layout with status badges for completed, pending, and failed transfers.

Copy this prompt to try it in Bolt.new

Troubleshooting

Adyen sessions API returns 403 Forbidden or 'Invalid API key'

Cause: The ADYEN_API_KEY is incorrect, belongs to the wrong environment (live key used in test, or vice versa), or the API credential does not have the Checkout role.

Solution: In the Adyen Customer Area, go to Developers → API Credentials → select your credential → verify the Roles section includes 'Checkout web service role'. Generate a new API key if needed. Ensure you are using a test API key (starts with 'AQE') against the test endpoint (checkout-test.adyen.com), not the live endpoint.

typescript
1// Test environment uses test subdomain
2const baseUrl = environment === 'test'
3 ? 'https://checkout-test.adyen.com'
4 : 'https://checkout-live.adyen.com';
5
6// Header must use 'X-API-key' (not 'Authorization')
7headers: { 'X-API-key': process.env.ADYEN_API_KEY! }

Drop-in component does not render or shows a blank container

Cause: The Adyen Drop-in mounts into a DOM element that may not exist yet when the useEffect runs, or the CSS file is not imported.

Solution: Ensure you import the Adyen CSS file at the top of your component. Use a useRef attached to a div element and check that the ref.current exists before calling dropin.mount(). Add a non-zero height to the Drop-in container div to ensure it is visible.

typescript
1import '@adyen/adyen-web/dist/adyen.css';
2
3// Ensure the container div has a min-height
4<div ref={dropinRef} style={{ minHeight: '200px' }} />

Adyen webhooks are not arriving after deployment

Cause: The webhook URL is configured with the Bolt preview URL instead of the deployed Netlify URL, or the webhook endpoint is returning a non-200 status code causing Adyen to stop retrying.

Solution: In Adyen Customer Area → Developers → Webhooks, verify the Server Communication URL shows your deployed Netlify domain (https://yoursite.netlify.app/api/adyen/webhook), not a Bolt preview URL. WebContainers cannot receive incoming HTTP traffic — webhooks only work on deployed URLs. Ensure your webhook handler returns '[accepted]' as plain text with status 200.

typescript
1// Webhook response must be exactly this
2return new Response('[accepted]', {
3 status: 200,
4 headers: { 'Content-Type': 'text/plain' },
5});

CORS error when the Adyen Drop-in tries to make requests from the Bolt preview

Cause: The Bolt preview origin is not added to the Allowed Origins list in your Adyen API credential configuration.

Solution: In Adyen Customer Area → Developers → API Credentials → your credential → Allowed Origins, add your Bolt preview URL. The origin will look like https://[hash].local.credentialless.webcontainer-api.io. Also add your deployed Netlify URL. The Drop-in makes direct requests to Adyen's client-side endpoints using the Client Key (not the API key), so these origins must be explicitly allowed.

Best practices

  • Never put ADYEN_API_KEY in client-side code or as a NEXT_PUBLIC_ variable — it must only be accessed in server-side API routes
  • Use the Client Key (NEXT_PUBLIC_ADYEN_CLIENT_KEY) for the Drop-in frontend — it is designed to be public and is scoped to your specific domains
  • Always verify the HMAC signature on incoming webhook notifications using @adyen/api-library before processing payment events
  • Return '[accepted]' from your webhook endpoint within 10 seconds — Adyen retries notifications if the response is delayed or non-200
  • Use the Adyen test cards list from the documentation to test all result codes: authorised, refused, error, pending, and redirect flows
  • Store the merchant reference and PSP reference from webhooks in your database to create a reliable audit trail for every payment
  • Test the full payment flow on a deployed Netlify URL before enabling production credentials — several Drop-in behaviors differ between preview and deployed environments

Alternatives

Frequently asked questions

Does Bolt.new work with Adyen?

Yes. Adyen's Checkout API and Drop-in component work well with Bolt.new's Next.js API routes. You create payment sessions server-side in an API route, then mount the Drop-in React component on the frontend. Outbound API calls to Adyen work in Bolt's WebContainer preview. Webhook notifications require a deployed Netlify URL.

Can I test Adyen payments in Bolt's preview without deploying?

Yes for the checkout flow. Adyen's Drop-in component and payment session API work in Bolt's WebContainer preview using test credentials. Use Adyen's test card numbers (4111 1111 1111 1111 for success) to test the full checkout UI. The one exception is webhooks — Adyen cannot send webhook notifications to the Bolt preview URL. Deploy to Netlify to test webhook-based payment confirmation.

What is the difference between Adyen's API key and Client Key?

The API key (ADYEN_API_KEY) is a secret server-side credential that must never be exposed in client code. It is used in your Next.js API routes to create payment sessions, process refunds, and manage payments. The Client Key (NEXT_PUBLIC_ADYEN_CLIENT_KEY) is a public identifier for the Drop-in component — it is safe to include in frontend code and only works for client-side operations on the domains you have whitelisted.

How do I go live with Adyen in a Bolt.new app?

Adyen requires an application and approval process for live accounts. Once approved, you receive live API credentials. Update ADYEN_API_KEY and ADYEN_CLIENT_KEY in your Netlify environment variables with the live values, change ADYEN_ENVIRONMENT from 'test' to 'live', and update the Checkout API base URL to your region's live endpoint (e.g., https://checkout-live.adyen.com for EU). Update webhook URLs to point to your production domain.

Does Adyen support subscriptions and recurring payments?

Yes. Adyen supports tokenized cards for recurring billing through its Stored Payment Methods feature. When creating a payment session, set storePaymentMethodMode to 'subscriptionSetup' to tokenize the card. Subsequent charges use the resulting storedPaymentMethodId. For full subscription management with billing cycles and dunning, pair Adyen with your own billing logic or use Adyen's Billing Agreements feature.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.