NAV
shell

CCUBE API v2 Reference

Overview

Base URLs: - Production: https://{tenant-subdomain}.inc.construction Replace {tenant-subdomain} with your tenant subdomain provided by CCUBE.

Conventions

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'

Project Files

Upload File to Project

curl -X POST "https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files" \
  -H "Authorization: Token YourApiToken,user_email=YourEmail" \
  -F "file=@/path/to/your/file.jpg" \
  -F "name=project_attachment.jpg"

The above command returns JSON structured like this:

{
  "id": 456,
  "name": "project_attachment.jpg",
  "url": "https://presigned-s3-url...",
  "content_type": "image/jpeg",
  "position": 1,
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "extension": "jpg",
  "is_image": true,
  "external_url": "http://tenant.inc.construction/api/core/files/...",
  "attachable": {
    "id": 123,
    "type": "Projects::Project"
  },
  "thumb_urls": {
    "sm": "https://presigned-thumb-sm-url...",
    "md": "https://presigned-thumb-md-url...",
    "lg": "https://presigned-thumb-lg-url...",
    "sm_aspect": "https://presigned-thumb-sm-aspect-url..."
  }
}

This endpoint uploads a file to a specific project. Files are stored securely in Amazon S3 with automatic thumbnail generation for images and PDF preview support.

HTTP Request

POST https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files

URL Parameters

Parameter Description
PROJECT_ID The ID of the project to attach the file to

Form Parameters

Parameter Type Required Description
file file yes The file to upload (supports images, PDFs, documents)
name string no Custom filename (defaults to original filename)

Get All Project Files

curl "https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files" \
  -H "Authorization: Token YourApiToken,user_email=YourEmail"

The above command returns JSON structured like this:

[
  {
    "id": 456,
    "name": "project_plan.jpg",
    "url": "https://presigned-s3-url...",
    "content_type": "image/jpeg",
    "position": 1,
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "extension": "jpg",
    "is_image": true,
    "external_url": "http://tenant.inc.construction/api/core/files/...",
    "thumb_urls": {
      "sm": "https://presigned-thumb-sm-url...",
      "md": "https://presigned-thumb-md-url...",
      "lg": "https://presigned-thumb-lg-url...",
      "sm_aspect": "https://presigned-thumb-sm-aspect-url..."
    }
  }
]

This endpoint retrieves all files attached to a specific project.

HTTP Request

GET https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files

URL Parameters

Parameter Description
PROJECT_ID The ID of the project to retrieve files for

Get a Specific Project File

curl "https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files/{ID}" \
  -H "Authorization: Token YourApiToken,user_email=YourEmail"

The above command returns JSON structured like this:

{
  "id": 456,
  "name": "project_plan.jpg",
  "url": "https://presigned-s3-url...",
  "content_type": "image/jpeg",
  "position": 1,
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "extension": "jpg",
  "is_image": true,
  "external_url": "http://tenant.inc.construction/api/core/files/...",
  "attachable": {
    "id": 123,
    "type": "Projects::Project"
  },
  "thumb_urls": {
    "sm": "https://presigned-thumb-sm-url...",
    "md": "https://presigned-thumb-md-url...",
    "lg": "https://presigned-thumb-lg-url...",
    "sm_aspect": "https://presigned-thumb-sm-aspect-url..."
  }
}

This endpoint retrieves a specific file attached to a project.

HTTP Request

GET https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files/{ID}

URL Parameters

Parameter Description
PROJECT_ID The ID of the project
ID The ID of the file to retrieve

Update Project File

curl -X PATCH "https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files/{ID}" \
  -H "Authorization: Token YourApiToken,user_email=YourEmail" \
  -H "Content-Type: application/json" \
  -d '{
    "file": {
      "name": "updated_filename.jpg"
    }
  }'

The above command returns JSON structured like this:

{
  "id": 456,
  "name": "updated_filename.jpg",
  "url": "https://presigned-s3-url...",
  "content_type": "image/jpeg",
  "position": 1,
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T11:45:00Z",
  "extension": "jpg",
  "is_image": true,
  "external_url": "http://tenant.inc.construction/api/core/files/..."
}

This endpoint updates the metadata of a specific project file.

HTTP Request

PATCH https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files/{ID}

URL Parameters

Parameter Description
PROJECT_ID The ID of the project
ID The ID of the file to update

Body Parameters

Parameter Type Required Description
file[name] string no New filename for the file

Delete Project File

curl -X DELETE "https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files/{ID}" \
  -H "Authorization: Token YourApiToken,user_email=YourEmail"

The above command returns JSON structured like this:

{
  "message": "File deleted"
}

This endpoint deletes a specific file from a project. The file is permanently removed from S3 storage.

HTTP Request

DELETE https://{tenant-subdomain}.inc.construction/api/v2/projects/{PROJECT_ID}/files/{ID}

URL Parameters

Parameter Description
PROJECT_ID The ID of the project
ID The ID of the file to delete

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.