REST API · v1
The ashiba.ai REST API.
Read and write across your projects, cost lines, checklist, schedule, documents, and bids — with role-scoped keys that hold the same rule the app does.
Prefer to drive ashiba from an AI agent? The same surface is exposed as Model Context Protocol tools — see the
MCP reference →Base URL & versioning
Every endpoint below is relative to https://www.ashiba.ai/api/v1. v1 is stable; breaking changes ship under a new version prefix, never in place.
Authentication
Create a key in
Settings → API keys (company owners). A key carries exactly your access — the same role rules the app enforces — and is
read-only by default; a read+write key is an explicit opt-in. Send it as a bearer token:
curl https://www.ashiba.ai/api/v1/projects \
-H "Authorization: Bearer ak_3f9c…"
The cost rule
A sub- or client-scoped key never carries a cost or margin figure. Cost endpoints return 403 for such keys, and cost fields are stripped in the serializer even if a route were ever misgated. It is the same invariant the app enforces, held at the token.
Response envelope
Success returns { data, meta? }; failure returns { error: { code, message } } with an HTTP status. Codes: unauthorized (401), forbidden (403), not_found (404), bad_request (400). Every path under /api/v1 answers in this envelope — an unknown endpoint returns a JSON not_found, never an HTML page.
{
"data": [ { "id": 12, "name": "412 Kestrel Ridge", "status": "Construction", "role": "owner" } ],
"meta": { "count": 1 }
}
Endpoints
59 endpoints, grouped by resource. The right column is the access each one requires.
Account
GET/me
The key's user and company role.
any key Projects
GET/projects
Every project the key can reach, role-scoped.
any key POST/projects
Create a project ({name, address?, start_date?}). You become an admin member; a starter checklist is seeded.
owner/admin GET/projects/{id}
A single project (404 if the key has no access).
project access PATCH/projects/{id}
Update a project ({status?, start_date?}). Advance the lifecycle or set/clear the crew-calendar start date.
manager Estimating & money
GET/projects/{id}/cost-items
The estimate/actual ledger, with verdicts.
manager only POST/projects/{id}/cost-items
Add a cost line ({kind, name, est_low?, est_high?}).
manager PATCH/projects/{id}/cost-items/{itemId}
Update a cost line — record the actual, adjust the band, set status/vendor/notes. Partial; recording the actual freezes the original band.
manager DELETE/projects/{id}/cost-items/{itemId}
Delete a cost line. Refused if linked by a bid/payment/change order — unlink first.
manager GET/projects/{id}/bids
Bids per package.
manager POST/projects/{id}/bids
Add a bid ({package, vendor, amount, cost_item_id?}).
manager POST/projects/{id}/bids/{bidId}/award
Award a bid — declines siblings and commits the amount to the linked cost line as the actual.
manager DELETE/projects/{id}/bids/{bidId}
Delete a bid. Refused while awarded (its amount is committed to a cost line).
manager GET/projects/{id}/payments
Sub pay applications.
manager POST/projects/{id}/payments
Add a pay-app ({vendor, amount, cost_item_id?, lien_waiver?, coi_ok?}).
manager POST/projects/{id}/payments/{paymentId}/advance
Advance a pay-app due→approved→paid. Paid settles the linked line; release needs waiver + COI.
manager DELETE/projects/{id}/payments/{paymentId}
Delete a pay-app. Refused while paid (it settled its cost line).
manager GET/projects/{id}/changes
Change orders with amount and status.
manager POST/projects/{id}/changes
Add a change order ({title, amount?, days_delta?, cost_item_id?}).
manager POST/projects/{id}/changes/{coId}/advance
Advance a CO draft→sent→signed ({to}). Signing lifts the linked cost line band by the amount.
manager GET/projects/{id}/draws
The payment draw schedule.
manager POST/projects/{id}/draws
Add a payment draw ({title, amount?, gate?}). Lands pending.
manager POST/projects/{id}/draws/{drawId}/advance
Advance a draw pending→ready→invoiced→paid ({to}).
manager DELETE/projects/{id}/draws/{drawId}
Delete a payment draw.
manager Field
GET/projects/{id}/checklist
Checklist items.
canSee(checklist) POST/projects/{id}/checklist
Add a checklist item ({title, section?}). title is sanitized.
manager PATCH/projects/{id}/checklist/{itemId}
Edit an item (partial: title/section/done). title re-sanitized.
manager DELETE/projects/{id}/checklist/{itemId}
Delete a checklist item.
manager POST/projects/{id}/checklist/{itemId}/toggle
Flip a checklist item done/undone.
canWrite(checklist) GET/projects/{id}/schedule
Schedule tasks with slip.
canSee(schedule) POST/projects/{id}/schedule
Add a schedule task ({name, trade?, day_start?, duration?}). Self-baselined; slip starts at 0.
manager PATCH/projects/{id}/schedule/{taskId}
Edit a task (partial: name/trade/day_start/duration/status). Baseline untouched, so slip reflects the move.
manager DELETE/projects/{id}/schedule/{taskId}
Delete a schedule task.
manager GET/projects/{id}/logs
Daily-log entries.
canSee(log) POST/projects/{id}/logs
Add a daily-log entry ({note, date?, client_visible?}).
manager DELETE/projects/{id}/logs/{logId}
Delete a log entry (its photos cascade).
manager GET/projects/{id}/documents
Document metadata, filtered by visibility.
per-doc POST/projects/{id}/documents
Create a document ({title, rev?, html?, sub_visible?, client_visible?}). html is sanitized; private by default.
manager PATCH/projects/{id}/documents/{docId}
Update a document (partial: title/rev/html/sub_visible/client_visible). html re-sanitized.
manager DELETE/projects/{id}/documents/{docId}
Delete a document.
manager GET/projects/{id}/permits
Permits and their status.
manager POST/projects/{id}/permits
Add a permit ({name, authority?, notes?}). Lands as preparing.
manager POST/projects/{id}/permits/{permitId}/advance
Advance a permit along the city stage machine ({to}). Edge-validated; stamps dates.
manager GET/projects/{id}/punch
The punch/closeout list.
manager POST/projects/{id}/punch
Add a punch item ({title, location?, assignee?}). Lands not done.
manager POST/projects/{id}/punch/{itemId}/toggle
Flip a punch item done/undone.
manager DELETE/projects/{id}/punch/{itemId}
Delete a punch item.
manager GET/projects/{id}/inspections
Inspection gates.
manager POST/projects/{id}/inspections
Add an inspection gate ({name, day?, num?, notes?}). Lands pending.
manager POST/projects/{id}/inspections/{inspectionId}/status
Set the gate result ({status}: pending|scheduled|passed|failed).
manager Company
GET/leads
Your company lead pipeline (company-scoped, not project-nested).
owner/admin POST/leads
Add a lead ({name, contact?, email?, scope?, est_value?}). Lands as new.
owner/admin POST/leads/{id}/advance
Advance a lead one pipeline stage ({to}). Edge-validated.
owner/admin POST/leads/{id}/convert
Convert a won lead into a project (creator becomes admin; checklist seeded; estimate logged).
owner/admin DELETE/leads/{id}
Delete a lead (a converted lead keeps its project).
owner/admin GET/vendors
Your company vendor bench (company-scoped, not project-nested).
owner/admin POST/vendors
Add a vendor ({name, trade?, contact?, email?, phone?, status?, rating?, notes?}).
owner/admin PATCH/vendors/{id}
Update a vendor (partial: any of name/trade/contact/email/phone/status/rating/notes).
owner/admin DELETE/vendors/{id}
Remove a vendor from the bench.
owner/admin