Esc

↑↓ move↵ openIndex · Pagefind
API preview · design draft
API reference · Changes

Change orders

Priced scope changes. Approval flows straight into budget, commitments, the next pay app and the forecast. One write, everything updates.

Design draftSubject to changeobject: change_orderid prefix: co_
  1. OBJECT The change_order object
  2. GET /v1/change-orders/{id}Retrieve a change order
  3. GET /v1/change-ordersList change orders
  4. POST /v1/change-ordersCreate a change order
  5. POST /v1/change-orders/{id}/approveApprove a change order
  6. GET /v1/change-orders/{id}/auditList audit trail

The change_order object

Every object carries an id, timestamps, and an audit_trail. Money is integer cents. Expand any node in the explorer to see how it links to the rest of the record.

  • id
    string
    Unique, stable identifier. Prefixed by object type.
  • object
    string
    String naming the object type.
  • project
    string
    Project ID.
  • number
    integer
    Sequential CO number on the project.
  • title
    string
    Short description.
  • status
    enum
    draft · pending_approval · approved · rejected · void.
  • reason
    enum
    owner_request · hidden_condition · design_error · allowance · other.
  • source_rfi
    string
    RFI that triggered it, if any.
  • amount
    integer
    Total, cents. Equals the sum of lines.
  • schedule_impact_days
    integer
    Requested time extension.
  • lines
    array
    Cost code breakdown: cost_code, description, amount.
  • approvals
    array
    Every approval decision, with role, user and time.
  • pay_app
    string
    Pay app it was billed on, once billed.
  • created_at
    timestamp
    ISO 8601, UTC.
  • updated_at
    timestamp
    ISO 8601, UTC. Changes on every write.
  • audit_trail
    string
    Path to the append-only history of who changed what, and when.
change_order · sample data
object{17}
  • id"co_14"id
  • object"change_order"string
  • project"prj_24118"id
  • number14integer
  • title"Add fire dampers — Level 3 corridor"string
  • status"approved"string
  • reason"hidden_condition"string
  • source_rfi"rfi_212"id
  • amount8640000integer$86,400.00
  • currency"usd"string
  • schedule_impact_days3integer
  • linesarray[3]
    • 0object{3}
      • cost_code"cc_233300"id
      • description"Fire dampers, material"string
      • amount4860000integer$48,600.00
    • 1object{3}
      • cost_code"cc_233300"id
      • description"Install labor"string
      • amount3120000integer$31,200.00
    • 2object{3}
      • cost_code"cc_233300"id
      • description"Markup"string
      • amount660000integer$6,600.00
  • approvalsarray[1]
    • 0object{4}
      • role"project_manager"string
      • user"usr_dana_pm"id
      • decision"approved"string
      • at"2026-09-30T21:18:42Z"timestamp
  • pay_app"pa_9"id
  • created_at"2026-09-24T16:40:09Z"timestamp
  • updated_at"2026-09-30T21:18:42Z"timestamp
  • audit_trail"/v1/change-orders/co_14/audit"string
GET /v1/change-orders/{id}

Retrieve a change order

One CO with lines and approvals.

Parameters

  • id
    stringpathrequired
    The change order ID, e.g. co_14.
  • expand[]
    stringquery
    Inline related objects, e.g. source_rfi.

Returns

The change_order object. Errors use the standard error shape.

Request
curl https://api.os.construction/v1/change-orders/co_14 \
  -H "Authorization: Bearer $OS_API_KEY"
Response · 200
{
  "id": "co_14",
  "object": "change_order",
  "project": "prj_24118",
  "number": 14,
  "title": "Add fire dampers — Level 3 corridor",
  "status": "approved",
  "reason": "hidden_condition",
  "source_rfi": "rfi_212",
  "amount": 8640000,
  "currency": "usd",
  "schedule_impact_days": 3,
  "lines": [
    {
      "cost_code": "cc_233300",
      "description": "Fire dampers, material",
      "amount": 4860000
    },
    {
      "cost_code": "cc_233300",
      "description": "Install labor",
      "amount": 3120000
    },
    {
      "cost_code": "cc_233300",
      "description": "Markup",
      "amount": 660000
    }
  ],
  "approvals": [
    {
      "role": "project_manager",
      "user": "usr_dana_pm",
      "decision": "approved",
      "at": "2026-09-30T21:18:42Z"
    }
  ],
  "pay_app": "pa_9",
  "created_at": "2026-09-24T16:40:09Z",
  "updated_at": "2026-09-30T21:18:42Z",
  "audit_trail": "/v1/change-orders/co_14/audit"
}
GET /v1/change-orders

List change orders

Filter by project and status.

Parameters

  • project
    stringquery
    ID of the project, e.g. prj_24118.
  • status
    enumquery
    Status filter.
  • limit
    integerquery
    Page size, 1 to 100. Default 25.
  • cursor
    stringquery
    Cursor from a previous page’s next_cursor.

Returns

A paginated list of change_order objects. Errors use the standard error shape.

Request
curl https://api.os.construction/v1/change-orders \
  -H "Authorization: Bearer $OS_API_KEY"
Response · 200
{
  "object": "list",
  "url": "/v1/change-orders",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "co_14",
      "object": "change_order",
      "project": "prj_24118",
      "number": 14,
      "title": "Add fire dampers — Level 3 corridor",
      "status": "approved",
      "reason": "hidden_condition",
      "source_rfi": "rfi_212",
      "amount": 8640000,
      "currency": "usd",
      "schedule_impact_days": 3,
      "lines": [
        {
          "cost_code": "cc_233300",
          "description": "Fire dampers, material",
          "amount": 4860000
        },
        {
          "cost_code": "cc_233300",
          "description": "Install labor",
          "amount": 3120000
        },
        {
          "cost_code": "cc_233300",
          "description": "Markup",
          "amount": 660000
        }
      ],
      "approvals": [
        {
          "role": "project_manager",
          "user": "usr_dana_pm",
          "decision": "approved",
          "at": "2026-09-30T21:18:42Z"
        }
      ],
      "pay_app": "pa_9",
      "created_at": "2026-09-24T16:40:09Z",
      "updated_at": "2026-09-30T21:18:42Z",
      "audit_trail": "/v1/change-orders/co_14/audit"
    }
  ]
}
POST /v1/change-orders

Create a change order

Creates a draft. Lines must sum to amount.

Idempotent. Send an Idempotency-Key; retries within 24 hours return the original result and never write twice.

Parameters

  • Idempotency-Key
    stringheaderrequired
    Any unique string. Replays return the first result instead of writing twice.
  • project
    stringbodyrequired
    Project ID.
  • title
    stringbodyrequired
    Title.
  • lines
    arraybodyrequired
    cost_code, description, amount.
  • source_rfi
    stringbody
    Linked RFI.

Returns

The change_order object. Errors use the standard error shape.

Request
curl -X POST https://api.os.construction/v1/change-orders \
  -H "Authorization: Bearer $OS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "project": "prj_24118",
    "title": "Add fire dampers — Level 3 corridor",
    "reason": "hidden_condition",
    "source_rfi": "rfi_212",
    "lines": [
      {
        "cost_code": "cc_233300",
        "description": "Fire dampers, material",
        "amount": 4860000
      },
      {
        "cost_code": "cc_233300",
        "description": "Install labor",
        "amount": 3120000
      },
      {
        "cost_code": "cc_233300",
        "description": "Markup",
        "amount": 660000
      }
    ]
  }'
Response · 201
{
  "id": "co_14",
  "object": "change_order",
  "project": "prj_24118",
  "number": 14,
  "title": "Add fire dampers — Level 3 corridor",
  "status": "draft",
  "reason": "hidden_condition",
  "source_rfi": "rfi_212",
  "amount": 8640000,
  "currency": "usd",
  "schedule_impact_days": 3,
  "lines": [
    {
      "cost_code": "cc_233300",
      "description": "Fire dampers, material",
      "amount": 4860000
    },
    {
      "cost_code": "cc_233300",
      "description": "Install labor",
      "amount": 3120000
    },
    {
      "cost_code": "cc_233300",
      "description": "Markup",
      "amount": 660000
    }
  ],
  "approvals": [],
  "pay_app": null,
  "created_at": "2026-09-24T16:40:09Z",
  "updated_at": "2026-09-30T21:18:42Z",
  "audit_trail": "/v1/change-orders/co_14/audit"
}
POST /v1/change-orders/{id}/approve

Approve a change order

Requires a user key with approver role. Agent keys cannot call this; they propose via agent actions.

Idempotent. Send an Idempotency-Key; retries within 24 hours return the original result and never write twice.

Parameters

  • id
    stringpathrequired
    The change order ID, e.g. co_14.
  • Idempotency-Key
    stringheaderrequired
    Any unique string. Replays return the first result instead of writing twice.
  • note
    stringbody
    Optional note for the audit trail.

Returns

The change_order object. Errors use the standard error shape.

Request
curl -X POST https://api.os.construction/v1/change-orders/co_14/approve \
  -H "Authorization: Bearer $OS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "note": "Per RFI-212 response"
  }'
Response · 200
{
  "id": "co_14",
  "object": "change_order",
  "project": "prj_24118",
  "number": 14,
  "title": "Add fire dampers — Level 3 corridor",
  "status": "approved",
  "reason": "hidden_condition",
  "source_rfi": "rfi_212",
  "amount": 8640000,
  "currency": "usd",
  "schedule_impact_days": 3,
  "lines": [
    {
      "cost_code": "cc_233300",
      "description": "Fire dampers, material",
      "amount": 4860000
    },
    {
      "cost_code": "cc_233300",
      "description": "Install labor",
      "amount": 3120000
    },
    {
      "cost_code": "cc_233300",
      "description": "Markup",
      "amount": 660000
    }
  ],
  "approvals": [
    {
      "role": "project_manager",
      "user": "usr_dana_pm",
      "decision": "approved",
      "at": "2026-09-30T21:18:42Z"
    }
  ],
  "pay_app": "pa_9",
  "created_at": "2026-09-24T16:40:09Z",
  "updated_at": "2026-09-30T21:18:42Z",
  "audit_trail": "/v1/change-orders/co_14/audit"
}
GET /v1/change-orders/{id}/audit

List audit trail

Every object has one. Append-only, newest first.

Parameters

  • id
    stringpathrequired
    The change order ID, e.g. co_14.

Returns

A paginated list of change_order objects. Errors use the standard error shape.

Request
curl https://api.os.construction/v1/change-orders/co_14/audit \
  -H "Authorization: Bearer $OS_API_KEY"
Response · 200
{
  "object": "list",
  "url": "/v1/change-orders/co_14/audit",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "aud_5521",
      "object": "audit_entry",
      "action": "approved",
      "actor": "usr_dana_pm",
      "at": "2026-09-30T21:18:42Z",
      "changes": {
        "status": [
          "pending_approval",
          "approved"
        ]
      }
    },
    {
      "id": "aud_5499",
      "object": "audit_entry",
      "action": "submitted",
      "actor": "usr_lee_pe",
      "at": "2026-09-25T14:03:10Z",
      "changes": {
        "status": [
          "draft",
          "pending_approval"
        ]
      }
    }
  ]
}

Events

Webhooks fire on every state change of a change_order.