CCUBE API v2 Reference
Overview
Base URLs:
- Production: https://{tenant-subdomain}.inc.construction
Replace {tenant-subdomain} with your tenant subdomain provided by CCUBE.
Conventions
- Content-Type: All endpoints accept and return JSON. Send requests with header
Content-Type: application/json
. - Authorization: All endpoints (unless specified) require header
Authorization: Token <token>,user_email=<email>
. - Pagination: Index endpoints support
page
(default: 1) andper_page
(default: 20). If not specified, defaults apply. - Error format: See the Errors section; validation errors return HTTP 422 with field-level details when available.
Authentication
To authenticate, use this endpoint:
POST https://{tenant-subdomain}.inc.construction/users/sign_in
curl -X POST "https://{tenant-subdomain}.inc.construction/users/sign_in" \
-H "Content-Type: application/json" \
-d '{
"user": {
"email": "your.email@example.com",
"password": "your_password"
}
}'
Success Response (200 OK):
{
"user_token": "generated_token",
"user_email": "your.email@example.com",
"email": "your.email@example.com",
"user_id": 1,
"user_contact_id": 1
}
All subsequent API requests must include the Authorization header:
Authorization: Token YourToken,user_email=your.email@example.com
Users
Get All Users
curl "https://{tenant-subdomain}.inc.construction/api/v2/users" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"email": "user1@example.com",
"name": "User One",
"role": "admin",
"created_at": "2024-01-01T12:00:00Z",
"updated_at": "2024-01-15T09:30:00Z"
},
{
"id": 2,
"email": "user2@example.com",
"name": "User Two",
"role": "user",
"created_at": "2024-01-02T10:00:00Z",
"updated_at": "2024-01-16T08:45:00Z"
}
]
This endpoint retrieves all Users.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/users
Query Parameters
Parameter | Default | Description |
---|---|---|
page | 1 | Page number to retrieve |
per_page | 20 | Number of results per page |
Get Specific User
This endpoint retrieves a specific User.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/users/{id}
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the User to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/users/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
{
"id": 1,
"email": "user1@example.com",
"given_name": "User",
"family_name": "One"
}
Create a New User
This endpoint to create a new User.
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/users
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
user[email] | string | yes | User's email address |
user[password] | string | yes | User's password (min 8 chars) |
user[password_confirmation] | string | yes | Must match password |
user[user_type] | string | yes | Either "full" or "limited" |
user[contact_id] | integer | no | Associated contact ID |
user[role_ids][] | array[integer] | yes | Array of role IDs |
user[given_name] | string | no | User's first name |
user[family_name] | string | no | User's last name |
user[suspended] | boolean | no | Account status (default: false) |
user[super_user] | boolean | no | Super user status (default: false) |
user[paid_tenant] | boolean | no | Paid tenant status |
user[dunning_tenant] | boolean | no | Dunning status |
user[trial] | boolean | no | Trial status |
user[demo] | boolean | no | Demo account status |
user[paid_user] | boolean | no | Paid user status |
curl 'https://{tenant-subdomain}.inc.construction/api/v2/users' -X POST \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"user": {
"email": "newuser@example.com",
"password": "password123",
"password_confirmation": "password123",
"user_type": "full",
"contact_id": 1234,
"role_ids": [1],
"given_name": "John",
"family_name": "Doe",
"suspended": false,
"super_user": false,
"paid_tenant": false,
"dunning_tenant": false,
"trial": false,
"demo": false,
"paid_user": false
}
}'
The above command returns JSON structured like this:
{
"id": 3,
"email": "newuser@example.com",
"role": "user",
"name": "New User",
"suspended": false,
"current_sign_in_at": "2023-10-01T12:00:00Z",
"last_sign_in_at": "2023-09-30T12:00:00Z",
"given_name": "New",
"family_name": "User"
}
Delete a User
This endpoint deletes a specific User.
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/users/{id}
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the User to delete |
curl 'https://{tenant-subdomain}.inc.construction/api/v2/users/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json'
The above command returns JSON structured like this:
{"message": "User deleted successfully"}
Update a User
Endpoint: PUT /api/v2/users/{id}
Description: This endpoint updates an existing user’s details by their ID.
Body Parameters (Update)
Parameter | Type | Required | Description |
---|---|---|---|
user[email] | string | no | New email address |
user[given_name] | string | no | First name |
user[family_name] | string | no | Last name |
user[suspended] | boolean | no | Account status |
user[user_type] | string | no | Either "full" or "limited" |
user[contact_id] | integer | no | Associated contact ID |
user[role_ids][] | array[integer] | no | Role assignments |
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/users/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"user": {
"email": "updated@example.com",
"given_name": "John",
"family_name": "Doe",
"suspended": false,
"user_type": "full",
"contact_id": 1234,
"role_ids": [1]
}
}'
The above command returns JSON structured like this:
{
"id": 1,
"email": "updated@example.com",
"given_name": "John",
"family_name": "Doe"
}
Projects
Get All Projects
curl "https://{tenant-subdomain}.inc.construction/api/v2/projects" \
-H 'Authorization: Token YourToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"status": "Active",
"stage": { "id": 2, "name": "Active" },
"number": "P-001",
"work_start": "2024-01-01",
"work_end": "2024-12-31",
"external_id": null,
"building_id": 10,
"call_notes": null,
"client": { "name": "Client Co", "email": "client@example.com", "phone": "+11234567890" },
"workflow_id": 3,
"work_type": { "id": 5, "name": "Roofing" },
"property_type": { "id": 7, "name": "Residential" },
"communication_status": { "id": 1, "name": "Open" },
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-05T00:00:00Z"
}
]
This endpoint retrieves all Projects.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/projects
Query Parameters
Parameter | Default | Description |
---|---|---|
page | 1 | Page number to retrieve |
per_page | 20 | Number of results per page |
Get Specific Project
This endpoint retrieves a specific Project.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/projects/{id}
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the Project to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/projects/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
{
"id": 1,
"number": "P-001",
"status": "Active",
"stage": { "id": 2, "name": "Active" },
"work_start": "2024-01-01",
"work_end": "2024-12-31",
"external_id": null,
"building_id": 10,
"call_notes": null,
"work_type": { "id": 5, "name": "Roofing" },
"property_type": { "id": 7, "name": "Residential" },
"communication_status": { "id": 1, "name": "Open" },
"client": { "name": "Client Co", "email": "client@example.com", "phone": "+11234567890" },
"address": { "id": 99, "street": "123 Main St", "city": "City", "state": "ST", "zip": "12345", "country": "USA" }
}
Create a New Project
This endpoint creates a new Project.
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/projects
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
project[name] | string | yes | Project title |
project[number] | string | yes | Unique project number/reference |
project[client_id] | integer | yes | Associated client ID |
project[manager_id] | integer | yes | Project manager ID |
project[work_start] | date | no | Project start date (YYYY-MM-DD) |
project[work_end] | date | no | Project end date (YYYY-MM-DD) |
project[stage_id] | integer | no | Current stage ID (pipeline stage) |
project[work_type_id] | integer | no | Work type ID |
project[property_type_id] | integer | no | Property type ID (FR: type de propriété) |
project[communication_status_id] | integer | no | Communication status ID |
project[call_notes] | string | no | Call notes (FR: demande) |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/projects" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"project": {
"name": "Project Name",
"number": "P-001",
"client_id": 1,
"manager_id": 1,
"work_start": "2024-01-01",
"work_end": "2024-12-31",
"stage_id": 2,
"work_type_id": 5,
"property_type_id": 7,
"communication_status_id": 1,
"call_notes": "Left voicemail; follow-up tomorrow"
}
}'
The above command returns JSON structured like this:
{
"id": 1,
"name": "project 1"
}
Delete a Project
This endpoint deletes a specific Project.
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/projects/{id}
URL Parameters
curl 'https://{tenant-subdomain}.inc.construction/api/v2/projects/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json'
The above command returns JSON structured like this:
{
"message": "Project deleted"
}
Update a Project
Endpoint: PUT /api/v2/projects/{id}
Description: This endpoint updates an existing project's details by ID.
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
project[name] | string | no | Project title |
project[number] | string | no | Project reference |
project[client_id] | integer | no | Associated client ID |
project[manager_id] | integer | no | Project manager ID |
project[work_start] | date | no | Start date (YYYY-MM-DD) |
project[work_end] | date | no | End date (YYYY-MM-DD) |
project[stage_id] | integer | no | Stage ID |
project[work_type_id] | integer | no | Work type ID |
project[property_type_id] | integer | no | Property type ID |
project[communication_status_id] | integer | no | Communication status ID |
project[call_notes] | string | no | Call notes |
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/projects/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"project": {
"name": "Updated Project",
"number": "P-001",
"client_id": 1,
"manager_id": 1,
"work_start": "2024-02-01",
"work_end": "2024-12-15",
"stage_id": 3,
"work_type_id": 6,
"property_type_id": 8,
"communication_status_id": 2,
"call_notes": "Client confirmed meeting 08/20"
}
}'
The above command returns JSON structured like this:
{
"id": 1,
"name": "project 1",
"number": "23",
"updated_at": "2024-08-28T19:27:32.094-04:00"
}
Get Communication Statuses
This endpoint retrieves all available communication statuses for projects.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/projects/communication_statuses
curl "https://{tenant-subdomain}.inc.construction/api/v2/projects/communication_statuses" \
-H 'Authorization: Token YourToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "New Inquiry",
"value": "new_inquiry",
"position": 1,
"is_first": true,
"is_last": false,
"type": "Projects/CommunicationStatus"
},
{
"id": 2,
"name": "Called Back",
"value": "called_back",
"position": 2,
"is_first": false,
"is_last": false,
"type": "Projects/CommunicationStatus"
},
{
"id": 3,
"name": "Scheduled",
"value": "scheduled",
"position": 3,
"is_first": false,
"is_last": true,
"type": "Projects/CommunicationStatus"
}
]
Get Work Types
This endpoint retrieves all available work types for projects.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/projects/work_types
curl "https://{tenant-subdomain}.inc.construction/api/v2/projects/work_types" \
-H 'Authorization: Token YourToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "Borne Résidentielle",
"value": "borne_residentielle",
"position": 1,
"type": "Projects/WorkType"
},
{
"id": 2,
"name": "Borne Commerciale",
"value": "borne_commerciale",
"position": 2,
"type": "Projects/WorkType"
},
{
"id": 3,
"name": "Multi Logements",
"value": "multi_logements",
"position": 3,
"type": "Projects/WorkType"
},
{
"id": 4,
"name": "Autres travaux électriques",
"value": "autres_travaux_electriques",
"position": 4,
"type": "Projects/WorkType"
}
]
Get Project Stages
This endpoint retrieves all available stages for projects based on the default workflow.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/projects/stages
curl "https://{tenant-subdomain}.inc.construction/api/v2/projects/stages" \
-H 'Authorization: Token YourToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "call",
"workflow_id": 1,
"previous_steps": [],
"next_steps": [2, 6, 8]
},
{
"id": 2,
"name": "quote",
"workflow_id": 1,
"previous_steps": [1],
"next_steps": [3, 6, 7]
},
{
"id": 3,
"name": "work",
"workflow_id": 1,
"previous_steps": [2],
"next_steps": [4, 7]
}
]
Quotes
Get All Quotes
GET /api/v2/quotes
shell
curl "https://{tenant-subdomain}.inc.construction/api/v2/quotes" \
-H 'Authorization: Token YourToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"project_id": 12,
"client_id": 34,
"number": "Q-001",
"quoted_total": 3500.0,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-02T00:00:00Z",
"status": "Draft",
"subtotal": 3200.0,
"external_id": null,
"client": { "id": 34, "name": "Client Co", "email": "client@example.com", "phone": "+11234567890" }
}
]
This endpoint retrieves all Quotes.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/quotes
Query Parameters
Parameter | Default | Description |
---|---|---|
page | 1 | Page number to retrieve |
per_page | 20 | Number of results per page |
Get Specific Quote
This endpoint retrieves a specific Quote.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/quotes/{id}
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the Quote to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/quotes/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
{
"id": 4,
"number": "Q-1002",
"status": "Approved",
"external_id": null,
"client": { "name": "Client Co", "email": "client@example.com", "phone": "+11234567890" }
}
Create a New Quote
This endpoint to create a new Quote.
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/quotes
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
quote[number] | string | yes | Quote number/reference |
quote[description] | string | no | Quote details/notes |
quote[project_id] | integer | yes | Associated project ID |
quote[department_id] | integer | yes | Department ID |
quote[quote_type] | string | yes | Quote type (e.g., standard) |
quote[terms] | string | no | Payment terms |
quote[title] | string | no | Quote title |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/quotes" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"quote": {
"number": "Q-001",
"description": "Description",
"project_id": 1,
"department_id": 1,
"quote_type": "standard",
"terms": "Payment terms",
"title": "Quote title"
}
}'
The above command returns JSON structured like this:
{
"id": 36,
"number": "Q-1033",
"status": "Draft",
"external_id": null
}
Delete a Quote
This endpoint deletes a specific Quote.
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/quotes/{id}
URL Parameters
curl 'https://{tenant-subdomain}.inc.construction/api/v2/quotes/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json'
The above command returns JSON structured like this:
{"message": "Quote deleted successfully"}
Update a Quote
Endpoint: PUT /api/v2/quotes/{id}
Description: This endpoint updates an existing quote's details by ID.
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/quotes/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"quote": {
"number": "Q-001",
"description": "Updated description",
"project_id": 1,
"department_id": 1,
"quote_type": "standard"
}
}'
The above command returns JSON structured like this:
{
"id": 164,
"name": "1154-S1157",
"description": "roof fix"
}
Invoices
Get All Invoices
GET /api/v2/invoices
curl "https://{tenant-subdomain}.inc.construction/api/v2/invoices" \
-H 'Authorization: Token YourToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"number": "INV-1000",
"issue_date": "2024-01-01",
"due_date": "2024-01-31",
"project_id": 1,
"client_id": 1,
"subtotal": 1000.0,
"total": 1000.0,
"paid_total": 800.0,
"balance": 200.0
}
]
This endpoint retrieves all Invoices.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/invoices
### Query Parameters
Pagination
⚠️ Coming Soon
Parameter | Default | Description |
---|---|---|
page | 1 | you can specify which page to get |
per_page | 20 | number of results per page |
Get Specific Invoice
This endpoint retrieves a specific Invoice.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/invoices/{id}
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the Invoice to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/invoices/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
{
"id": 1,
"number": "INV-1000",
"full_number": "2024-INV-1000",
"issue_date": "2024-01-01",
"due_date": "2024-01-31",
"project_id": 1,
"client_id": 1,
"status": "Approved",
"external_id": null,
"subtotal": 1000.0,
"tax1_rate": 0.0,
"tax2_rate": 0.0,
"tax1_amount": 0.0,
"tax2_amount": 0.0,
"total": 1000.0,
"paid_total": 1000.0,
"balance": 0.0,
"subject": "Invoice subject",
"description": "Invoice description",
"terms": null,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"paid_on": "2024-01-15",
"estimator_id": null,
"is_credit": false,
"client": { "name": "Client Co", "email": "client@example.com", "phone": "+11234567890" },
"lines": [
{
"id": 11,
"material": "Shingles - 3-tab",
"description": "Roof replacement - materials",
"quantity": 20,
"unit_price": 25.0,
"rate": null,
"total": 500.0,
"position": 1
},
{
"id": 12,
"material": null,
"description": "Labor",
"quantity": 10,
"unit_price": 50.0,
"rate": null,
"total": 500.0,
"position": 2
}
]
}
Notes: - paid_total represents the total of all payments applied to this invoice (no individual payments listed here). - subtotal, tax1_amount, tax2_amount, and total are numeric amounts; tax1_rate and tax2_rate are decimal rates (e.g., 0.099 for 9.9%). - client_id corresponds to the Party (client/contact) associated to the invoice; some UIs may label this as Party ID. - lines[].material is optional; use it to store the material reference/label. lines[].rate is reserved for future use; when not applicable, it may be null. - Balance = total - paid_total.
Line item fields returned in lines[]: - id: integer - material: string or null (optional) - description: string - quantity: number - unit_price: number - rate: number or null (reserved for future rate usage) - total: number (quantity x unit_price, adjusted by rate if applicable) - position: integer (ordering)
Create a New Invoice
This endpoint creates a new Invoice.
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/invoices
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
invoice[number] | string | yes | Invoice number/reference |
invoice[subject] | string | yes | Invoice subject/title |
invoice[description] | string | no | Invoice description |
invoice[client_id] | integer | yes | Client ID (aka Party ID) |
invoice[project_id] | integer | yes | Project ID |
invoice[issue_date] | date | yes | Issue date (YYYY-MM-DD) |
invoice[due_date] | date | no | Due date (YYYY-MM-DD) |
invoice[lines_attributes][] | array[object] | no | Line items to create; each item supports: material (string, optional), description (string), quantity (number), unit_price (number), rate (number, optional), position (integer, optional) |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/invoices" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"number": "INV-001",
"subject": "Invoice subject",
"description": "Details",
"client_id": 1,
"project_id": 1,
"issue_date": "2024-01-01",
"due_date": "2024-01-31",
"lines_attributes": [
{"material": "Shingles - 3-tab", "description": "Materials", "quantity": 20, "unit_price": 25.0, "position": 1},
{"description": "Labor", "quantity": 10, "unit_price": 50.0, "position": 2}
]
}
}'
The above command returns JSON structured like this:
{
"id": 67,
"number": "INV-011",
"full_number": "2024-INV-011",
"issue_date": "2024-01-01",
"due_date": "2024-01-31",
"project_id": 1,
"client_id": 1,
"status": "Draft",
"external_id": null,
"subtotal": 1000.0,
"tax1_rate": 0.0,
"tax2_rate": 0.0,
"tax1_amount": 0.0,
"tax2_amount": 0.0,
"total": 1000.0,
"paid_total": 0.0,
"balance": 1000.0,
"subject": "Invoice subject",
"description": "Details",
"terms": null,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"paid_on": null,
"estimator_id": null,
"is_credit": false,
"client": { "name": "Client Co", "email": "client@example.com", "phone": "+11234567890" },
"lines": [
{ "id": 1, "material": "Shingles - 3-tab", "description": "Materials", "quantity": 20, "unit_price": 25.0, "rate": null, "total": 500.0, "position": 1 },
{ "id": 2, "material": null, "description": "Labor", "quantity": 10, "unit_price": 50.0, "rate": null, "total": 500.0, "position": 2 }
]
}
Delete a Invoice
This endpoint deletes a specific Invoice.
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/invoices/{id}
URL Parameters
curl 'https://{tenant-subdomain}.inc.construction/api/v2/invoices/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json'
The above command returns JSON structured like this:
{
"message": "Invoice deleted"
}
Update a Invoice
Endpoint: PUT /api/v2/invoices/{id}
Description: This endpoint updates an existing invoice’s details by ID.
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/invoices/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"invoice": {
"number": "INV-001",
"subject": "Updated subject",
"client_id": 1,
"project_id": 1
}
}'
The above command returns JSON structured like this:
{
"id": 6,
"number": "1",
"subject": "1"
}
Purchase Orders
Get All Purchase Orders
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders
This endpoint retrieves all Purchase Orders.
Query Parameters
Pagination
⚠️ Coming Soon
Parameter | Default | Description |
---|---|---|
page | 1 | you can specify which page to get |
per_page | 20 | number of results per page |
curl "https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"project_id": 22,
"number": "PO-1001",
"description": "Complete kitchen renovation.",
"expected_start": "2024-02-01",
"created_at": "2024-01-10T00:00:00Z",
"updated_at": "2024-01-12T00:00:00Z",
"external_id": null
},
{
"id": 2,
"project_id": 23,
"number": "PO-1002",
"description": "Bathroom remodeling.",
"expected_start": null,
"created_at": "2024-01-11T00:00:00Z",
"updated_at": "2024-01-13T00:00:00Z",
"external_id": null
}
]
Get Specific Purchase Order
This endpoint retrieves a specific Purchase Order.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders/ID
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the Purchase order to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
{
"id": 1,
"number": "PO-1011",
"external_id": null
}
Create a New Purchase Order
This endpoint to create a new Purchase Order.
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
purchase_order[number] | string | yes | Purchase order number/reference |
purchase_order[description] | string | no | Purchase order description |
purchase_order[department_id] | integer | yes | Department ID |
curl 'https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders' -X POST \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"purchase_order": {
"number": "PO-001",
"description": "Purchase order description",
"department_id": 1
}
}'
The above command returns JSON structured like this:
{
"id": 1,
"number": "PO-1011",
"description": "Purchase order description",
"external_id": null
}
Delete a Purchase Order
This endpoint deletes a specific Purchase Order.
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders/{id}
URL Parameters
curl 'https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json'
The above command returns JSON structured like this:
{
"id": 1,
"number": "1011"
}
Update a Purchase Order
Endpoint: PUT /api/v2/purchase_orders/{id}
Description: This endpoint updates an existing purchase order's details by ID.
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/purchase_orders/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"purchase_order": {
"number": "PO-001",
"description": "Updated description",
"department_id": 1
}
}'
Work Orders
Get All Work Orders
curl "https://{tenant-subdomain}.inc.construction/api/v2/work_orders" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"project_id": 50,
"number": "WO-1001",
"created_at": "2024-01-10T00:00:00Z",
"updated_at": "2024-01-12T00:00:00Z",
"external_id": null
},
{
"id": 2,
"project_id": 51,
"number": "WO-1002",
"created_at": "2024-01-11T00:00:00Z",
"updated_at": "2024-01-13T00:00:00Z",
"external_id": null
}
]
This endpoint retrieves all Work Orders.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/work_orders
Query Parameters
Pagination
⚠️ Coming Soon
Parameter | Default | Description |
---|---|---|
page | 1 | you can specify which page to get |
per_page | 20 | number of results per page |
Get Specific Work Order
This endpoint retrieves a specific Work Order.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/work_orders/ID
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the Work order to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/work_orders/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
{
"id": 1,
"name": "WO-1001",
"external_id": null
}
Create a New Work Order
This endpoint to create a new Work Order.
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/work_orders
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
work_order[number] | string | yes | Work order number/reference |
work_order[description] | string | yes | Work details/notes |
work_order[department_id] | integer | yes | Department ID |
work_order[start_date] | date | no | Start date (YYYY-MM-DD) |
work_order[end_date] | date | no | End date (YYYY-MM-DD) |
curl 'https://{tenant-subdomain}.inc.construction/api/v2/work_orders' -X POST \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"work_order": {
"number": "WO-001",
"description": "Description",
"department_id": 1,
"start_date": "2024-01-01",
"end_date": "2024-01-31"
}
}'
{
"id": 1,
"number": "WO-001",
"description": "Work order description"
}
Delete a Work Orders
This endpoint deletes a specific Work Order.
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/work_orders/{id}
URL Parameters
curl 'https://{tenant-subdomain}.inc.construction/api/v2/work_orders/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json'
Update a Work Orders
Endpoint: PUT /api/v2/work_orders/{id}
Description: This endpoint updates an existing Work Order details by ID.
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/work_orders/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"work_order": {
"number": "WO-001",
"description": "Updated description",
"department_id": 1
}
}'
Parties (contacts)
Get All Parties
curl "https://{tenant-subdomain}.inc.construction/api/v2/parties" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "Example Company",
"type": "company",
"addresses": [
{
"street": "123 Main St",
"city": "Example City",
"state": "EX",
"zip": "12345",
"country": "USA"
}
]
}
]
This endpoint retrieves all Parties.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/parties
Query Parameters
Pagination
⚠️ Coming Soon
Parameter | Default | Description |
---|---|---|
type | null | Filter by party type (building, company, contact) |
subtype | null | Filter by party subtype |
role | null | Filter by party role |
# Role-based filters:
/api/v2/parties?role=employee # Gets employee contacts
/api/v2/parties?role=supplier # Gets both supplier contacts and companies
/api/v2/parties?role=client # Gets both client contacts and companies
# Type-based filters:
/api/v2/parties?type=building # Gets all buildings
/api/v2/parties?type=company # Gets all companies
/api/v2/parties?type=contact # Gets all contacts
Subtype-based filters (using the SUBTYPES arrays from your models):
/api/v2/parties?subtype=supplier # Gets entities with supplier subtype
/api/v2/parties?subtype=client # Gets entities with client subtype
/api/v2/parties?subtype=contact # Gets entities with contact subtype
/api/v2/parties?subtype=employee # Gets entities with employee subtype
# Type and Subtype combinations:
/api/v2/parties?type=contact&subtype=supplier # Gets only contact-type suppliers
/api/v2/parties?type=company&subtype=client # Gets only company-type clients
# Multiple subtypes (using comma separation):
/api/v2/parties?subtype=supplier,client # Gets entities that are both suppliers and clients
/api/v2/parties?type=contact&subtype=employee,supplier # Gets contacts that are both employees and suppliers
Create Party
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
party[name] | string | yes | Party name |
party[type] | string | yes | One of: Crm::Parties::Contact, Crm::Parties::Company, Crm::Parties::Building |
party[first_name] | string | conditional | Required when type is Contact |
party[last_name] | string | conditional | Required when type is Contact |
party[addresses_attributes][] | array[object] | no | Nested addresses |
addresses_attributes[][street] | string | no | Street |
addresses_attributes[][city] | string | no | City |
addresses_attributes[][state] | string | no | State/province |
addresses_attributes[][zip] | string | no | Postal/ZIP code |
addresses_attributes[][country] | string | no | Country |
party[phones_attributes][] | array[object] | no | Nested phones |
phones_attributes[][value] | string | no | Phone number |
phones_attributes[][type] | string | no | e.g., office, mobile |
party[emails_attributes][] | array[object] | no | Nested emails |
emails_attributes[][value] | string | no | Email address |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/parties" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"party": {
"name": "Company Name",
"type": "Crm::Parties::Contact",
"first_name": "John",
"last_name": "Doe",
"addresses_attributes": [
{
"street": "123 Main St",
"city": "Example City",
"state": "EX",
"zip": "12345"
}
],
"phones_attributes": [
{
"value": "+1234567890",
"type": "office"
}
],
"emails_attributes": [
{
"value": "contact@example.com"
}
]
}
}'
The above command returns JSON structured like this:
{
"id": 1,
"name": "Example Company",
"type": "Crm::Parties::Contact"
}
Update Party
curl -X PUT "https://{tenant-subdomain}.inc.construction/api/v2/parties/1" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"party": {
"name": "Updated Company Name"
}
}'
Delete Party
curl "https://{tenant-subdomain}.inc.construction/api/v2/parties/1" -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
Contact Information
Create Phone
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
phone[value] | string | yes | Phone number in international format if possible |
phone[type] | string | no | e.g., office, mobile, home |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/phones" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"phone": {
"value": "+1234567890",
"type": "office"
}
}'
Create Email
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
email[value] | string | yes | Email address |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/emails" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"email": {
"value": "contact@example.com"
}
}'
Create Address
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
address[street] | string | yes | Street |
address[city] | string | yes | City |
address[state] | string | yes | State/province |
address[zip] | string | yes | Postal/ZIP code |
address[country] | string | no | Country |
curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/addresses" \
-H 'Authorization: Token YourToken,user_email=YourEmail' \
-H "Content-Type: application/json" \
-d '{
"address": {
"street": "123 Main St",
"city": "Example City",
"state": "EX",
"zip": "12345",
"country": "USA"
}
}'
Notes
Get All Notes
curl "https://{tenant-subdomain}.inc.construction/api/v2/notes?page=1&per_page=20" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
The above command returns JSON structured like this:
[
{
"id": 1,
"notable_type": "Project",
"notable_id": 123,
"body": "Example note text",
"created_by_id": 45,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-02T00:00:00Z"
}
]
This endpoint retrieves all Notes.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/notes
Query Parameters
Parameter | Default | Description |
---|---|---|
page | 1 | Page number to retrieve |
per_page | 20 | Number of results per page |
notable_type | Filter by parent type (Project, Quote, Invoice, WorkOrder, PurchaseOrder) | |
notable_id | Filter by parent ID |
Get Specific Note
This endpoint retrieves a specific Note.
HTTP Request
GET https://{tenant-subdomain}.inc.construction/api/v2/notes/{id}
URL Parameters
Parameter | Description |
---|---|
id | The ID of the Note to retrieve |
curl "https://{tenant-subdomain}.inc.construction/api/v2/notes/1" \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
Returns JSON like:
{
"id": 1,
"notable_type": "Project",
"notable_id": 123,
"body": "Example note text",
"created_by_id": 45,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-02T00:00:00Z"
}
Create a New Note
HTTP Request
POST https://{tenant-subdomain}.inc.construction/api/v2/notes
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
note[notable_type] | string | yes | Parent entity type (Project, Quote, Invoice, WorkOrder, PurchaseOrder) |
note[notable_id] | integer | yes | Parent entity ID |
note[body] | string | yes | Note text/body |
curl 'https://{tenant-subdomain}.inc.construction/api/v2/notes' -X POST \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"note": {
"notable_type": "Project",
"notable_id": 123,
"body": "Kickoff scheduled for Friday"
}
}'
Returns JSON structured like this:
{
"id": 777,
"notable_type": "Project",
"notable_id": 123,
"body": "Kickoff scheduled for Friday",
"created_by_id": 45,
"created_at": "2024-01-03T10:30:00Z",
"updated_at": "2024-01-03T10:30:00Z"
}
Update a Note
Endpoint: PUT /api/v2/notes/{id}
Body Parameters
Parameter | Type | Required | Description |
---|---|---|---|
note[body] | string | yes | New note text/body |
CURL Request
curl 'https://{tenant-subdomain}.inc.construction/api/v2/notes/{id}' -X PUT \
-H 'Authorization: Token YourApiToken,user_email=YourEmail' \
-H 'Content-Type: application/json' \
--data-raw '{
"note": {
"body": "Updated note text"
}
}'
Delete a Note
HTTP Request
DELETE https://{tenant-subdomain}.inc.construction/api/v2/notes/{id}
curl 'https://{tenant-subdomain}.inc.construction/api/v2/notes/{id}' -X DELETE \
-H 'Authorization: Token YourApiToken,user_email=YourEmail'
Errors
CCUBE API uses conventional HTTP status codes to indicate the success or failure of an API request. Errors are returned as JSON.
Example error response:
{
"error": {
"code": "unauthorized",
"message": "Invalid or expired token",
"details": null
}
}
Status | Meaning |
---|---|
400 | Bad Request — Your request is invalid (e.g., malformed JSON, missing required parameter). |
401 | Unauthorized — Missing or invalid credentials. Ensure Authorization header is set: Authorization: Token <token>,user_email=<email> . |
403 | Forbidden — You do not have permission to perform this action. |
404 | Not Found — The requested resource does not exist. |
405 | Method Not Allowed — The HTTP method is not supported for this endpoint. |
406 | Not Acceptable — You requested a format that isn't JSON. |
409 | Conflict — The request could not be completed due to a resource conflict. |
410 | Gone — The requested resource is no longer available. |
422 | Unprocessable Entity — Validation failed; check details for field errors. |
429 | Too Many Requests — You have exceeded the rate limit. |
500 | Internal Server Error — We had a problem with our server. Try again later. |
503 | Service Unavailable — We're temporarily offline for maintenance. Try again later. |