Approve a change order
Finance module
POST/change-orders/{id}/approvechangeOrders.approve
Records an approval decision on the change order. Its requester cannot price and approve it alone, and an unpriced change order cannot be approved at zero. Spend authority and separation of duties are enforced in the approval RPC; a refusal returns 422 and names the rule. Requires `Idempotency-Key`; a replay returns the original response. A rule that refuses the request returns 422 with `refusal` and `reason`.
- Requires the capability finance.change_order.approve.
- OAuth scopes: finance.
- Send an Idempotency-Key header. A replay with the same key returns the original response.
- Error statuses: 400, 401, 404, 409, 422, 429. Errors are RFC 9457 problem details.
Path and query parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id | string (uuid) | Yes | Identifier of the change order. |
Response 200: ChangeOrder
| Field | Type | Required | Description |
|---|---|---|---|
| id | string (uuid) | Yes | Identifier of the change order. |
| org_id | string (uuid) | Yes | Identifier of the owning organization, derived from the parent row and never accepted from the caller. |
| created_at | string (date-time) | Yes | When the row was created. |
| created_by | string (uuid) | null | Yes | Identifier of the person who created the row; null when a seed, platform or system process created it. |
| updated_at | string (date-time) | Yes | When the row was last updated. |
| updated_by | string (uuid) | null | Yes | Identifier of the person who last updated the row; null when a seed, platform or system process updated it. |
| project_id | string (uuid) | Yes | Identifier of the project. |
| title | string | Yes | Change order title.Constraints: length 1 to 300 |
| reason | string | null | Yes | What changes and why.Constraints: length 1 to 20000 |
| requested_by | string (uuid) | null | Yes | Identifier of the requester. |
| change_order_state | "Proposed" | "Priced" | "Approved" | "Rejected" | "Canceled" | Yes | Change order state. |
| total | MoneyTotal | Yes | A money aggregate that never coerces unpriced inputs to zero. |
| budget_id | string (uuid) | Yes | Identifier of the budget the change order revises. |
| change_order_number | integer | Yes | Change order number within the project.Constraints: range 1 to any |
| order_type_enum_id | string | null | Yes | Canon change order type.Constraints: pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ |
| priced_by | string (uuid) | null | Yes | Identifier of the person who priced the change order. |
| schedule_impact_days | integer | null | Yes | Days the change moves the schedule; negative when it pulls it in, zero for none.Constraints: range -3650 to any |
| client_impact | string | null | Yes | Effect of the change on the client, as stated.Constraints: length 1 to 500 |
| approved_at | string (date-time) | null | Yes | When the change order moved to Approved, from its transition ledger. |
| approved_by | string (uuid) | null | Yes | Identifier of the person who moved the change order to Approved. |
{
"id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"org_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"created_at": "2026-10-08T14:30:00Z",
"created_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"updated_at": "2026-10-08T14:30:00Z",
"updated_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"project_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"title": "Add Second Bar",
"reason": "Client added a second bar at the north lawn.",
"requested_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"change_order_state": "Proposed",
"total": {
"total_minor": 1250000,
"currency": "USD",
"unpriced_count": 2
},
"budget_id": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"change_order_number": 3,
"order_type_enum_id": "ENM-092",
"priced_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f",
"schedule_impact_days": 2,
"client_impact": "Adds a second stage to the run of show.",
"approved_at": "2026-10-08T14:30:00Z",
"approved_by": "0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f"
}Code samples
curl -X POST "$XOS_BASE_URL/change-orders/0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f/approve" \
-H "Authorization: Bearer $XOS_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"const { data } = await xos.changeOrders.approve("0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f");response = xos.change_orders.approve("0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f")xos change-orders approve 0192f1e2-7c3a-7b4d-9e8f-1a2b3c4d5e6f