Create, cancel or close a purchase order

Creates, cancels and closes purchase orders from the conversation, with pre-checks and a confirmation before each action.

ProcurementControlleršŸ“… WeeklyExpertCan make changes

Ask it like this

Create a purchase order for €12,000 gross for Accenture on the Tech cost center, from 1 November to 31 January.

When to use it

When you open a supplier engagement, cancel a purchase order created by mistake or close one that is settled.

What it produces

The summary to confirm (supplier, amount, cost center, period), then the purchase order number and its state read back after the action.

How it works

  1. 1Finds the supplier and cost center involved
  2. 2Has you confirm supplier, amount, cost center and period
  3. 3Creates the purchase order and gives you its number
  4. 4Checks whether a purchase order can be cancelled or closed
  5. 5States what cannot be undone and waits for your go-ahead
  6. 6Reads the purchase order back to confirm its new state

What protects you

  • This skill can change Spendesk data: every action waits for your confirmation
  • Write actions are in Beta and off by default: an Admin or Account Owner enables them
  • It acts with your permissions and your role, never beyond
  • The assistant cannot approve or pay
ā–øTechnical detail82/100 Ā· 5 tools
Budget & POsSuppliersget_suppliersget_cost_centersget_purchase_orderscreate_purchase_ordercancel_purchase_order

# Purchase order lifecycle

## āš ļø Write tools in Beta, two of them irreversible

`create_purchase_order`, `cancel_purchase_order` and `close_purchase_order` need the "Manage purchase orders" permission, off by default: an Admin or Account Owner enables it on the connection, then the user reconnects and ticks it.

| Action | Can it be undone? |
|--------|-------------------|
| Create | Cannot be deleted. Only recourse: cancel, while it is open with no invoice |
| Cancel | **Irreversible** |
| Close | **Irreversible**, and the amount is rewritten |

A purchase order is never deleted. A terminal status (`closed` or `cancelled`) cannot move to the other.

## Create a purchase order

### 1. Resolve the supplier and the cost center

```json
{ "tool": "get_suppliers", "params": { "search": "<supplier name>" } }
```

Pass `supplierId` whenever a supplier matches. `supplierName` creates a supplier on the fly when the name does not match exactly: "Acme Corp." against "Acme Corp" creates a **second supplier** and splits the history.

```json
{ "tool": "get_cost_centers", "params": {} }
```

`costCenterId` is required.

### 2. Confirm with the user, then create

Restate the supplier, the amount, the cost center and the period, and wait for the go-ahead.

```json
{
  "tool": "create_purchase_order",
  "params": {
    "supplierId": "<id>",
    "amount":    { "amount": 12000, "currency": "EUR", "precision": 2 },
    "netAmount": { "amount": 10000, "currency": "EUR", "precision": 2 },
    "costCenterId": "<id>",
    "startDate": "2026-10-05", "endDate": "2026-10-31",
    "customFieldAssociations": [],
    "description": "…"
  }
}
```

- Amounts are in **minor units** of the functional currency: `12000` = EUR 120.00. `amount` includes tax, `netAmount` excludes it, and `amount` ≄ `netAmount`.
- `customFieldAssociations` is required: pass `[]` when there are none.
- Observed response: `purchaseOrderId` and `purchaseOrderNumber` ("PO-20").

āš ļø Two points verified live:
- **The purchase order is open immediately** (`status: open`, `billingStatus: waitingForBilling`): creation through this tool goes through no visible approval step. Tell the user before creating.
- **The tool is not idempotent**: a second call creates a second purchase order. If the outcome is unclear (timeout), check with `get_purchase_orders` before trying again.

## Cancel a purchase order

### 1. Check it can be cancelled

```json
{ "tool": "get_purchase_orders", "params": { "status": ["open"], "supplierIds": ["<id>"] } }
```

It can only be cancelled when it is `open`, with **no invoice attached** (`invoices: []`) and **no associated expense**.

### 2. Name the purchase order and get an explicit go-ahead

Give its number, its supplier (resolve `supplierId` to a name) and its amount, state that it cannot be undone, wait for the go-ahead. Checking the data is not approval.

```json
{ "tool": "cancel_purchase_order", "params": { "purchaseOrderId": "<id>" } }
```

Observed response: `{ "outcome": "cancelled", … }`. The purchase order stays visible with `status: cancelled`; when read back, it no longer carries `billingStatus` or `costCenterId`.

A second call on the same purchase order returns an explicit error ("the purchase order is not in open status"): that is an answer, not a failure to retry.

## Close a purchase order

Only possible when it is `open`, with **at least one invoice attached and every invoice paid**.

```json
{ "tool": "close_purchase_order", "params": { "purchaseOrderId": "<id>" } }
```

āš ļø **Closing rewrites `amount` to the billed amount.** The originally approved budget can no longer be read afterwards: a purchase order approved at 10,000 and billed 8,000 will show 8,000. If the user needs to keep track of the approved amount, note it before closing. Closing can also fail on the spending-commitment side: read the reason rather than retrying.

## Limits to state

- `amount āˆ’ billedAmount` never reveals an overrun: `get_purchase_orders` cannot answer "which purchase orders went over budget".
- A purchase order stays `open` after its end date: nothing closes it automatically.
- The MCP cannot approve a purchase order request or pay an invoice.

## What was tested

Tested live on the demo account on 5 October 2026: creating purchase order PO-20 (EUR 120.00 gross, existing supplier), reading it back as open, cancelling it, reading it back as cancelled, and a second cancel call to observe the error. **Closing was not run** (it needs a purchase order with paid invoices); it is described from the tool's documentation.

## Example user prompts

- "Create a purchase order for €12,000 gross for Accenture on the Tech cost center, from 1 November to 31 January"
- "Cancel purchase order PO-20, it was created by mistake"
- "Which open purchase orders are fully invoiced and paid, and can be closed?"

How to install this skill

/
  1. 1
    Download the file s77-cycle-de-vie-bons-de-commande.md using the button above.
  2. 2
    Place the file in the .claude/ directory of your project (or ~/.claude/ for a global install).
    cp s77-cycle-de-vie-bons-de-commande.md .claude/s77-cycle-de-vie-bons-de-commande.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_suppliers, get_cost_centers, get_purchase_orders, create_purchase_order, cancel_purchase_order.

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?