How to

How to build an invoice approval queue

Invoices arrive in an inbox, get forwarded twice, and surface again as an overdue notice. Here is the model behind a queue that holds them, the prompts to build it, and what it takes to run it.

The short answer

An invoice approval queue is four parts: intake that captures every invoice however it arrived, a match against the purchase order that authorised it, an exception path for the ones that do not match, and a payment-ready list. The work is not the approving, it is the matching: most invoices should clear automatically against something already approved, and the queue exists for the ones that do not. Build it so the exceptions are the visible part and the matches are quiet.

invoice-queue.helix-app.ai

Invoice queue

9

Exceptions to clear

214

Cleared automatically

2

Suspected duplicates

3 days

To next discount deadline

Supplier Invoice Amount Why it is here Due
Kestrel Ltd KL-4471 31,000 No purchase order 11 days
Apple AP-99120 26,880 Over tolerance by 340 6 days
Harbon LLP H-2210 9,500 Unknown supplier 14 days
Figma FG-8801 18,400 Possible duplicate 9 days
Northrise NR-114 4,120 Quantity mismatch 2 days
A sketch of the exception queue. It only shows invoices that did not match: the 214 that did never appear here, which is the whole point.

What matters here

  • An invoice queue is four parts: intake, matching against what was already approved, an exception path, and a payment-ready state.
  • Most invoices should never need a human. If everything lands in a queue for review, the queue is a re-approval process rather than an exception process.
  • Three-way matching means invoice, purchase order and receipt of goods or service agree. Two-way skips the receipt, which is common for services and fine if you know that is the trade.
  • Tolerance thresholds are what make auto-matching usable. An invoice that differs by rounding should clear; one that differs by 30% should not.
  • Duplicate detection belongs at intake, not at payment. The same invoice arriving twice by two routes is the most common and most expensive error.
  • The queue reads and writes to a finance system, so managed credentials and a named owner are not optional extras.

Who this is for

You run accounts payable or finance operations. You already know your approval matrix and your payment terms. What you want is for the invoices that match what was approved to clear without a human, and for the ones that do not to be obvious.

How it works in practice

What happens to an invoice from the moment it arrives to the moment it is paid.

  1. 1

    It lands in one place

    However it arrived, emailed, portal or scan, it becomes one record with the supplier, number, amount and any purchase order reference.

  2. 2

    Duplicates get caught at the door

    Same supplier and number, or same supplier, amount and a nearby date, gets flagged before anything else touches it.

  3. 3

    Most invoices clear without a human

    If it matches the purchase order within tolerance, it clears and goes straight to the payment-ready list, with a record of what it matched.

  4. 4

    The rest become exceptions with a reason

    No order, over tolerance, quantity mismatch, unknown supplier. Each routes to whoever can resolve that kind, not to a shared pile.

  5. 5

    An approver sees the discrepancy, not two documents

    Invoice on one side, order on the other, difference highlighted. No opening attachments to find the gap.

  6. 6

    Payment-ready, with the discount dates in view

    A clean list of what is approved to pay, sorted by due date, with early-payment windows flagged before they close.

What an invoice queue is made of

An invoice queue is not an inbox with rules. It is four parts, and the second is the one that decides whether the tool saves time or just moves the pile.

Intake

Every invoice in one place, however it arrived: emailed PDF, supplier portal, or a forwarded scan. Capture supplier, invoice number, date, amount, currency, line items and the purchase order reference if there is one.

Matching

Compare the invoice against the purchase order or approval that authorised it. Agreement within tolerance clears automatically. Anything else becomes an exception with a reason attached.

An exception path

The queue proper: mismatched amounts, missing purchase orders, quantities that do not reconcile, suppliers nobody recognises. Each exception routes to whoever can resolve that kind, not to a general pile.

Payment ready

A clean, dated list of what is approved to pay, with the evidence attached. This is the handoff to whoever runs the payment run, and it is what an auditor asks to see.

These prompts start from a Helix project, which is what handles sign-in, credentials and hosting. Start with Helix

The prompts

Paste these into Claude Code, Codex or Cursor in order. Each one leaves you with something that runs, so you can stop after any step.

  1. Every invoice in one place, duplicates caught

    Intake, and the single most expensive error in accounts payable.

    In this Helix project, build me an invoice approval queue.
    
    Start with intake. Every invoice becomes one record: supplier, invoice
    number, dates, currency, totals, line items, and the purchase order
    reference if there is one. Let me type one in and attach the original
    document.
    
    Before anything else touches a new invoice, check whether we have seen it
    before. Flag it if the supplier and invoice number already exist, and flag
    it if the supplier, total and date are all close to something we already
    have. Show me the suspected duplicate side by side rather than rejecting
    it. The same invoice arriving twice by two routes is the most common
    mistake in this whole process and it costs real money.
    
    I sign in through Helix, so do not build a login page. Read the signed-in
    user from the runtime. And do not put any key or connection string in the
    code: if this needs to reach another system, tell me and I will create the
    connection in my workspace.

    Worth knowing. Duplicate detection has to run first. Catching it at intake costs one prompt; catching it at payment costs a supplier conversation.

  2. Matching, so most invoices never reach a person

    The part that decides whether this saves time or just moves the pile.

    Now match invoices against what was actually approved.
    
    I will give you purchase orders with their line items. Match each invoice
    by reference, and fall back to supplier plus amount when the reference is
    missing, because it often is.
    
    Set tolerances in one place I can edit: an absolute amount and a
    percentage, whichever is smaller. Inside tolerance, the invoice clears on
    its own and goes to the payment-ready list. Outside it, or with no order
    at all, it becomes an exception with the reason attached.
    
    Every automatic clearance still writes down what it matched and why. "It
    cleared automatically" is a decision, and somebody will eventually ask
    what it matched against.
  3. The exception queue

    The screen a person opens, and what has to be on it.

    Build the queue itself, and only put exceptions in it.
    
    Each row shows what the invoice says, what the order said, and the
    difference between them, next to each other. An approver should never have
    to open two documents to find a discrepancy.
    
    Route each type of exception to whoever can resolve that type. Missing
    order, over tolerance, quantity mismatch, unknown supplier, suspected
    duplicate. A single shared pile means everything waits for whoever looks
    first.
    
    Actions: approve anyway with a reason, reject with a reason, send back to
    the supplier, or reassign. Sort by days to the payment due date, because
    paying late is the actual cost of a slow queue.
  4. Ready to pay, and the record behind it

    The handoff, and the evidence.

    Finish with the payment-ready list.
    
    Everything approved and not yet paid, grouped by supplier, sorted by due
    date, with early-payment discount windows flagged before they close. A
    queue that pays on time is table stakes. One that catches the discount
    pays for itself.
    
    Let me export a batch for the payment run and mark it paid so it leaves
    the list.
    
    And keep an appended record of every state change, with who, when, and
    what the invoice and the match looked like at that moment. Give me a
    supplier view too: every invoice from one supplier and its status, which
    is what I need open when they ring.
  5. Connect it to real systems

    The step that turns a working prototype into something with your data in it.

    Now connect it to the systems we actually run, so it works on real data
    rather than the rows you seeded.
    
    Anything in angle brackets is a placeholder. Swap it for whatever we use
    instead, and have the app name the connection it wants rather than assume
    a vendor, so changing my mind later is a config change and not a rewrite.
    
    <NetSuite>. Read purchase orders to match against, and push the approved
    payment batch back.
    
    <Gmail>. Pull invoices that arrive as attachments, so intake is not
    somebody retyping them.
    
    <Slack>. Tell an approver an exception is waiting, with the discrepancy in
    the message.
    
    <Google Drive>. Keep the original invoice attached to its record for the
    audit trail.
    
    <Coupa>. Read the purchase orders and receipts that three-way matching
    needs.
    
    <Snowflake>. Land cleared invoices next to the purchase orders, so spend
    by supplier and by cost centre is one join rather than two exports.
    
    <Brex>. Match card-paid invoices, which otherwise arrive twice and get
    paid twice.
    
    Only write where I have said to write. Everything else is read only.
    
    Do not write a key, a token or a connection string anywhere in the code,
    and do not ask me to paste one. Tell me which connections you need and I
    will create each as an authentication in my Helix workspace. Reference
    them by alias.

    Worth knowing. Every name in angle brackets is a placeholder for whatever you run. Helix holds the credential as a workspace authentication, so the app references an alias and never the secret itself.

  6. Ship it

    The last step of every build: a URL, and the right people on it.

    Deploy my app.

    Worth knowing. Your assistant runs helix deploy underneath and the app comes back as a URL. This app decides what money leaves the company, so set Access Control before sharing and scope it to the people whose approvals actually count.

What it connects to

An invoice queue is only as good as what it can see, and most of what it needs already lives somewhere else.

  • NetSuite

    Read purchase orders to match against, and push the approved payment batch back.

  • Gmail

    Pull invoices that arrive as attachments, so intake is not somebody retyping them.

  • Slack

    Tell an approver an exception is waiting, with the discrepancy in the message.

  • Google Drive

    Keep the original invoice attached to its record for the audit trail.

  • Coupa

    Read the purchase orders and receipts that three-way matching needs.

  • Snowflake

    Land cleared invoices next to the purchase orders, so spend by supplier and by cost centre is one join rather than two exports.

  • Brex

    Match card-paid invoices, which otherwise arrive twice and get paid twice.

Each line says whether the app reads, writes or both. Anything not described as writing should be read only.

Named systems are the ones most teams actually run, not a list of the only ones that work. Swap in whatever you use.

Each connection is an authentication in your Helix workspace, referenced by alias. The app names the connection it wants and never holds the credential, so nothing here ends up in your code and any of it can be rotated or revoked without a redeploy.

Running it for real

The build gets you a working queue. It holds supplier data, decides what gets paid, and writes to a finance system, so it has to be run properly before it touches a real payment run.

AI Deployment

Get it to a URL people can open

One command takes the app from your assistant to a live address, so the people who need it get a link rather than instructions for running it locally.

App Security

Put your identity provider in front of it

An invoice queue decides what money leaves the company. SSO means approvers sign in with their existing account, and access is scoped to the people whose approvals count.

App Security

Connect the finance system with managed credentials

Reading purchase orders and writing payment-ready batches needs real access. Granting it to the app rather than pasting a key into it means it can be rotated or revoked without a redeploy.

App Registry

Put a name on it

Every app carries a named owner and an entry IT can see, so the tool does not become nobody's problem when the person who built it changes role.

Cost Management

Know what it costs to run

Per-app spend visibility, with budgets and caps, so an internal tool cannot quietly become a line item nobody can explain.

Questions people ask

What is an invoice approval queue?

It is a single place every supplier invoice lands, gets matched against the purchase order or approval that authorised it, and either clears automatically or becomes an exception for a person to resolve. The queue is for the exceptions. If every invoice needs review, the process is re-approving what was already approved.

What is the difference between two-way and three-way matching?

Two-way matching compares the invoice against the purchase order. Three-way also requires a record that the goods or service were actually received. Three-way is stronger and slower, and is usually reserved for physical goods; services often run two-way because a receipt record does not naturally exist.

How do I stop paying duplicate invoices?

Detect them at intake rather than at payment. Flag any invoice where the supplier and invoice number already exist, and any where supplier, total and date are close to an existing record. The same invoice arriving twice by two routes is the most common accounts payable error.

What tolerance should invoice matching use?

Set both an absolute amount and a percentage and take whichever is smaller, so rounding differences clear and proportionally large gaps do not. The right numbers depend on your spend profile, which is why they belong in one editable file rather than buried in logic.

What should the audit trail capture?

Every state change, appended not edited, with who did it, when, and a snapshot of the invoice and the match result at that moment. Automatic clearances need a record too: "it matched" is a decision, and an auditor will ask what it matched against.

Can I build this without an engineering team?

Yes. The prompts here are written for Claude Code, Codex or Cursor and stage the build, so you can stop after any of them and still have something that runs. What no tool decides for you is your tolerance thresholds and which categories need a three-way match.

Last reviewed September 2026.

Build it, then run it properly

Helix is the governed runtime for AI-built apps. Deploy what you build, put SSO in front of it, connect it to your systems with managed credentials, and give it a named owner.