Esc

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

One API. Every object on the job.

A resource-oriented REST API over the same record your PMs and accountants use. This is a design draft: nothing is live, every shape is open to change, and founding contractors are shaping it with us.

API preview · design draftSubject to changeRequest early access →

Conventions

Base URL

https://api.os.construction/v1. HTTPS only. JSON in, JSON out.

IDs

Every object has a stable, prefixed id: prj_24118, co_14, inv_4471. Safe to store.

Money

Integer cents with a currency. 8640000 is $86,400.00. No floats near a ledger.

Audit trail

Every object links to an append-only history: who, what, when, and the before/after.

Idempotent writes

Every POST and PATCH takes an Idempotency-Key. Retry freely; we write once.

Versioning

Dated versions pinned per key. Breaking changes ship as a new version, never in place.

Objects

Twelve resources, one data model. A change order points at its RFI, its cost codes and the pay app that billed it, so you never stitch exports together again.

Core

Job cost

Changes

Accounting

Field

Agents

Platform

Pagination

List endpoints return a list object. Pass next_cursor back as cursor until has_more is false. Cursors are stable under concurrent writes, so a nightly sync never skips a row.

Expanding

Related objects come back as IDs. Ask for them inline with expand[], up to two levels deep.

list object
{
  "object": "list",
  "url": "/v1/rfis",
  "has_more": true,
  "next_cursor": "cur_9f2c",
  "data": [ { "id": "rfi_212", "object": "rfi", ... } ]
}
curl
curl "https://api.os.construction/v1/change-orders/co_14?expand[]=source_rfi&expand[]=pay_app" \
  -H "Authorization: Bearer $OS_API_KEY"

Errors

Conventional HTTP status codes, plus a machine-readable code and a sentence a PM could read.

  • 400
    invalid_request
    Missing or malformed parameter.
  • 401
    unauthenticated
    No key, or a revoked key.
  • 403
    forbidden
    Key lacks the scope or role. Agent keys hitting approve endpoints land here.
  • 404
    not_found
    No such object, or not visible to this key.
  • 409
    conflict
    State does not allow it (e.g. approving a void CO) or idempotency key reused with a different body.
  • 422
    validation_failed
    Business rule failed: CO lines must sum to amount, period already locked.
  • 429
    rate_limited
    Slow down. See Retry-After.
Error · 422
{
  "error": {
    "type": "invalid_request",
    "code": "exceeds_commitment",
    "message": "Invoice amount exceeds PO-118 remaining commitment by $6,150.00.",
    "param": "amount",
    "object": "inv_4471",
    "request_id": "req_8XkQ2"
  }
}

All endpoints