Projects
Projects are used to track and organize business activities, costs, and revenues. They serve as financial dimensions that can be assigned to journal entries, invoices, and other transactions to provide detailed project-based reporting and analysis.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /projects | List projects |
| POST | /projects | Create a project |
| GET | /projects/{id} | Get a project |
| POST/PUT | /projects/{id} | Update a project |
| DELETE | /projects/{id} | Deactivate a project |
Query Parameters
The GET /projects endpoint supports the following query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | No | Filter by client account ID. When omitted, projects from all of the user’s eligible client accounts are returned |
| is_active | boolean | No | Filter by active status (default: true). Pass null to include both active and inactive |
| order_by | string | No | Comma-separated sort fields, each with an optional direction (e.g. name asc, sequence_number desc). Takes any project attribute, plus statistics.last_used_at, which puts projects that were never used last. Unknown fields are ignored |
| page | integer | No | Page number for pagination (default: 1) |
| per_page | integer | No | Number of items per page (default: 100) |
| with | string | No | Include related resources in the response (supported: statistics, journal_entry_lines, vouchers) |
Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | The ID of the project |
| created_at | datetime | The date and time when the project was created |
| created_by_id | integer | The ID of the user that created the project |
| updated_at | datetime | The date and time when the project was last updated |
| updated_by_id | integer | The ID of the user that last updated the project |
| client_account_id | integer | The ID of the client account this project belongs to |
| sequence_number | integer | The sequence number of the project |
| name | string | The name of the project |
| is_active | boolean | Whether the project is active or not |
| autonomy_level | string or null | Per-entity autonomy override. Values: NONE, DRAFT, FULL, or null (inherit from client account settings) |
Relationships
All relationships are opt-in and only included when requested via the with query parameter.
| Relationship | Type | Description |
|---|---|---|
| statistics | object | Aggregated statistics for the project. See Statistics |
| journal_entry_lines | JournalEntryLine | Journal entry lines tagged with this project |
| vouchers | Voucher | Vouchers assigned to this project |
Statistics
Returned with with=statistics.
{
"balances": [
{"account_code": "3000", "balance": -15000.0},
{"account_code": "6300", "balance": 4200.0}
],
"last_used_at": "2026-10-14T09:30:00+00:00",
"usage": {
"item_collection_entries": {
"count": 3,
"amount": 2100.0,
"used": 2,
"used_amount": 1600.0,
"unused": 1,
"unused_amount": 500.0
}
}
}
| Attribute | Type | Description |
|---|---|---|
| balances | array | Debit minus credit per account for journal entry lines on the project. Accounts with a zero balance are left out |
| last_used_at | datetime or null | When a journal entry line or item collection entry was last added to the project |
| usage.item_collection_entries.count | integer | Number of item collection entries on the project |
| usage.item_collection_entries.amount | number or null | Price times quantity across those entries. null when there are none |
| usage.item_collection_entries.used | integer | Entries that have been added to a document line |
| usage.item_collection_entries.used_amount | number or null | Price times quantity across the used entries |
| usage.item_collection_entries.unused | integer | Entries that have not been added to a document line |
| usage.item_collection_entries.unused_amount | number or null | Price times quantity across the unused entries |
Statistics are cached, and refreshed when a journal entry on the project is added or updated. usage can therefore lag behind recent changes to item collection entries.
Example Response
{
"id": 1,
"created_at": "2023-05-10T12:00:00Z",
"created_by_id": 1,
"updated_at": "2023-05-10T12:00:00Z",
"updated_by_id": 1,
"client_account_id": 1,
"sequence_number": 1001,
"name": "Website Redesign",
"is_active": true,
"autonomy_level": null
}
Deactivation Validation
When attempting to deactivate a project using the DELETE endpoint, the system performs validation to ensure data integrity:
- Balance Checking: The system checks if any accounting accounts with mandatory project dimensions have non-zero balances for this specific project.
- Validation Failure: If any accounts have non-zero balances, the deactivation is denied with a 400 Bad Request error.
- Error Details: The error message includes specific account codes and their balances to help identify which transactions need to be resolved.
Example Error Response
{
"error": {
"code": "common.validation_error",
"message": "Cannot deactivate project: account 1500: 2500.00, account 2000: -750.00",
"request_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
}
}
This validation ensures that projects cannot be deactivated while they still have outstanding balances, maintaining the integrity of your accounting records.
Error Codes
Project endpoints use the common error codes. Errors raised by the project endpoints themselves include "details": {"resource": "project"}.
| Code | HTTP status | When |
|---|---|---|
common.validation_error |
400 | The request body is missing or empty on POST /projects or POST/PUT /projects/{id} |
common.forbidden |
403 | The project, or the client_account_id in the request, is outside your eligible client accounts |
common.not_found |
404 | No project exists with the given ID |
Example Error Response
{
"error": {
"code": "common.not_found",
"message": "Project not found",
"details": {"resource": "project"},
"request_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
}
}
Notes
- The client_account_id on individual project records must be one of the eligible client accounts for the authenticated user.
- When creating or updating a project, the created_by_id/updated_by_id is automatically set to the authenticated user’s ID.
- The sequence_number is automatically assigned when creating a new project.
- Project names must be unique within a client account.
- Both
POSTandPUTare accepted on/projects/{id}for updates — they behave identically. - The DELETE endpoint deactivates the project (sets is_active to false) rather than permanently deleting the record.
- Projects with outstanding balances in mandatory dimension accounts cannot be deactivated until those balances are resolved.
- All dates are returned in ISO 8601 format.