Skip to content
TruTecDevelopers
Get an API key

Change orders

List, create and edit change orders on a job, send them to the customer for approval, and approve, decline or void them.

View as Markdown

A change order changes a job after it is sold: added or removed scope, a contract change in dollars, and extra days. Change orders are numbered per job (CO #1, #2, ...).

There are three kinds:

Kind What it is
quick A title, scope text and a fixed dollar amount.
tm Time and materials, priced in the estimate editor from the job's estimate.
full Full pricing in the estimate editor: new work only, or the whole job revised.

A change order moves through the workspace's stages (for example Estimating, Review, Ready to send, Sent, Approved, Declined). Each stage has a meaning (working, sent, approved or declined) that sets the change order's status. Approving posts the change to the job's contract value and budget and, when the workspace syncs to QuickBooks Online or another accounting system, exports it, exactly as in TruTec.

Writes act as the person who created the API key and need operations turned on for the workspace (403 Operations not enabled otherwise).

The change order object#

Field Type Description
id, co_number integer Id, and the number within the job.
kind, kind_label, pricing_mode string See above. pricing_mode is additive or revision for priced change orders.
title, description string
status string draft, sent, approved, declined or void.
stage, stage_label string The workspace stage it sits in.
job_id, job_number, job_name, customer, customer_name, customer_email The job and who approves.
amount_delta, tax_delta, cost_delta number Contract, tax and cost change in dollars (+/-).
days_delta integer Schedule days added or removed.
revised_contract number or null The job's contract value including this change order.
lines array Lines by cost code (priced change orders).
ep_estimate_id, est_proposal_id integer or null The estimate and proposal behind a priced change order.
approved_at, approval_source, signature_name, signed_at How and when the customer or office approved it.
sent_at, decision_comment, source source is office or field (raised from the crew app).
exported_at, export_ref Accounting export.
created_at, updated_at string

Change orders#

List change orders#

GET /v1/change-orders

Permission: Read jobs

Takes job_id, status, limit (default 50, maximum 200) and offset. This older endpoint returns {"change_orders": [...], "total", "limit", "offset"} instead of the usual data / pagination; each row is the object above without the workflow fields. See Jobs.

Get a change order#

GET /v1/change-orders/{id}

Permission: Read jobs

curl "https://trutec.ai/api/v1/change-orders/5521" \
  -H "X-API-Key: sk_your_api_key_here"
{
  "data": {
    "id": 5521,
    "co_number": 2,
    "kind": "quick",
    "kind_label": "Quick",
    "pricing_mode": null,
    "title": "Add 40 LF of curb at the entrance",
    "description": "Remove and replace 40 LF of damaged curb.",
    "status": "sent",
    "stage": "sent",
    "approved_at": null,
    "approval_source": null,
    "signature_name": null,
    "job_id": 70412,
    "job_number": "24-118",
    "job_name": "Northgate Plaza reseal",
    "customer": "Northgate Property Group",
    "customer_email": "[email protected]",
    "amount_delta": 1850.5,
    "tax_delta": 0.0,
    "cost_delta": 0.0,
    "days_delta": 1,
    "revised_contract": 50350.5,
    "ep_estimate_id": null,
    "est_proposal_id": null,
    "exported_at": null,
    "export_ref": null,
    "lines": [],
    "stage_label": "Sent",
    "source": "office",
    "customer_name": "Dana Ortiz",
    "sent_at": "2026-11-04T15:12:40Z",
    "signed_at": null,
    "decision_comment": null,
    "created_at": "2026-11-04T14:58:02Z",
    "updated_at": "2026-11-04T15:12:40Z"
  }
}

Create a change order#

POST /v1/change-orders

Permission: Write jobs

Name Type Required Description
job_id integer Yes
title string Yes for quick Up to 200 characters.
kind string No quick (default), tm or full.
description string No The scope change.
amount_delta number No Dollars, + or -. quick only; priced kinds take their amount from the estimate.
days_delta integer No
customer_name, customer_email string No Who approves it.
pricing_mode string No additive (default) or revision, for full.
request_key string No A UUID. Repeating a tm or full create with the same key returns the same change order.

A quick change order starts as a draft in the first working stage. A tm or full change order copies the job's estimate into a new change-order estimate (the response's ep_estimate_id) to be priced; the key's creator needs the estimator or admin role, and the job needs an estimate (400 otherwise).

curl -X POST "https://trutec.ai/api/v1/change-orders" \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "job_id": 70412,
    "title": "Add 40 LF of curb at the entrance",
    "amount_delta": 1850.50,
    "days_delta": 1,
    "customer_email": "[email protected]"
  }'

Returns 201 with the change order. Nothing is sent to the customer.

Update a change order#

PATCH /v1/change-orders/{id}

Permission: Write jobs

Send any of title, description, amount_delta, days_delta, customer_name, customer_email. Only draft and sent change orders can change; approved or declined ones return 400.

Send a change order to the customer#

POST /v1/change-orders/{id}/send

Permission: Write jobs

This emails the customer (customer_email) a link to review and sign the change order online, from the key creator's connected mailbox when there is one. The status becomes sent. The response has emailed: false when there is no customer email; the link is still created and can be sent from TruTec. A decided change order returns 400.

Approve or decline#

POST /v1/change-orders/{id}/approve

POST /v1/change-orders/{id}/decline

Permission: Write jobs

Records the office's decision, the same as moving the change order to the workspace's Approved or Declined stage. Approving updates the job's contract value and budget and runs any accounting export. A change order the customer already signed cannot be declined.

Move to a stage#

POST /v1/change-orders/{id}/stage with {"stage": "review"}

Permission: Write jobs

Moves to any stage key from GET /v1/change-order-stages. A stage that means approved or declined does what Approve or Decline does. An unknown key returns 400.

Void a change order#

POST /v1/change-orders/{id}/void

Permission: Write jobs

Sets the status to void. A priced change order that is signed or approved cannot be voided (409).

List stages#

GET /v1/change-order-stages

Permission: Read jobs

{
  "data": [
    { "key": "estimating", "label": "Estimating", "meaning": "working" },
    { "key": "review", "label": "Review", "meaning": "working" },
    { "key": "ready_to_send", "label": "Ready to send", "meaning": "working" },
    { "key": "sent", "label": "Sent", "meaning": "sent" },
    { "key": "approved", "label": "Approved", "meaning": "approved" },
    { "key": "declined", "label": "Declined", "meaning": "declined" }
  ]
}

Deleting change orders#

Change orders can't be deleted, in TruTec or through the API. Void one instead (POST /v1/change-orders/{id}/void): it stays on the job's list marked void and keeps its number.