# Void or refund Authorize.Net payments from one search screen

> A payment lookup console for billing and support: search any recent charge, see the customer's CRM history beside it, and reverse it the right way in one click.

- Workflow type: app
- Services: Authorize.Net, HubSpot, Slack
- Categories: Customer Support, Finance
- Published: 2026-08-14

## What it does

- Search every recent payment from one box by email, name, amount, or transaction id, covering both charges still waiting in tonight's batch and charges from earlier settled batches.
- Works out the correct reversal itself and shows a single button per payment: void while the charge is still pending, refund once it has cleared. Reps stop getting their refunds rejected for being too early.
- Shows the customer's CRM record right next to the payment, so a rep can see who they are dealing with before touching any money.
- Posts every void and refund to a Slack channel with the rep's name, the amount, and their stated reason, writes the same note onto the customer record, and keeps a permanent in-app log of who reversed what.

## What you'll need

- An Authorize.Net merchant account with API access turned on
- A HubSpot account where your customers exist as contacts
- A Slack workspace and a channel where payment reversals should be announced
- A decision on the dollar amount above which a written reason should be mandatory

## Prompt

Build me an internal app my billing and support team opens whenever a customer questions a charge, so nobody on the team needs an Authorize.Net login of their own. The whole app is anchored on one rule that Authorize.Net enforces and that my reps keep getting wrong: a transaction sitting in the unsettled queue cannot be refunded, it has to be voided, and only a transaction that has already settled can be refunded. The app should work out which of those two applies and offer only that action, rather than showing both and letting someone pick wrong.

The main screen is a payment search. A rep types an email address, a customer name, a dollar amount, or a transaction id into a single box and gets back matching payments. Build the results from two sources and merge them. First, Get Unsettled Transaction List for everything still waiting in tonight's batch. Second, Get Settled Batch List to enumerate the recent settled batches, then Get Transaction List for each of those batches to pull their transactions. Authorize.Net list operations do not accept a free-text search term, so the handler should fetch the candidate set and filter it server side against whatever the rep typed, matching on customer name, email, amount, and transaction id. Dedupe by transaction id. Keep how far back the settled search reaches configurable, defaulting to about the last thirty days, and be aware that the settled batch list paginates by settlement date over roughly a thirty-one day window rather than by offset.

Each result row shows the customer name, email, amount, date, card last four, and status, plus a clear settlement badge saying either that the charge is still pending in tonight's batch or that it settled, with the settlement date. Clicking a row opens the full record via Get Transaction Details, showing the complete payment detail including line items, billing address, card type, authorization code, and the current transaction status.

Every payment, in the list and in the detail view, gets exactly one action button, chosen by the app from the settlement state. Pending charges get a Void button. Settled charges get a Refund button. Both are submitted through Create Transaction, using the void transaction type with the original transaction id as the reference for a void, and the refund transaction type with the original transaction id, the card last four, and the amount for a refund. Never render both buttons at once, and never render a refund button on something unsettled. Because a batch can settle between the moment the rep searched and the moment they click, re-check the transaction's current state with Get Transaction Details at submit time and switch to the correct action instead of letting the gateway reject it with a cryptic error. Read the response properly: check the top level result code, then the transaction response code, and surface a plain-English success or failure message rather than a raw error code.

Next to each payment, show the customer's CRM context pulled from HubSpot. Look the contact up with Get Contact using the email address from the transaction via the idProperty parameter, and fall back to Search Contacts when there is no email match or when the rep searched by name. Show enough for a rep to know who they are talking to: name, company, lifecycle stage, contact owner, and recent activity. If no contact matches, say so plainly and still allow the reversal.

Add a reason box on the reversal. Let me set a threshold amount in settings, and for any payment above that threshold the action button stays disabled until the rep has typed a reason. Below the threshold a reason is optional but still captured. The reason travels with everything downstream.

When a void or refund succeeds, do two things. Post to a Slack channel with Send a Message, including the rep's name, the customer, the amount, whether it was a void or a refund, the transaction id, and the reason they typed. Then write the same note back onto the customer's HubSpot record with Create Note, associated to the contact so it shows on their timeline. If the Slack post or the note fails, the reversal still happened, so show that clearly rather than implying the money was not moved.

Keep a permanent in-app log of who reversed what, stored in the app's own database so it survives regardless of what happens in the gateway or the CRM. Each entry records the timestamp, the rep who acted, the customer, the transaction id, the amount, whether it was a void or a refund, the reason given, and whether the gateway accepted it. Give this its own screen with search and filtering by rep, date range, and action type. Nothing in the app should ever delete or edit a log entry.

Finally, a small settings screen for the threshold amount, the Slack channel, and how many days back the settled payment search reaches.

## How to customize

- Set the amount above which the button stays locked until the rep types a reason, and raise or lower it as your team earns trust
- Choose which Slack channel receives reversal notices and how far back the search reaches across past settled batches
- Change what customer detail appears beside each payment, such as lifecycle stage, account owner, or open deals

## FAQ

### Why can't I refund a payment that was made today?

Payment processors will not refund money that has not actually moved yet. A charge taken today sits in a pending batch until it settles overnight, and until then the only way to reverse it is to void it. That is the single most common mistake in payment support, and it is exactly why this app decides for you: it shows a void button on pending charges and a refund button on settled ones, so a rep never has to know the rule.

### Do my billing and support reps need their own payment gateway logins?

No, and that is the point. The app connects to the gateway once, and reps work entirely inside it. Nobody needs a merchant account login, so you are not handing out credentials to a system where someone could also change settings or view unrelated data.

### What if a payment settles in between the rep searching and the rep clicking?

The app re-checks the payment's status at the moment the button is pressed. If the charge settled in the meantime, it switches to a refund instead of failing with a confusing gateway error, and tells the rep what happened.

### Can I stop reps from reversing large amounts without an explanation?

Yes. You set a threshold amount, and any payment above it keeps its button disabled until the rep types a reason. That reason then travels with the reversal into Slack, onto the customer's record, and into the permanent log.

### Will there be a record of who refunded what?

Every void and refund is written to a log inside the app that does not get cleared, showing the rep, the customer, the amount, the action taken, the reason, and whether the gateway accepted it. The same details are posted to Slack and saved as a note on the customer's CRM record.

Use this prompt in General Input: https://www.generalinput.com/prompts/void-or-refund-authorizenet-payments-from-one-search-screen