Spot invoices entered twice

Detects invoice duplicates by identifying payables from the same supplier with identical or very close amounts over a short period.

ControllerAP Manager๐Ÿ“† MonthlyIntermediateRead-only

Ask it like this

Are there any duplicate invoices over the last 3 months?

When to use it

Before a payment run, to avoid paying the same invoice twice.

What it produces

List of suspect invoice pairs with supplier, amounts, dates, and duplicate confidence level.

How it works

  1. 1Lists the period's supplier invoices
  2. 2Spots those with the same number from the same supplier
  3. 3Spots those of the same amount a few days apart
  4. 4Checks whether one of the two has already been paid
  5. 5Presents the pairs to check, most urgent first

What protects you

  • This skill only reads: it changes nothing in Spendesk
  • It acts with your permissions and your role, never beyond
  • The assistant cannot approve or pay
โ–ธTechnical detail65/100 ยท 2 tools
ReconciliationSuppliersget_invoicesget_invoice_by_id

# Duplicate invoice detection

## Purpose

Spot supplier invoices that may have been entered twice, **before** they are paid twice. Two signals: the same invoice number from the same supplier, or the same amount from the same supplier a few days apart.

There is no duplicate detection in the MCP: this is a comparison the assistant makes on the invoice list. The result is a list of pairs **to check**, not a list of confirmed duplicates. The skill deletes and blocks nothing.

## Step 1 โ€” List the period's invoices

State the period (the last 3 months by default).

```json
{
  "tool": "get_invoices",
  "params": { "issuedAfter": "YYYY-MM-DD", "issuedBefore": "YYYY-MM-DD", "sortBy": "issueDate", "pageSize": 100 }
}
```

Each invoice already carries what is needed: `invoiceNumber`, `supplier.id` and `supplier.name`, `grossAmount`, `currency`, `issueDate`, `approvalStatus`, `paymentStatus`.

- With no approval filter, the list holds pending, approved **and rejected** invoices: keep the rejected ones, a duplicate has often been rejected once already.
- With no `type` filter, credit notes are not listed: that is intended, a credit note is not a duplicate.
- Page with `cursor` while `hasNextPage` is `true`; conclude nothing from a partial list.
- `grossAmount` can be `null` on a pending invoice: leave it out of the amount comparison.

## Step 2 โ€” Same invoice number

Group by (`supplier.id`, `invoiceNumber`), comparing numbers regardless of case and spaces. Any group of two invoices or more is a **likely duplicate**.

To check one specific number across the whole history, the `invoiceNumber` filter does an exact search.

## Step 3 โ€” Same amount, close dates

Group by (`supplier.id`, `grossAmount`, `currency`). In each group, flag invoices whose `issueDate` values are 5 days apart or less: **possible duplicate**.

Do not flag a supplier that bills the same amount every month (rent, subscription): the one-month gap already rules those out; say so if the user widens the window.

## Step 4 โ€” Qualify each pair

For the pairs kept:

```json
{ "tool": "get_invoice_by_id", "params": { "id": "<invoice id>" } }
```

Read `payments` (has one of the two already been paid?), `attachments` (are the two documents the same file?) and `purchaseOrders`. This tool's payment status is authoritative for a given invoice.

Order of priority:

1. both invoices approved and unpaid โ€” the double payment can still be avoided;
2. one paid, the other approved;
3. both paid โ€” to flag for recovery.

## Report

```
Possible duplicates โ€” invoices issued from <date> to <date> (N invoices checked)

Likely duplicates (same number): N pairs
| Supplier | No. | Amount | Date 1 | Date 2 | Payment 1 | Payment 2 |

Possible duplicates (same amount, 5 days or less): N pairs
| Supplier | Amount | Date 1 | Date 2 | Gap | Payment 1 | Payment 2 |
```

## Limits to state

- The same amount from the same supplier a few days apart can be legitimate (partial deliveries).
- Two different supplier records for one supplier escape the comparison: it works by supplier ID.
- The assistant cannot reject or delete an invoice: the decision is made in Spendesk.

## What was verified

The fields used were verified live on the demo account on 5 October 2026. The comparison itself was not replayed on all of the account's invoices.

## Example prompts
- "Are there any duplicate invoices over the last 3 months?"
- "Check for potential duplicates before my next payment run"
- "Was invoice INV-2026-7734 entered twice?"

How to install this skill

/
  1. 1
    Download the file s47-duplicate-invoice-detection.md using the button above.
  2. 2
    Place the file in the .claude/ directory of your project (or ~/.claude/ for a global install).
    cp s47-duplicate-invoice-detection.md .claude/s47-duplicate-invoice-detection.md
  3. 3
    Use in Claude Code โ€” the skill is automatically discovered. Describe your need in natural language and Claude will apply the skill instructions.
๐Ÿ’ก Make sure the Spendesk MCP is configured in your .claude/settings.json with the tools get_invoices, get_invoice_by_id.

Similar skills

โ˜… Top
95/100ยท๐Ÿ” Ad hocยทExpert

Audit what the MCP covers

Probes all available MCP tools, re-evaluates coverage of 50 persona use cases, detects new fields or tools, and regenerates the gap analysis report.

CFOControllerAP Manager
90/100ยท๐Ÿ“… WeeklyยทBeginner

Card requests via get_requests

Explains how to use get_requests for card requests and why expense reimbursements don't appear there. Avoids a frequent source of confusion between two distinct workflows.

ControllerFinance Analyst
90/100ยท๐Ÿ” Ad hocยทIntermediate

Active vs archived cost centers

Distinguishes active cost centers from archived ones with correct use of get_cost_centers. Avoids the counter-intuitive isArchived vs isActive naming convention pitfall.

ControllerFinance Analyst

Interested in AI Agent services or Custom Integrations?