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.
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.
What does this prompt do?
- 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 do I need to use this?
- 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
How can I customize it?
- 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
FAQs
Why can't I refund a payment that was made today?
Do my billing and support reps need their own payment gateway logins?
What if a payment settles in between the rep searching and the rep clicking?
Can I stop reps from reversing large amounts without an explanation?
Will there be a record of who refunded what?
Related templates
Stop buying stale lists. Reps run a saved search, work the results like an inbox, and only the accounts they approve ever reach your CRM.
Pick a date, a starting point and a radius, then build a sequenced day of customer visits that lands straight on your calendar.
One screen where reps filter for companies that fit, see who is actually reachable at each account, and save only the addresses that verify.
Search creators for free, shortlist the best with your team, and spend an audit credit only when you decide someone is worth a closer look.
One screen showing invited, completed, and shortlisted counts for every open role, plus the stalled invites that have quietly gone nowhere.
See every competitor battlecard next to the number of open deals that name that competitor, so the cards carrying real pipeline get refreshed first.
Stop hunting through the payment gateway to fix one charge.
Give your billing and support team one screen that finds any payment and reverses it correctly the first time.