Match invoices to purchase orders
Finds invoices with no purchase order and purchase orders waiting for an invoice, from the real link between the two.
AP ManagerProcurement๐
WeeklyIntermediateRead-only
Ask it like this
Do all my invoices this month have a purchase order?
When to use it
Every week, to check that received invoices are attached to a purchase order and spot purchase orders with no invoice.
What it produces
Invoices with no purchase order per currency, purchase orders waiting for or late on billing, and visible overruns.
How it works
- 1Lists recent invoices and reads their attached purchase order
- 2Isolates invoices with no purchase order, per currency
- 3Lists open purchase orders and their billing status
- 4Flags those waiting for an invoice or whose invoice is late
- 5Reports visible overruns, stating what cannot be detected
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 detail72/100 ยท 3 tools
Budget & POsReconciliationget_invoicesget_purchase_ordersget_supplier_by_id
# Invoice โ purchase order matching
## The link exists: do not reconstruct it
Spendesk records which purchase order an invoice is attached to, and the MCP exposes it on both sides:
- on an invoice, `purchaseOrders` lists the attached purchase orders (empty when there are none);
- on a purchase order, `invoices` lists its invoices, and `billingStatus` sums up billing progress.
**Do not match "by eye"** on supplier and amount: a supplier can have several purchase orders, and an invoice from a supplier under purchase order may well not be attached to it. Read the real link.
This skill changes nothing: attaching an invoice to a purchase order is done in Spendesk.
## Step 1 โ Invoices with no purchase order
```json
{
"tool": "get_invoices",
"params": { "approvalStatus": ["pending", "approved"], "createdAfter": "YYYY-MM-DD", "pageSize": 100 }
}
```
State the start date used (by default, the last 60 days).
- An invoice whose `purchaseOrders` is empty is an **invoice with no purchase order**.
- Page with `cursor` while `hasNextPage` is `true`.
- With no `type` filter, only invoices are listed; credit notes need a separate call and are not part of this check.
- Amounts are in each invoice's own currency: total per currency, never together.
- Some suppliers have no purchase order by nature (subscriptions, utilities): ask the user which to exclude rather than flagging them all.
To check the invoices of one specific purchase order, filter with `purchaseOrderId`.
## Step 2 โ Open purchase orders and their billing
```json
{ "tool": "get_purchase_orders", "params": { "status": ["open"], "pageSize": 100 } }
```
Read on each purchase order: `amount`, `billedAmount`, `endDate`, `invoices` and `billingStatus`.
| `billingStatus` | Reading |
|-----------------|---------|
| `waitingForBilling` | No invoice received so far |
| `lateInvoice` | An expected invoice is late: chase first |
| any other value | Billing in progress or complete: read `billedAmount` |
Also flag purchase orders whose `endDate` has passed and that are still open: nothing closes them automatically.
## Step 3 โ What can be said about overruns
โ ๏ธ **An overrun is not always detectable.** `amount` is the **current** committed amount, not the originally approved one: depending on company configuration, Spendesk realigns it to the billed amount when an invoice exceeds it, and always on closing. A purchase order approved at 10,000 and billed 14,000 can therefore show 14,000 on both sides.
- If `billedAmount` > `amount`: flag it, that is a visible overrun.
- If `billedAmount` โค `amount`: **do not conclude there is no overrun**. Say the originally approved amount is not available.
## Step 4 โ Resolve names
`supplierId` on a purchase order is a raw ID:
```json
{ "tool": "get_supplier_by_id", "params": { "id": "<supplierId>" } }
```
Invoices already carry `supplier.name`.
## Report
```
Invoice โ purchase order matching โ <today's date>
Invoices with no purchase order (since <date>): N โ X EUR ยท Y GBP
| Invoice | Supplier | Amount | Due date | Approval status |
Purchase orders waiting for an invoice: N
| No. | Supplier | Committed amount | Period end | Billing status |
Visible overruns: N (others cannot be detected, see limit)
```
## Observed result (demo account, 5 October 2026)
13 open purchase orders, none billed (`invoices` empty and `billedAmount` at zero everywhere). Twelve were `waitingForBilling` and one `lateInvoice`: a purchase order whose period had ended on 31 December 2025. The 5 most recent invoices had no purchase order attached.
## Example prompts
- "Do all my invoices this month have a purchase order?"
- "Which open purchase orders are still waiting for an invoice?"
- "Show me the invoices with no purchase order received this quarter"
How to install this skill
/
- 1Download the file
s53-invoice-po-matching.mdusing the button above. - 2Place the file in the
.claude/directory of your project (or~/.claude/for a global install).cp s53-invoice-po-matching.md .claude/s53-invoice-po-matching.md - 3Use 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_purchase_orders, get_supplier_by_id.Similar skills
โ
Top
โ
Top