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
- 1Finds the supplier and cost center involved
- 2Has you confirm supplier, amount, cost center and period
- 3Creates the purchase order and gives you its number
- 4Checks whether a purchase order can be cancelled or closed
- 5States what cannot be undone and waits for your go-ahead
- 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
/
- 1Download the file
s77-cycle-de-vie-bons-de-commande.mdusing the button above. - 2Place 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 - 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_suppliers, get_cost_centers, get_purchase_orders, create_purchase_order, cancel_purchase_order.Similar skills
ā
Top