To use Authorize.Net with Bolt.new, prompt Bolt to install the authorizenet npm package and create an API route that accepts tokenized card data from Accept.js. Store your API Login ID and Transaction Key in the .env file. Outbound payment API calls work in Bolt's WebContainer during development. Deploy to Netlify or Vercel before testing Authorize.Net webhooks, which require a publicly accessible URL.
Accept Payments in Bolt.new with Authorize.Net's Traditional Gateway
Authorize.Net is one of the oldest and most widely trusted payment gateways in North America, processing billions of dollars in transactions annually for businesses that maintain their own merchant banking relationships. Unlike Stripe's all-in-one platform model, Authorize.Net is a pure gateway — it sits between your application and your merchant bank account, handling card authorization, fraud screening, and settlement. If your business already has a merchant account with a bank, Authorize.Net is the most common gateway layer used by that bank.
The integration architecture for Bolt.new follows the Accept.js pattern, which is Authorize.Net's modern approach to PCI-compliant card handling. Accept.js is a JavaScript library hosted on Authorize.Net's servers that runs entirely in the browser, capturing card data and converting it to a single-use payment nonce before the data ever reaches your server. Your Bolt-generated API route receives only the nonce — never the raw card number — and forwards it to Authorize.Net's API for charging. This keeps your application out of PCI DSS scope for card data storage.
During development in Bolt's WebContainer, outbound calls to Authorize.Net's sandbox API work without any additional configuration. Accept.js loads from Authorize.Net's CDN and the tokenization flow works in the preview. However, Authorize.Net's webhook notifications (called Silent Post or Webhook events) require a publicly accessible URL — the WebContainer cannot receive incoming HTTP connections. You need to deploy to Netlify or Vercel before testing the full end-to-end notification flow.
Integration method
Bolt.new integrates with Authorize.Net by generating an API route that uses the authorizenet npm package to process payment nonces returned by Accept.js. Accept.js runs as a hosted client-side script directly from Authorize.Net's servers, tokenizing card data in the browser before it reaches your app. The API route then charges the nonce server-side using your API Login ID and Transaction Key stored in the .env file.
Prerequisites
- An Authorize.Net sandbox account (free at sandbox.authorize.net — separate from a live account)
- Your sandbox API Login ID and Transaction Key from Authorize.Net Developer Center → Sandbox → Manage Credentials
- A Bolt.new project set up with either Vite + React or Next.js
- Basic understanding that Authorize.Net requires an existing merchant bank account for live processing (sandbox is free to test)
- A deployed URL on Netlify or Vercel for testing webhook notifications after development
Step-by-step guide
Get Your Authorize.Net Sandbox Credentials
Get Your Authorize.Net Sandbox Credentials
Before writing any code, you need API credentials from Authorize.Net's developer sandbox. The sandbox is a completely separate environment from production — you can test transactions without moving real money, and sandbox credentials never work in production. Start by visiting sandbox.authorize.net and creating a free sandbox account. After signup, log in and navigate to the Sandbox menu in the top navigation. Select 'Manage Credentials' to find your API Login ID and Transaction Key. The API Login ID is a short alphanumeric string that identifies your merchant account. The Transaction Key is a secret string used to authenticate API requests — treat it like a password and never expose it in client-side code. Copy both values. You will also need your Client Key for Accept.js — this is a public key safe to include in browser-side JavaScript. Find it under Account → Settings → Security Settings → Manage Public Client Key. Create a new key if one does not exist. Note: in the sandbox, you can generate test transactions that show up in your Sandbox account reports without charging real cards. The sandbox API endpoint is different from production: sandbox transactions go to apitest.authorize.net while production uses api2.authorize.net. Bolt's generated code should use the sandbox endpoint during development.
Pro tip: Write down all three credentials: API Login ID, Transaction Key, and Client Key. The Client Key is public (safe for Accept.js in the browser). The API Login ID and Transaction Key are secrets — they go in your .env file only.
Expected result: You have your API Login ID, Transaction Key, and Client Key from the Authorize.Net sandbox dashboard.
Add Credentials to .env and Prompt Bolt to Install the SDK
Add Credentials to .env and Prompt Bolt to Install the SDK
Environment variables in Bolt.new live in the .env file at the root of your project. Open the file tree in Bolt and create or edit .env. Add three variables: AUTHORIZE_API_LOGIN_ID, AUTHORIZE_TRANSACTION_KEY, and VITE_AUTHORIZE_CLIENT_KEY. The VITE_ prefix makes the client key accessible in browser-side code via import.meta.env — this is intentional because the client key is designed to be public. The API Login ID and Transaction Key do not get the VITE_ prefix because they should only be accessible in server-side code. Now prompt Bolt to install the authorizenet npm package and scaffold the integration. The authorizenet package is Authorize.Net's official Node.js SDK for server-side API calls. It provides typed classes for all API request and response objects, making it much easier to work with than raw HTTP calls. The package handles request signing, response parsing, and error formatting. When Bolt installs it, verify it appears in package.json as a dependency. Keep in mind that in Vite projects, API route logic needs to run through a serverless function at deploy time — during development you may need to proxy API calls through vite.config.ts, or use a Next.js project where app/api routes are available natively. Ask Bolt to set up whichever pattern applies to your project.
Install the authorizenet npm package and create the foundation for Authorize.Net payment processing. Add AUTHORIZE_API_LOGIN_ID, AUTHORIZE_TRANSACTION_KEY, and VITE_AUTHORIZE_CLIENT_KEY environment variables to my .env file (with placeholder values). Create a server-side API route at /api/authorize-payment that initializes the Authorize.Net SDK in sandbox mode using API Login ID and Transaction Key from environment variables. The route should accept a POST request with a paymentNonce and amount field.
Paste this in Bolt.new chat
1# .env2AUTHORIZE_API_LOGIN_ID=your_api_login_id_here3AUTHORIZE_TRANSACTION_KEY=your_transaction_key_here4VITE_AUTHORIZE_CLIENT_KEY=your_client_key_herePro tip: The VITE_AUTHORIZE_CLIENT_KEY is intentionally public — Authorize.Net's Client Key is designed to be embedded in browser JavaScript. Never use VITE_ prefix for your Transaction Key or API Login ID.
Expected result: The authorizenet package appears in package.json and the .env file contains all three credential placeholders ready for your real sandbox values.
Embed Accept.js and Build the Payment Form
Embed Accept.js and Build the Payment Form
Accept.js is Authorize.Net's hosted JavaScript library that captures card data and converts it to a single-use payment nonce before the data reaches your server. You load Accept.js from Authorize.Net's CDN — for sandbox, use https://jstest.authorize.net/v1/Accept.js, and for production use https://js.authorize.net/v1/Accept.js. The form must include fields for card number, expiration date, and CVV code, but these fields should NOT be regular controlled React inputs that you manage in state — Accept.js reads them directly and the nonce generation happens without your JavaScript ever seeing the raw card number. The typical implementation uses a hidden iframe or special data-attributes that Accept.js intercepts. When the user submits the form, you call Accept.dispatchData() with your API Login ID and Client Key. Accept.js calls back with a response object containing either an opaqueData.dataValue (the nonce) or an array of error messages. Once you have the nonce, you POST it to your server-side API route along with the transaction amount. The card number and CVV fields never touch your server, keeping you outside PCI DSS scope for cardholder data. During development in Bolt's WebContainer preview, the Accept.js script loads from Authorize.Net's CDN via outbound HTTP — this works fine. The tokenization flow completes in the browser and generates a valid sandbox nonce.
Add an Accept.js payment form to my checkout page. Load the Accept.js sandbox script from https://jstest.authorize.net/v1/Accept.js. Create a PaymentForm React component with card number, expiration month, expiration year, and CVV inputs. When the user submits the form, call Accept.dispatchData() with my VITE_AUTHORIZE_CLIENT_KEY and API Login ID. On success, extract the opaqueData.dataValue nonce and POST it along with the payment amount to /api/authorize-payment. Show a loading spinner while processing and display the transaction ID on success or the error message on failure.
Paste this in Bolt.new chat
1// components/AuthorizePaymentForm.tsx2'use client';3import { useState } from 'react';45declare global {6 interface Window {7 Accept: {8 dispatchData: (secureData: object, callback: (response: AcceptResponse) => void) => void;9 };10 }11}1213interface AcceptResponse {14 messages: { resultCode: string; message: Array<{ code: string; text: string }> };15 opaqueData?: { dataDescriptor: string; dataValue: string };16}1718interface AuthorizePaymentFormProps {19 amount: number;20 onSuccess: (transactionId: string) => void;21 onError: (message: string) => void;22}2324export function AuthorizePaymentForm({ amount, onSuccess, onError }: AuthorizePaymentFormProps) {25 const [cardNumber, setCardNumber] = useState('');26 const [expMonth, setExpMonth] = useState('');27 const [expYear, setExpYear] = useState('');28 const [cvv, setCvv] = useState('');29 const [loading, setLoading] = useState(false);3031 function handleSubmit(e: React.FormEvent) {32 e.preventDefault();33 setLoading(true);3435 const secureData = {36 authData: {37 clientKey: import.meta.env.VITE_AUTHORIZE_CLIENT_KEY,38 apiLoginID: import.meta.env.VITE_AUTHORIZE_API_LOGIN_ID,39 },40 cardData: {41 cardNumber: cardNumber.replace(/\s/g, ''),42 month: expMonth,43 year: expYear,44 cardCode: cvv,45 },46 };4748 window.Accept.dispatchData(secureData, async (response: AcceptResponse) => {49 if (response.messages.resultCode === 'Error') {50 const errorMsg = response.messages.message.map((m) => m.text).join(', ');51 onError(errorMsg);52 setLoading(false);53 return;54 }5556 const nonce = response.opaqueData?.dataValue;57 const descriptor = response.opaqueData?.dataDescriptor;5859 const result = await fetch('/api/authorize-payment', {60 method: 'POST',61 headers: { 'Content-Type': 'application/json' },62 body: JSON.stringify({ nonce, descriptor, amount }),63 });6465 const data = await result.json();66 setLoading(false);6768 if (data.transactionId) {69 onSuccess(data.transactionId);70 } else {71 onError(data.error || 'Payment failed');72 }73 });74 }7576 return (77 <form onSubmit={handleSubmit} className="space-y-4">78 <script src="https://jstest.authorize.net/v1/Accept.js" />79 <input80 type="text"81 placeholder="Card Number"82 value={cardNumber}83 onChange={(e) => setCardNumber(e.target.value)}84 className="w-full border rounded px-3 py-2"85 maxLength={19}86 />87 <div className="flex gap-2">88 <input type="text" placeholder="MM" value={expMonth} onChange={(e) => setExpMonth(e.target.value)} className="w-24 border rounded px-3 py-2" maxLength={2} />89 <input type="text" placeholder="YYYY" value={expYear} onChange={(e) => setExpYear(e.target.value)} className="w-28 border rounded px-3 py-2" maxLength={4} />90 <input type="text" placeholder="CVV" value={cvv} onChange={(e) => setCvv(e.target.value)} className="w-20 border rounded px-3 py-2" maxLength={4} />91 </div>92 <button type="submit" disabled={loading} className="w-full bg-blue-600 text-white py-3 rounded hover:bg-blue-700 disabled:opacity-50">93 {loading ? 'Processing...' : `Pay $${amount.toFixed(2)}`}94 </button>95 </form>96 );97}Pro tip: Load the sandbox Accept.js script (jstest.authorize.net) during development and switch to js.authorize.net for production. Loading the wrong version causes silent tokenization failures.
Expected result: A payment form renders in the Bolt preview with card fields. Submitting calls Accept.js for tokenization and POSTs the nonce to your API route.
Create the Server-Side API Route to Charge the Nonce
Create the Server-Side API Route to Charge the Nonce
The API route receives the payment nonce from Accept.js along with the transaction amount, then charges it using Authorize.Net's API. In a Next.js Bolt project, this lives at app/api/authorize-payment/route.ts. The authorizenet SDK uses a class-based approach that differs from typical REST SDKs — you instantiate request objects (like AuthorizeNetAPI.createTransactionRequest), set properties on them, and call a controller to execute the request. The transaction type for a standard purchase is authCaptureTransaction, which both authorizes and captures the payment in one step (funds are captured immediately). The payment object uses an OpaqueData type to accept Accept.js nonces — you pass both the dataDescriptor (always 'COMMON.ACCEPT.INAPP.PAYMENT') and the dataValue (the nonce) to the OpaqueData object. The sandbox environment routes to apitest.authorize.net automatically when you set the environment to SANDBOX in the controller. Always check the transaction response's resultCode — 'Ok' means approved, 'Error' means declined or a system error. Parse the transId from the response for your confirmation message. The entire transaction is server-side and safe: your Transaction Key never leaves the server, and the raw card number never reaches your server at all.
Create an API route at app/api/authorize-payment/route.ts that accepts POST requests with nonce, descriptor, and amount fields. Use the authorizenet npm package to create an authCaptureTransaction request with the payment nonce as OpaqueData (dataDescriptor and dataValue). Set the API credentials from process.env.AUTHORIZE_API_LOGIN_ID and process.env.AUTHORIZE_TRANSACTION_KEY. Use the sandbox environment. On success, return the transaction ID as JSON. On failure, return the error message. Add error handling for SDK exceptions.
Paste this in Bolt.new chat
1// app/api/authorize-payment/route.ts2import { NextRequest, NextResponse } from 'next/server';3import * as AuthorizeNet from 'authorizenet';45const ApiContracts = AuthorizeNet.APIContracts;6const ApiControllers = AuthorizeNet.APIControllers;78export async function POST(request: NextRequest) {9 const { nonce, descriptor, amount } = await request.json();1011 const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();12 merchantAuthenticationType.setName(process.env.AUTHORIZE_API_LOGIN_ID!);13 merchantAuthenticationType.setTransactionKey(process.env.AUTHORIZE_TRANSACTION_KEY!);1415 const opaqueData = new ApiContracts.OpaqueDataType();16 opaqueData.setDataDescriptor(descriptor || 'COMMON.ACCEPT.INAPP.PAYMENT');17 opaqueData.setDataValue(nonce);1819 const paymentType = new ApiContracts.PaymentType();20 paymentType.setOpaqueData(opaqueData);2122 const transactionRequestType = new ApiContracts.TransactionRequestType();23 transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.AUTHCAPTURETRANSACTION);24 transactionRequestType.setPayment(paymentType);25 transactionRequestType.setAmount(amount.toFixed(2));2627 const createRequest = new ApiContracts.CreateTransactionRequest();28 createRequest.setMerchantAuthentication(merchantAuthenticationType);29 createRequest.setTransactionRequest(transactionRequestType);3031 return new Promise((resolve) => {32 const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());33 ctrl.setEnvironment(ApiContracts.Constants.endpoint.sandbox);3435 ctrl.execute(() => {36 const apiResponse = ctrl.getResponse();37 const response = new ApiContracts.CreateTransactionResponse(apiResponse);3839 if (response && response.getMessages().getResultCode() === ApiContracts.MessageTypeEnum.OK) {40 const transId = response.getTransactionResponse().getTransId();41 resolve(NextResponse.json({ transactionId: transId }));42 } else {43 const errorText =44 response?.getTransactionResponse()?.getErrors()?.getError()?.[0]?.getErrorText() ||45 response?.getMessages()?.getMessage()?.[0]?.getText() ||46 'Transaction failed';47 resolve(NextResponse.json({ error: errorText }, { status: 400 }));48 }49 });50 });51}Pro tip: The authorizenet SDK uses a callback-based pattern, not Promises. Wrap the controller.execute() call in a new Promise() so you can await it cleanly in your Next.js API route.
Expected result: POSTing a valid sandbox nonce and amount to /api/authorize-payment returns a JSON object with transactionId. The transaction appears in your Authorize.Net sandbox account reports.
Deploy and Configure Authorize.Net Webhooks
Deploy and Configure Authorize.Net Webhooks
Authorize.Net supports webhook notifications (called Webhooks in the new API) that POST transaction event data to a URL you configure. Common events include net.authorize.payment.authcapture.created (successful charge) and net.authorize.payment.fraud.held (fraud screening held a transaction). During development in Bolt's WebContainer, these incoming HTTP POST requests from Authorize.Net cannot reach the preview environment — the WebContainer has no public URL that external services can reach. This is a fundamental WebContainer limitation. To receive webhooks, you must first deploy your app to Netlify or Vercel. After deploying, set your production environment variables in your hosting platform's dashboard: AUTHORIZE_API_LOGIN_ID and AUTHORIZE_TRANSACTION_KEY as plain server-side variables (no NEXT_PUBLIC_ or VITE_ prefix). Then go to Authorize.Net's sandbox account, navigate to Account → Settings → Transaction Reporting → Webhooks, and add a new webhook endpoint using your deployed URL, for example https://your-app.netlify.app/api/authorize-webhook. Select the events you want: at minimum net.authorize.payment.authcapture.created. Authorize.Net signs webhook payloads with an HMAC-SHA512 signature using a webhook signing key — find this key in the Webhooks section after creating the endpoint. Store it as AUTHORIZE_WEBHOOK_KEY in your environment variables and verify the X-ANET-Signature header on every incoming webhook request before processing it.
Create a webhook handler at app/api/authorize-webhook/route.ts that verifies the X-ANET-Signature header using HMAC-SHA512 with the AUTHORIZE_WEBHOOK_KEY environment variable. Parse the webhook payload for net.authorize.payment.authcapture.created events and log the transaction ID and amount. Return 200 on success. Return 401 if signature verification fails. Handle the raw body correctly for signature verification.
Paste this in Bolt.new chat
1// app/api/authorize-webhook/route.ts2import { NextRequest, NextResponse } from 'next/server';3import crypto from 'crypto';45export async function POST(request: NextRequest) {6 const body = await request.text();7 const signature = request.headers.get('x-anet-signature');89 if (!signature) {10 return NextResponse.json({ error: 'Missing signature' }, { status: 401 });11 }1213 // Authorize.Net sends SHA512=<hash>14 const expectedSig = crypto15 .createHmac('sha512', process.env.AUTHORIZE_WEBHOOK_KEY!)16 .update(body)17 .digest('hex')18 .toUpperCase();1920 const receivedSig = signature.replace('SHA512=', '').toUpperCase();2122 if (expectedSig !== receivedSig) {23 return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });24 }2526 const event = JSON.parse(body);2728 if (event.eventType === 'net.authorize.payment.authcapture.created') {29 const transactionId = event.payload?.id;30 const amount = event.payload?.authAmount;31 console.log(`Payment captured: transaction ${transactionId} for $${amount}`);32 // Update your database here33 }3435 return NextResponse.json({ received: true });36}Pro tip: Authorize.Net's webhook signature is prefixed with 'SHA512=' in the X-ANET-Signature header. Strip that prefix before comparing the computed HMAC to the received value.
Expected result: After deploying and registering the webhook in Authorize.Net sandbox settings, successful test transactions trigger the webhook and your handler logs the transaction details.
Common use cases
E-Commerce Product Checkout
Accept credit card payments for physical or digital products using Authorize.Net's sandbox. The customer enters card details into the Accept.js form, receives a payment nonce, and your API route charges the nonce for the order total. The transaction result determines the success or failure message shown to the customer.
Add Authorize.Net payment processing to my e-commerce checkout page. Use Accept.js to tokenize the card data in the browser, then send the payment nonce to an API route at /api/authorize-payment. The route should charge the nonce for the cart total using the authorizenet npm package and my sandbox API Login ID and Transaction Key from .env. Show a success message with the transaction ID on success, or the error message on failure.
Copy this prompt to try it in Bolt.new
Recurring Billing with Customer Profiles
Create a customer payment profile in Authorize.Net's Customer Information Manager (CIM) so the customer's card can be charged on a recurring basis without re-entering card details. The first charge stores the profile, and subsequent charges reference the stored profile ID.
Build a recurring billing system using Authorize.Net CIM. When a user subscribes, use Accept.js to tokenize their card, then call my API route to create a customer profile and payment profile in Authorize.Net CIM. Store the customerProfileId and customerPaymentProfileId in Supabase linked to the user. Create a second API route that charges the stored payment profile when the monthly billing cycle runs. Use sandbox credentials from .env.
Copy this prompt to try it in Bolt.new
B2B Invoice Payment Portal
Let business customers pay outstanding invoices by entering their card details on a branded payment page. The invoice amount and invoice number are passed to the checkout flow, and the transaction description in Authorize.Net references the invoice for reconciliation.
Create a payment portal page at /pay-invoice/:invoiceId that fetches invoice details from my Supabase database and displays the amount due. Add an Accept.js payment form below the invoice details. When the customer submits payment, POST the nonce and invoiceId to /api/pay-invoice which charges the exact invoice amount via Authorize.Net and marks the invoice as paid in Supabase. Show the transaction ID as confirmation. Use sandbox mode.
Copy this prompt to try it in Bolt.new
Troubleshooting
Accept.js returns 'E_WC_05: Please include a valid API Login ID' error in the browser console
Cause: The VITE_AUTHORIZE_CLIENT_KEY or API Login ID passed to Accept.dispatchData() does not match your sandbox account credentials, or you are loading the production Accept.js script while using sandbox credentials.
Solution: Double-check that VITE_AUTHORIZE_CLIENT_KEY in your .env matches the Public Client Key from your Authorize.Net sandbox account under Account → Settings → Security Settings → Manage Public Client Key. Ensure you are loading https://jstest.authorize.net/v1/Accept.js (note: jstest not js) for sandbox credentials. The production URL https://js.authorize.net only works with live API keys.
API route throws 'TypeError: Cannot read properties of undefined' when calling SDK methods
Cause: The authorizenet npm package uses a class-based API where you must call setter methods after instantiation. Accessing response properties before checking if they are defined causes null reference errors when a transaction is declined.
Solution: Always check that the response object and nested objects are not null before calling getter methods. Declined transactions may return a valid response object but with a null getTransactionResponse(). Wrap response parsing in a try/catch block and add null guards before chaining getters.
1const transResponse = response?.getTransactionResponse();2const resultCode = response?.getMessages()?.getResultCode();3if (resultCode === ApiContracts.MessageTypeEnum.OK && transResponse?.getTransId()) {4 const transId = transResponse.getTransId();5 // success6}Webhook requests from Authorize.Net are not arriving after deployment
Cause: Webhooks require a publicly accessible URL and cannot be received in Bolt's WebContainer preview. If deployed but still not receiving, the webhook endpoint URL may be incorrect or the events may not be selected in the Authorize.Net Webhooks configuration.
Solution: Confirm your app is deployed and the URL is publicly accessible. In Authorize.Net sandbox Account → Settings → Transaction Reporting → Webhooks, verify the endpoint URL matches your deployed app's webhook path exactly. Use Authorize.Net's webhook test tool to send a test event and check the response code returned by your handler.
'The merchant login ID or password is invalid or the account is inactive' error from the API route
Cause: The AUTHORIZE_API_LOGIN_ID or AUTHORIZE_TRANSACTION_KEY environment variable is missing, incorrect, or is a live key being used with the sandbox API endpoint (or vice versa).
Solution: Verify both environment variables are set correctly in your .env file for development. The API Login ID is typically 10 characters and the Transaction Key is 16 characters. Sandbox and live credentials are completely separate — sandbox credentials from sandbox.authorize.net only work with the sandbox endpoint and live credentials from account.authorize.net only work with the production endpoint.
Best practices
- Use Authorize.Net's sandbox account and sandbox Accept.js script (jstest.authorize.net) for all development — never use live credentials in development environments
- Never expose your Transaction Key in client-side code — it belongs only in server-side environment variables and API routes
- Always verify webhook signature headers using HMAC-SHA512 before processing any webhook payload from Authorize.Net
- Store transaction IDs in your database immediately when a payment succeeds — you need them for refunds, voids, and support inquiries
- Use authCaptureTransaction for immediate charges and authOnlyTransaction for reserving funds — know which transaction type your business model requires
- Handle duplicate submissions by disabling the payment button while processing and re-enabling only on error — double-charging customers damages trust
- Test declined transaction scenarios explicitly: use Authorize.Net test amounts like $0.01 (decline), $0.02 (insufficient funds), and $0.03 (communication error) in sandbox mode
Alternatives
Stripe is an all-in-one platform with instant account setup and no need for a pre-existing merchant bank account, making it faster to launch for new businesses.
Braintree (a PayPal company) offers similar traditional gateway features to Authorize.Net but with built-in PayPal acceptance and a more modern API design.
Worldpay serves enterprise merchants needing global multi-currency acquiring with deep integration into existing financial infrastructure.
2Checkout handles global payments across 200+ countries and multiple currencies, making it suitable for digital goods sold internationally.
Frequently asked questions
Does Bolt.new have a native Authorize.Net integration like it does for Stripe?
No. Unlike Stripe, Authorize.Net does not have a native Settings panel in Bolt.new. You integrate it manually by prompting Bolt to install the authorizenet npm package and generate the Accept.js form and API route code. The manual approach works well — the authorizenet SDK is well-documented and Bolt generates accurate integration code from descriptive prompts.
Can I test Authorize.Net payments in Bolt's WebContainer preview?
Outbound API calls work in the preview, so Accept.js tokenization and API route charges complete successfully during development. However, Authorize.Net webhook notifications (incoming HTTP POST requests) cannot reach the WebContainer. Test the payment form and transaction flow in the preview, then deploy to Netlify or Vercel to test the full webhook-driven notification flow.
Do I need a merchant account to use Authorize.Net?
For production, yes — Authorize.Net is a payment gateway that connects to your existing merchant bank account. Unlike Stripe, it does not provide the merchant account itself. For development and testing with the sandbox account, no merchant account is required. If you do not already have a merchant account, Stripe or Braintree may be simpler starting points since they include the merchant account in their platform.
How does Accept.js differ from building a custom card form?
Accept.js captures card data in the browser and converts it to a single-use payment nonce before your JavaScript or server ever sees the raw card number. This keeps your application outside of PCI DSS scope for cardholder data storage, which significantly reduces your compliance burden. Building a custom card form that POSTs raw card numbers to your server requires full PCI DSS compliance and regular security audits.
How do I switch from Authorize.Net sandbox to production in my Bolt app?
Update three things: replace your sandbox credentials in your hosting environment variables with your live API Login ID, Transaction Key, and Client Key; change the Accept.js script URL from https://jstest.authorize.net/v1/Accept.js to https://js.authorize.net/v1/Accept.js; and change the SDK controller environment from ApiContracts.Constants.endpoint.sandbox to ApiContracts.Constants.endpoint.production. Create new production webhooks in your live Authorize.Net account pointing to your production URL.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation