REFERENCE
API reference
REST API over HTTPS. All endpoints return JSON. Authentication required for all non-public endpoints. Base URL: your ZRO instance domain.
12 min read
Authentication
ZRO uses JWT bearer tokens. Authenticate once, then include the token on every subsequent request.
1
Obtain a token
http
POST /api/auth/login
Content-Type: application/json
{
"email": "you@company.com",
"password": "your-password"
}json
// 200 response
{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"user": {
"id": "usr_abc123",
"name": "Alex Smith",
"email": "you@company.com",
"plan": "professional"
}
}2
Include the token in requests
http
GET /api/projects
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...Projects
GET
/api/projectsList all projects for the authenticated user. Returns an array ordered by updatedAt descending.POST
/api/projectsCreate a new project. Body: name (required), reference, currency, status, regionCode.GET
/api/projects/:idRetrieve a single project including aggregated cost and BOQ stats.PUT
/api/projects/:idUpdate project fields. Partial update — only provided fields are changed.DELETE
/api/projects/:idDelete a project and all associated data. Irreversible.json
// Project object
{
"id": "proj_abc123",
"name": "Office Tower Phase 2",
"reference": "J-2026-0045",
"currency": "EUR",
"regionCode": "DE",
"status": "active",
"budget": "2850000",
"createdAt": "2026-04-01T09:00:00Z",
"updatedAt": "2026-04-20T14:22:00Z"
}Estimates
GET
/api/estimatesList all estimates. Optional query param: projectId to filter by project.POST
/api/estimatesSave an estimate. Use /api/estimate (no trailing s) for AI-generated quick estimates.GET
/api/estimates/:idRetrieve a single estimate with full line items.DELETE
/api/estimates/:idDelete an estimate.Note
The
POST /api/estimate endpoint (singular) is the AI-assisted quick estimate. It accepts scope, city, area, and currency and returns a full structured estimate.Copilot
POST
/api/copilotSend a message to the executive copilot. Streams the response as SSE (Server-Sent Events).json
// Request body
{
"mode": "daily-brief" | "cost-risk" | "estimate-review" | "project-executive",
"message": "Summarise the cost exposure on my active projects",
"projectId": "proj_abc123" // optional — scopes context to one project
}
// Streaming response: text/event-stream
// Each chunk: data: {"delta": "partial text..."}Important
The copilot endpoint streams via SSE. Standard
fetch() with response.body.getReader() handles this in modern browsers. If you need a non-streaming fallback, append ?stream=false to receive the complete response in a single JSON object.Costs
GET
/api/costsList cost entries. Query param: projectId (required).POST
/api/costsCreate a cost entry. Fields: projectId, category, amount, currency, date, description.PUT
/api/costs/:idUpdate a cost entry.DELETE
/api/costs/:idDelete a cost entry.Errors and status codes
json
// All error responses follow this shape
{
"error": "Human-readable message describing the problem"
}