Connect Retool to Authorize.Net by creating a REST API Resource targeting Authorize.Net's JSON API with your API Login ID and Transaction Key as authentication credentials. Use Authorize.Net's API to build a payment management dashboard — view transactions, search customer profiles, process refunds and voids, and generate settlement reports from a centralized Retool admin panel for businesses on this legacy payment gateway.
| Fact | Value |
|---|---|
| Tool | Authorize.Net |
| Category | Payment |
| Method | REST API Resource |
| Difficulty | Intermediate |
| Time required | 30 minutes |
| Last updated | April 2026 |
Build an Authorize.Net Payment Management Dashboard in Retool
Authorize.Net is one of the oldest and most widely deployed payment gateways in North America, serving hundreds of thousands of merchants across e-commerce, retail, and professional services. While modern alternatives like Stripe have simpler API designs, many established businesses remain on Authorize.Net due to existing integrations, contractual arrangements, or institutional familiarity. For these teams, Authorize.Net's built-in reporting interface is functional but inflexible — it's difficult to combine payment data with business metrics or build custom workflows for fraud review and dispute management.
Connecting Authorize.Net to Retool bridges this gap by giving your operations and finance teams direct query access to payment data in a customizable internal tool. Your team can search transactions by date, card type, or amount; view customer payment profiles with stored card data; process refunds and voids without logging into multiple systems; generate settlement reports for reconciliation; and set up automated alerts for suspicious transaction patterns using Retool Workflows.
Authorize.Net's JSON API (the modern alternative to its older XML API) accepts authentication credentials embedded in every request body as a merchantAuthentication object containing your API Login ID and Transaction Key. All queries go to a single endpoint (api2.authorize.net/xml/v1/request.api) with different request types specified in the body. Retool's REST API Resource handles the base URL and POST configuration, while the specific action is controlled by the requestType field in each query's body.
Integration method
Authorize.Net connects to Retool through a REST API Resource using credentials embedded in the JSON request body (API Login ID and Transaction Key). Unlike most REST APIs that use HTTP header authentication, Authorize.Net's JSON API includes authentication credentials in a 'merchantAuthentication' object inside every request body. Retool proxies all requests server-side, keeping your payment credentials secure. JavaScript transformers handle the response structure and can be used to parse XML responses from Authorize.Net's older endpoints when needed.
Prerequisites
- An Authorize.Net merchant account with API access — obtain your API Login ID and Transaction Key from Account → Settings → API Credentials & Keys in the Authorize.Net merchant interface
- Separate sandbox API credentials for testing (Authorize.Net provides a free sandbox at sandbox.authorize.net with test credentials)
- Understanding of Authorize.Net's API terminology: API Login ID, Transaction Key, merchant profile ID, and transaction ID
- A Retool account with permission to create Resources and write query bodies
- Familiarity with Retool's query editor and Table component
Step-by-step guide
Create an Authorize.Net REST API Resource in Retool
Navigate to the Resources tab in Retool and click Add Resource. Select REST API from the resource type list. Name the resource 'Authorize.Net API'. In the Base URL field, enter https://apitest.authorize.net/xml/v1/request.api for the sandbox environment or https://api2.authorize.net/xml/v1/request.api for production. Authorize.Net's entire JSON API goes through this single endpoint — all operations are distinguished by the JSON body content, not by different URL paths. This means every Authorize.Net query in Retool will use POST to this same URL with different body structures. Authorize.Net's JSON API does not use HTTP Authorization headers. Instead, authentication credentials are included in every request body. For this reason, do not configure any authentication in the Retool resource's Authentication section — leave it set to None. The credentials will be included in each query's body. Add a default header: key = Content-Type, value = application/json. This ensures Authorize.Net's API parses your requests correctly. Store your API Login ID and Transaction Key as Secret configuration variables in Retool before writing queries: Settings → Configuration Variables → create AUTHORIZENET_API_LOGIN_ID and AUTHORIZENET_TRANSACTION_KEY, mark both as Secret. This allows you to reference them securely in query bodies without exposing the values. Click Save Changes. You now have separate configurations for sandbox and production by maintaining two resources with different base URLs.
Pro tip: Maintain two Authorize.Net resources in Retool: one pointing to the sandbox URL (https://apitest.authorize.net/xml/v1/request.api) with test credentials, and one pointing to production (https://api2.authorize.net/xml/v1/request.api) with live credentials. Use a Dropdown in your app to switch between them during development to prevent test queries from accidentally reaching production.
Expected result: The Authorize.Net API REST resource is saved with the correct API URL, Content-Type header configured, and no HTTP-level authentication (credentials are in the request body). Configuration variables for API Login ID and Transaction Key are created and marked as Secret.
Query the transaction list for a date range
Create your first Authorize.Net query to retrieve transactions. In your Retool app, open the Code panel and add a new query. Name it getTransactions and select the Authorize.Net API resource. Set Method to POST. Leave Path empty — all Authorize.Net JSON API requests go to the root URL configured in the resource. Set Body Type to JSON. Enter the following JSON body structure for the getTransactionListRequest, which retrieves transactions for a specific batch or date range: This query type uses Authorize.Net's batch-based transaction retrieval. You first need to get settled batches (getSettledBatchListRequest), then retrieve transactions within each batch. Alternatively, use the unsettledTransactionList endpoint for pending transactions. For a date-range-based search, use getTransactionListRequest with batchId from the batch list. For searching by specific criteria (customer name, card number last 4, amount), use searchTransactionsRequest which accepts filter parameters. Create a second query named searchTransactions that uses the searchTransactionsRequest body type with filter fields connected to Text Input components in your app. This is the more useful query for the operations team since it searches across all settled and unsettled transactions without needing to know specific batch IDs. Bind a Table component to the search results using a JavaScript transformer that extracts the transaction array from the nested response structure.
1// JSON body for searchTransactionsRequest2{3 "searchTransactionsRequest": {4 "merchantAuthentication": {5 "name": "{{ retoolContext.configVars.AUTHORIZENET_API_LOGIN_ID }}",6 "transactionKey": "{{ retoolContext.configVars.AUTHORIZENET_TRANSACTION_KEY }}"7 },8 "refId": "retool_{{ Date.now() }}",9 "sorting": {10 "orderBy": "submitTimeUTC",11 "orderDescending": true12 },13 "paging": {14 "limit": 50,15 "offset": "{{ (pagination.page - 1) * 50 + 1 || 1 }}"16 },17 "searchQuery": {18 "fromDate": "{{ datePicker_from.value }}T00:00:00Z",19 "toDate": "{{ datePicker_to.value }}T23:59:59Z"20 }21 }22}Pro tip: Authorize.Net's pagination uses 1-based offsets (not 0-based like most REST APIs). The first page is offset 1, second page is offset 51 (for 50 items per page). Account for this in your pagination calculations by using ((page - 1) * limit) + 1 rather than (page - 1) * limit.
Expected result: The searchTransactions query returns a list of transactions for the selected date range. The response contains a transactions array (nested inside the response wrapper) that the transformer formats for the Table component.
Format Authorize.Net responses with JavaScript transformers
Authorize.Net's JSON API responses have a nested structure with multiple wrapper objects. The transaction data is typically found at response.searchTransactionsResponse.transactions.transaction (for search) or response.getTransactionListResponse.transactions.transaction (for batch list). JavaScript transformers are essential for extracting and formatting this data. Create a JavaScript transformer attached to the searchTransactions query by clicking the Advanced tab in the query editor and enabling Transform Results. Add the transformer code to extract and flatten the transaction data. For individual transaction details, create a separate query named getTransactionDetails. Set Method to POST, use the getTransactionDetailsRequest body type with the transaction ID from the selected table row: {{ table_transactions.selectedRow.transId }}. The detail response includes the full card data (masked), billing address, line items, and processing metadata. Authorize.Net also returns a messages object with result codes and descriptions. Always include message parsing in your transformer to surface error conditions clearly. The resultCode field is either Ok or Error — filter results where resultCode is not Ok and display them in an error banner component rather than silently failing.
1// JavaScript transformer — format Authorize.Net transaction search results2const response = data;3const resultCode = response?.messages?.resultCode;4if (resultCode !== 'Ok') {5 const errorMsg = response?.messages?.message?.[0]?.text || 'Unknown error';6 throw new Error(`Authorize.Net API Error: ${errorMsg}`);7}89const transactions = response?.transactions?.transaction || [];10const txArray = Array.isArray(transactions) ? transactions : [transactions];1112return txArray.map(tx => ({13 transId: tx.transId,14 submit_date: tx.submitTimeLocal15 ? new Date(tx.submitTimeLocal).toLocaleDateString('en-US', {16 year: 'numeric', month: 'short', day: 'numeric',17 hour: '2-digit', minute: '2-digit'18 })19 : 'N/A',20 amount: tx.settleAmount21 ? `$${parseFloat(tx.settleAmount).toFixed(2)}`22 : tx.authAmount23 ? `$${parseFloat(tx.authAmount).toFixed(2)}`24 : 'N/A',25 status: tx.transactionStatus || 'N/A',26 card_type: tx.payment?.creditCard?.cardType || 'N/A',27 card_last4: tx.payment?.creditCard?.cardNumber?.slice(-4) || 'N/A',28 customer_name: `${tx.billTo?.firstName || ''} ${tx.billTo?.lastName || ''}`.trim() || 'N/A',29 order_id: tx.order?.invoiceNumber || 'N/A',30 auth_code: tx.authCode || 'N/A'31}));Pro tip: Authorize.Net returns a single-item transaction as an object rather than a single-element array. Always normalize with: const txArray = Array.isArray(transactions) ? transactions : [transactions]; — this prevents a common bug where the transformer fails when only one transaction is returned in the response.
Expected result: The JavaScript transformer extracts transaction data from Authorize.Net's nested response structure and returns clean, flat objects suitable for the Table component. Error responses from Authorize.Net surface as clear error messages rather than silent undefined value issues.
Build the void and refund operation queries
Add write operations to allow your team to process refunds and voids directly from the Retool panel. Authorize.Net distinguishes between two reversal types: - Void: cancels a transaction before it settles (same-day transactions still in auth status). Use transactionType: voidTransaction. - Refund: returns funds for a settled transaction (transactions from previous days). Use transactionType: refundTransaction. Create a query named voidTransaction. Set Method to POST. In the JSON body, use createTransactionRequest with transactionType set to voidTransaction and the refTransId (the original transaction ID) from the selected table row. Create a separate query named refundTransaction. Set Method to POST. The refund body is more complex — it requires the original transaction amount, card number (last 4 digits), and expiration date in addition to the transaction ID. Pull these from the getTransactionDetails query data for the selected transaction. In your Retool app, add separate Void and Refund buttons. Configure each with a Confirm action to show a modal before execution (Transaction ID: {{ table_transactions.selectedRow.transId }}, Amount: {{ table_transactions.selectedRow.amount }}). On success, show a notification and trigger the search query to refresh the transaction list. Add validation in the button event handlers: only enable Void for transactions with status 'authorizedPendingCapture' and only enable Refund for transactions with status 'settledSuccessfully'. Disable buttons with a tooltip explanation when the status doesn't support that action.
1// JSON body for createTransactionRequest — refundTransaction type2{3 "createTransactionRequest": {4 "merchantAuthentication": {5 "name": "{{ retoolContext.configVars.AUTHORIZENET_API_LOGIN_ID }}",6 "transactionKey": "{{ retoolContext.configVars.AUTHORIZENET_TRANSACTION_KEY }}"7 },8 "refId": "refund_{{ Date.now() }}",9 "transactionRequest": {10 "transactionType": "refundTransaction",11 "amount": "{{ table_transactions.selectedRow.raw_amount }}",12 "payment": {13 "creditCard": {14 "cardNumber": "{{ getTransactionDetails.data.cardLast4 }}",15 "expirationDate": "XXXX"16 }17 },18 "refTransId": "{{ table_transactions.selectedRow.transId }}"19 }20 }21}Pro tip: For Authorize.Net refunds, the expirationDate field can be set to 'XXXX' when you have the original transaction ID (refTransId). Authorize.Net validates the refund against the stored transaction, so the exact expiration date is not required when the original transaction ID is provided. This simplifies the refund form — you do not need to ask your team to re-enter card details.
Expected result: The void and refund buttons are enabled only for transactions in appropriate statuses. Clicking either button shows a confirmation modal with transaction details. On confirmation, the operation is submitted to Authorize.Net and the transaction list refreshes to show the updated status.
Query customer payment profiles for support workflows
Authorize.Net's Customer Information Manager (CIM) stores tokenized payment profiles linked to customer IDs. Create queries to look up and manage these profiles for customer service scenarios. Create a query named getCustomerProfile. Set Method to POST. The body uses getCustomerProfileRequest with either a customerProfileId (Authorize.Net's internal ID) or the merchantCustomerId (your own customer ID if you stored it when creating the profile). Connect the customerProfileId input to a Text Input component named textInput_profileId. The getCustomerProfile response includes an array of paymentProfiles, each containing the masked card number, expiration date, and billing address. Create a transformer that flattens this structure into a list of payment methods with their associated profile IDs. For deleting an individual payment method, create deleteCustomerPaymentProfile with body type deleteCustomerPaymentProfileRequest, passing both the customerProfileId and the paymentProfileId of the method to delete. Add a Delete button to the payment methods Table row with a confirmation modal. For creating new customer profiles (when onboarding a new customer via your internal tool), create a createCustomerProfile query with the full CIM profile creation body including the customer's email, shipping address, and payment method data. For RapidDev integrations that combine Authorize.Net CIM data with your customer database, a joined view showing both Authorize.Net payment profile status and your internal CRM data side by side in the same Retool app gives support teams everything they need in one place.
1// JavaScript transformer — extract payment profiles from getCustomerProfileResponse2const response = data;3const profile = response?.profile || {};4const paymentProfiles = profile.paymentProfiles || [];5const profileArray = Array.isArray(paymentProfiles) ? paymentProfiles : [paymentProfiles];67return profileArray.map(pp => ({8 payment_profile_id: pp.customerPaymentProfileId,9 card_type: pp.payment?.creditCard?.cardType || 'N/A',10 card_number: pp.payment?.creditCard?.cardNumber || 'N/A',11 expiration: pp.payment?.creditCard?.expirationDate || 'N/A',12 billing_name: `${pp.billTo?.firstName || ''} ${pp.billTo?.lastName || ''}`.trim(),13 billing_email: pp.billTo?.email || 'N/A',14 billing_address: [15 pp.billTo?.address,16 pp.billTo?.city,17 pp.billTo?.state,18 pp.billTo?.zip19 ].filter(Boolean).join(', '),20 default_flag: pp.defaultPaymentProfile ? 'Default' : ''21}));Pro tip: When displaying Authorize.Net payment profiles, always use the masked card number returned by the API — never attempt to decrypt or display full card numbers. Authorize.Net returns only the last four digits regardless of your API permissions, which is the correct behavior for PCI DSS compliance.
Expected result: The customer profile lookup panel shows all stored payment methods for the entered customer profile ID. The payment methods table displays masked card details, billing addresses, and the default payment flag. The Delete button allows removing individual payment methods with confirmation.
Common use cases
Build a transaction search and refund panel
Create a Retool app where your operations team can search Authorize.Net transactions by date range, amount, card type, and status. Display transaction details with customer name, card last four, amount, and settlement status. Add a Refund button that calls Authorize.Net's refund API for selected transactions, with a mandatory confirmation modal before processing.
Build a transaction management panel that sends getTransactionListRequest to Authorize.Net with date range filters, displays results in a Table with transId, amount, settlementStatus, cardNumber (last 4), and customerName, plus a Refund button that triggers createTransactionRequest with transactionType=refundTransaction for the selected row.
Copy this prompt to try it in Retool
Customer payment profile management dashboard
Build a Retool dashboard that allows your support team to look up Authorize.Net customer profiles by email or customer profile ID. Display stored payment methods, shipping addresses, and transaction history for each profile. Add controls to create, update, or delete payment profiles for customer service scenarios.
Create a customer profile management panel with an email search input, a query that calls getCustomerProfileRequest by profile ID, displays stored payment methods and addresses in a Table, and includes action buttons to delete individual payment methods or deactivate the full customer profile.
Copy this prompt to try it in Retool
Daily settlement reconciliation report
Build a Retool financial report that queries Authorize.Net's settled transaction list for each business day, calculates totals by payment method and transaction type, and flags any discrepancies between the settled amount and expected amounts from your order management database. Export the reconciliation data as a downloadable CSV.
Create a settlement reconciliation panel that queries getSettledBatchListRequest for a date range, then for each batch calls getTransactionListRequest to retrieve transaction details, aggregates totals by card type and transaction type using a JavaScript transformer, and shows a summary table with batch ID, total amount, transaction count, and net settlement amount.
Copy this prompt to try it in Retool
Troubleshooting
API returns 'E00007 User authentication failed' on every request
Cause: The API Login ID or Transaction Key in the request body is incorrect, or the credentials are from the sandbox environment being used against the production endpoint (or vice versa).
Solution: Verify your API Login ID and Transaction Key in Authorize.Net merchant interface under Account → Settings → API Credentials & Keys. Ensure you are using sandbox credentials (from sandbox.authorize.net) against the sandbox endpoint and live credentials against the production endpoint. Configuration variable values are stored separately per environment in Retool — verify which environment your resource is pointing to.
refundTransaction returns 'The referenced transaction does not meet the criteria for issuing a credit'
Cause: Authorize.Net has restrictions on when refunds can be processed: the transaction must be in 'settledSuccessfully' status, the refund amount cannot exceed the original transaction amount, and there is a time limit (typically 180 days) after which refunds cannot be issued via the API.
Solution: Confirm the transaction status is 'settledSuccessfully' using getTransactionDetails before attempting a refund. Check that the refund amount (from table_transactions.selectedRow.raw_amount) matches or is less than the original settled amount. For transactions older than 180 days, Authorize.Net requires processing refunds through the merchant interface rather than the API.
Transaction search returns results but they appear to be truncated or missing recent transactions
Cause: Authorize.Net's getTransactionList endpoint only returns transactions within settled batches. Transactions submitted today that have not yet settled (status 'authorizedPendingCapture' or 'capturedPendingSettlement') are only visible via the getUnsettledTransactionListRequest endpoint.
Solution: Create a separate query using getUnsettledTransactionListRequest to fetch today's pending transactions, and combine it with your settled transaction search results using a JavaScript query that merges both arrays. Display both in the same Table with a status column that clearly distinguishes settled from pending transactions.
Customer profile lookup returns 'E00040 Customer Information Manager is not enabled'
Cause: The Authorize.Net account does not have the Customer Information Manager (CIM) add-on enabled. CIM is a paid feature that must be enabled separately in the merchant account settings.
Solution: Contact Authorize.Net's support or your merchant account manager to enable the Customer Information Manager feature. The CIM feature requires a separate activation in the merchant settings and may have additional monthly fees depending on your merchant plan. Once enabled, the getCustomerProfile and related CIM endpoints will become accessible.
Best practices
- Store your Authorize.Net API Login ID and Transaction Key as Secret configuration variables in Retool — embedding credentials directly in query body fields makes them visible to any Retool user who can view the query configuration.
- Always use Authorize.Net's sandbox environment (apitest.authorize.net) during development and testing to avoid processing real charges — maintain a separate sandbox resource in Retool with test credentials.
- Add status-based conditional logic to Void and Refund buttons — only enable Void for transactions in 'authorizedPendingCapture' status and Refund for 'settledSuccessfully', preventing error responses from attempting invalid operations.
- Normalize Authorize.Net's single-item vs. array response behavior in every JavaScript transformer by checking if the result is an array before mapping over it — responses with a single item return an object, not a one-element array.
- Include the refId field in all Authorize.Net write requests (use a timestamp or UUID) so you can correlate Retool query executions with Authorize.Net transaction logs during debugging and auditing.
- Combine Authorize.Net transaction data with your order management database in the same Retool app to enable quick reconciliation between payment gateway records and internal order records without switching between systems.
- Use Retool Workflows to schedule daily settlement reconciliation reports that compare Authorize.Net batch totals with your order database totals and flag discrepancies for your finance team.
Alternatives
Stripe has a native connector in Retool with simpler JSON REST authentication and a more developer-friendly API design, while Authorize.Net is preferred for businesses with existing merchant agreements or specific compliance requirements that Stripe doesn't meet.
Braintree (PayPal) offers both REST and GraphQL APIs with simpler authentication than Authorize.Net, and is preferred for businesses integrated with PayPal's payment ecosystem or needing Venmo and PayPal wallet support.
Worldpay handles high-volume enterprise payment processing with global acquiring capabilities, while Authorize.Net is more commonly used by small-to-mid-size North American merchants requiring a reliable, long-established gateway.
Frequently asked questions
Does Authorize.Net have a native connector in Retool?
No, Authorize.Net does not have a native connector in Retool. You connect it using a generic REST API Resource targeting Authorize.Net's JSON API endpoint. The key difference from most REST APIs is that Authorize.Net includes authentication credentials in the JSON request body (merchantAuthentication object) rather than HTTP headers, so the Resource itself has no authentication configured — all auth is included per-query in the body.
What is the difference between Authorize.Net's XML API and JSON API?
Authorize.Net has two API formats: the original XML-based SOAP API and the newer JSON REST API (api2.authorize.net). Both go through the same endpoint URL but accept different content types. For Retool integrations, always use the JSON API by setting Content-Type: application/json and formatting request bodies as JSON objects. The JSON API is simpler to work with in JavaScript transformers and does not require XML parsing.
How do I test Authorize.Net integration in Retool without real charges?
Use Authorize.Net's sandbox environment: create a developer account at developer.authorize.net to get sandbox API credentials (separate from your production credentials). Configure a second Retool resource with base URL https://apitest.authorize.net/xml/v1/request.api and your sandbox credentials. Use Authorize.Net's test card numbers (4111 1111 1111 1111 for Visa, 5424000000000015 for Mastercard) in test transaction submissions. The sandbox behaves identically to production but does not process real charges.
Can I use Retool to process new payment charges through Authorize.Net?
Yes, using the createTransactionRequest with transactionType: authCaptureTransaction. However, Retool should never handle raw cardholder data directly — use Authorize.Net's Accept.js library to collect card data on the client side (returning an opaque token), then pass that token to Authorize.Net's API via Retool. This approach maintains PCI compliance by ensuring raw card numbers never pass through Retool's servers.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation