Authentication
All API requests require authentication using a Bearer token. Include your API token in the Authorization header of each request:
Authorization: Bearer YOUR_API_TOKEN
For detailed information about authentication, token generation, and permissions, see the API Authentication documentation.
All endpoints are scoped to a specific account. Only projects belonging to the authenticated user's account will be accessible.
The Project Object
A project object represents a won client engagement or internal project within Drum. This endpoint only returns projects with project_type: "project". For opportunities in the sales pipeline, use the Opportunities API.
Core Attributes
Attribute | Type | Description |
id | integer | Unique identifier for the project. |
name | string | The project name. |
description | string | null | Optional detailed description of the project. |
project_number | string | Unique project number/code. |
currency | string | Three-letter ISO currency code (e.g., "AUD", "USD", "GBP"). |
Classification
Attribute | Type | Description |
project_type | string | Always "project" for this endpoint (active work). |
contract_type | string | Either "fixed_price" or "time_and_materials". |
budget_type | string | null | Either "project_level" or "per_stage". |
progress_claim_mode | string | Either "deliverable" or "task". |
Dates
Attribute | Type | Description |
start_date | string | null | Project start date in ISO 8601 format (YYYY-MM-DD). |
end_date | string | null | Project end date in ISO 8601 format (YYYY-MM-DD). |
completed_date | string | null | Date the project was completed. |
Associations
Attribute | Type | Description |
project_status | object | null | Project status details including |
client | object | null | Client information with |
company_id | integer | null | Legacy field - ID of the associated Company. Use |
team | object | null | Team assignment with |
Financial Metrics
Note: Financial data requires the view_project_metrics permission. Without this permission, these fields will not be included in the response.
Attribute | Type | Description |
total_budget | decimal | Total project budget in currency units. |
total_invoiced | decimal | Total amount invoiced to client. |
costs_to_date | decimal | Actual costs incurred on the project. |
unbilled_costs | decimal | Costs not yet invoiced to client. |
Profitability Metrics
Note: These fields require the view_gross_profit permission in addition to view_project_metrics. Without this permission, these fields will not be included in the response.
Attribute | Type | Description |
work_in_progress | decimal | WIP calculation (invoiced - earned revenue). |
remaining_cost_to_complete | decimal | Estimated costs remaining to complete the project. |
Retention (if enabled)
Attribute | Type | Description |
retention_percent | decimal | Percentage of each progress claim withheld. |
retention_amount | decimal | Total retention amount on project budget. |
retention_withheld | decimal | Amount withheld from approved claims. |
retention_released | decimal | Retention released back to client. |
retention_outstanding | decimal | Retention still withheld. |
Counters
Attribute | Type | Description |
quotes_count | integer | Number of quotes associated with project. |
invoices_count | integer | Number of invoices. |
progress_claims_count | integer | Number of progress claims. |
costs_count | integer | Number of cost entries. |
Metadata
Attribute | Type | Description |
project_tags | array of strings | Tags applied to the project. |
planned | boolean | Whether project is in planning state. |
skip_planning | boolean | Whether to skip planning phase. |
Nested Data (Show Endpoint Only)
Attribute | Type | Description |
deliverables | array | Array of deliverable objects (only in GET /projects/:id endpoint). See Deliverables below. |
Example Object (Index)
The index endpoint returns a lightweight representation:
{
"id": 42,
"name": "Website Redesign for Acme Corp",
"project_number": "PRJ-001",
"description": "Complete overhaul of corporate website",
"currency": "AUD",
"project_type": "project",
"contract_type": "fixed_price",
"start_date": "2025-01-15",
"end_date": "2025-04-30",
"project_status": {
"id": 5,
"name": "In Progress",
"complete_status": false
},
"client": {
"id": 123,
"name": "Acme Corp",
"type": "Company"
},
"team": {
"id": 2,
"name": "Design Team"
},
"total_budget": 75000.00,
"planned": false
}Example Object (Show)
The show endpoint includes comprehensive details and nested data:
{
"id": 42,
"name": "Website Redesign for Acme Corp",
"project_number": "PRJ-001",
"description": "Complete overhaul of corporate website",
"currency": "AUD",
"project_type": "project",
"contract_type": "fixed_price",
"budget_type": "project_level",
"progress_claim_mode": "deliverable",
"start_date": "2025-01-15",
"end_date": "2025-04-30",
"completed_date": null,
"project_status": {
"id": 5,
"name": "In Progress",
"complete_status": false
},
"client": {
"id": 123,
"name": "Acme Corp",
"type": "Company"
},
"company_id": 123,
"team": {
"id": 2,
"name": "Design Team"
},
"total_budget": 75000.00,
"total_invoiced": 45000.00,
"costs_to_date": 38000.00,
"unbilled_costs": 5000.00,
"work_in_progress": 2000.00,
"remaining_cost_to_complete": 12000.00,
"quotes_count": 1,
"invoices_count": 3,
"progress_claims_count": 2,
"costs_count": 45,
"project_tags": ["web-design", "urgent"],
"planned": false,
"skip_planning": false,
"deliverables": [
{
"id": 1,
"name": "Discovery & Research",
"description": "Initial discovery phase",
"position": 1,
"status": "completed",
"billing_type": "fixed_fee",
"allow_time_tracking": "allowed",
"percentage_complete": 100,
"currency": "AUD",
"start_date": "2025-01-15",
"end_date": "2025-02-01",
"duration": 80.0,
"budget": 10000.00,
"invoiced_amount": 10000.00,
"total_cost": 9500.00,
"budget_invoiced_percent": 100.0,
"plan_only": false,
"purchase_number": null,
"claim_items_count": 0,
"tasks": [
{
"id": 1,
"name": "Client Interviews",
"note": "Interview key stakeholders",
"position": 1,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": "2025-01-20",
"start_date": "2025-01-15",
"estimated_start_date": null,
"completed_date": "2025-01-20T10:30:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 150.00,
"original_duration": 8.0,
"original_total": 1200.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 7.5,
"actual_total": 1125.00,
"budget": 1200.00,
"total": 1200.00,
"remaining": 75.00,
"budget_used_percentage": 93.75,
"tracked_times_count": 3,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 5,
"name": "Senior Consultant"
}
}
]
}
]
}Deliverable Object
A deliverable represents a phase or work package within a project. In Drum, deliverables structure project work into logical chunks. Deliverables are ordered by the position field.
Attributes
Attribute | Type | Description |
id | integer | Unique identifier for the procedure. |
name | string | Name of the deliverable/phase. |
description | string | null | Detailed description. |
position | integer | Sort order within the project (1-indexed). |
status | string | One of: "not_started", "in_progress", "completed", "not_applicable", "blocked". |
billing_type | string | Either "fixed_fee" or "time_and_materials". |
allow_time_tracking | string | Either "allowed", "allowed_if_assigned", or "not_allowed". |
percentage_complete | integer | Completion percentage (0-100). |
currency | string | Currency code. |
start_date | string | null | Start date. |
end_date | string | null | End date. |
duration | decimal | Estimated duration in hours. |
budget | decimal | Total budget (requires |
invoiced_amount | decimal | Amount invoiced (requires |
total_cost | decimal | Actual costs (requires |
budget_invoiced_percent | decimal | Percentage invoiced (requires |
plan_only | boolean | Whether this is a planning deliverable only. |
purchase_number | string | null | Purchase order number. |
claim_items_count | integer | Number of progress claim items. |
project_phase_id | integer | null | Associated phase ID if grouped. |
tasks | array | Array of task objects. See Task Object below. |
Task Object
A task represents an individual work item within a deliverable. Tasks are ordered by the position field.
Attributes
Attribute | Type | Description |
id | integer | Unique identifier for the task. |
name | string | Task name. |
note | text | null | Additional notes or description. |
position | integer | Sort order within the deliverable (1-indexed). |
item_type | string | One of: "task", "heading", "event", "process_only". |
status | string | One of: "not_started", "in_progress", "completed", "not_applicable", "blocked". |
allow_time_tracking | string | Either "allowed", "not_allowed", or "allowed_if_assigned". |
active | boolean | Whether the task is active. |
visible | boolean | Whether the task is visible. |
currency | string | Currency code. |
due_date | string | null | Task due date. |
start_date | string | null | Task start date. |
estimated_start_date | string | null | Estimated start date. |
completed_date | string | null | Date the task was completed. |
budget_type | string | Either "fixed" or "hourly" (requires |
original_quantity_unit | string | Either "hour", "day", or "per_item" (requires |
original_rate | decimal | Rate per unit (requires |
original_duration | decimal | Estimated duration (requires |
original_total | decimal | Original budget (rate × duration) (requires |
variation_duration | decimal | Duration adjustments from variations (requires |
variation_total | decimal | Budget adjustments from variations (requires |
actual_duration | decimal | Actual time tracked (requires |
actual_total | decimal | Actual costs incurred (requires |
budget | decimal | Total budget including variations (requires |
total | decimal | Total budget (original + variations) (requires |
remaining | decimal | Budget remaining (requires |
budget_used_percentage | decimal | Percentage of budget used (requires |
tracked_times_count | integer | Number of time entries. |
costs_count | integer | Number of cost entries. |
booked_bookings_count | integer | Number of bookings. |
resource_type | object | null | Resource type with |
List all projects
Returns a paginated list of projects for the authenticated account. Results can be filtered using query parameters.
Endpoint
GET /api/v1/projects
Path Parameters
Parameter | Type | Description |
account_id | integer | The ID of the account to retrieve projects from. Must be an account the authenticated user has access to. |
Query Parameters
Parameter | Type | Description |
status | integer | Filter by project status ID. Only projects with this |
project_status | integer | Alternative filter by project status ID (same as |
assigned_to | integer | Filter by assigned user. Provide an |
project_tag_list | array of strings | Filter by project tags. Provide one or more tag names to return projects with any of those tags. Example: |
page | integer | Page number for pagination. Defaults to 1. |
items | integer | Number of items per page. Defaults to 20. |
Example Request
curl https://app.getdrum.com/api/v1/projects \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request with Filters
curl "https://app.getdrum.com/api/v1/projects?status=5&assigned_to=42&page=1&items=50" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request with Tags
curl "https://app.getdrum.com/api/v1/projects?project_tag_list[]=urgent&project_tag_list[]=design" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Returns an array of project objects. The index endpoint returns a lightweight representation without nested data.
Note: Financial fields (total_budget) are only included if the user has the view_project_metrics permission.
[
{
"id": 42,
"name": "Website Redesign for Acme Corp",
"project_number": "PRJ-001",
"description": "Complete overhaul of corporate website including new branding, responsive design, and CMS integration",
"currency": "AUD",
"project_type": "project",
"contract_type": "fixed_price",
"start_date": "2025-01-15",
"end_date": "2025-04-30",
"project_status": {
"id": 5,
"name": "In Progress",
"complete_status": false
},
"client": {
"id": 123,
"name": "Acme Corp",
"type": "Company"
},
"team": {
"id": 2,
"name": "Design Team"
},
"total_budget": 75000.00,
"planned": false
},
{
"id": 43,
"name": "Mobile App Development",
"project_number": "PRJ-002",
"description": "Native iOS and Android app for customer portal",
"currency": "AUD",
"project_type": "project",
"contract_type": "time_and_materials",
"start_date": "2025-02-01",
"end_date": "2025-07-31",
"project_status": {
"id": 5,
"name": "In Progress",
"complete_status": false
},
"client": {
"id": 124,
"name": "Tech Startup Inc",
"type": "Company"
},
"team": {
"id": 3,
"name": "Development Team"
},
"total_budget": 120000.00,
"planned": false
}
]
Note: The API uses pagination via the page and items query parameters. Use pagination metadata from response headers if available, or implement client-side pagination based on the number of results returned.
Retrieve a project
Retrieves the details of a specific project by ID.
Endpoint
GET /api/v1/projects/:id
Path Parameters
Parameter | Type | Description |
account_id | integer | The ID of the account the project belongs to. |
id | integer | The ID of the project to retrieve. |
Example Request
curl https://app.getdrum.com/api/v1/projects/42 \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Returns a comprehensive project object with nested deliverables and tasks.
Note: Financial fields require appropriate permissions:
Basic financial data (
total_budget,total_invoiced, etc.) requiresview_project_metricspermissionProfitability metrics (
work_in_progress,remaining_cost_to_complete) require bothview_project_metricsANDview_gross_profitpermissions
{
"id": 42,
"name": "Website Redesign for Acme Corp",
"project_number": "PRJ-001",
"description": "Complete overhaul of corporate website including new branding, responsive design, and CMS integration",
"currency": "AUD",
"project_type": "project",
"contract_type": "fixed_price",
"budget_type": "project_level",
"progress_claim_mode": "deliverable",
"start_date": "2025-01-15",
"end_date": "2025-04-30",
"completed_date": null,
"project_status": {
"id": 5,
"name": "In Progress",
"complete_status": false
},
"client": {
"id": 123,
"name": "Acme Corp",
"type": "Company"
},
"company_id": 123,
"team": {
"id": 2,
"name": "Design Team"
},
"total_budget": 75000.00,
"total_invoiced": 45000.00,
"costs_to_date": 38000.00,
"unbilled_costs": 5000.00,
"work_in_progress": 2000.00,
"remaining_cost_to_complete": 12000.00,
"quotes_count": 1,
"invoices_count": 3,
"progress_claims_count": 2,
"costs_count": 45,
"project_tags": ["web-design", "urgent"],
"planned": false,
"skip_planning": false,
"deliverables": [
{
"id": 1,
"name": "Discovery & Research",
"description": "Initial discovery phase including stakeholder interviews and requirements gathering",
"position": 1,
"status": "completed",
"billing_type": "fixed_fee",
"allow_time_tracking": "allowed",
"percentage_complete": 100,
"currency": "AUD",
"start_date": "2025-01-15",
"end_date": "2025-02-01",
"duration": 80.0,
"budget": 10000.00,
"invoiced_amount": 10000.00,
"total_cost": 9500.00,
"budget_invoiced_percent": 100.0,
"plan_only": false,
"purchase_number": null,
"claim_items_count": 0,
"tasks": [
{
"id": 1,
"name": "Client Interviews",
"note": "Interview key stakeholders to understand requirements",
"position": 1,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": "2025-01-20",
"start_date": "2025-01-15",
"estimated_start_date": null,
"completed_date": "2025-01-20T10:30:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 150.00,
"original_duration": 8.0,
"original_total": 1200.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 7.5,
"actual_total": 1125.00,
"budget": 1200.00,
"total": 1200.00,
"remaining": 75.00,
"budget_used_percentage": 93.75,
"tracked_times_count": 3,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 5,
"name": "Senior Consultant"
}
},
{
"id": 2,
"name": "Competitive Analysis",
"note": null,
"position": 2,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": "2025-01-25",
"start_date": "2025-01-20",
"estimated_start_date": null,
"completed_date": "2025-01-24T16:00:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 125.00,
"original_duration": 16.0,
"original_total": 2000.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 18.0,
"actual_total": 2250.00,
"budget": 2000.00,
"total": 2000.00,
"remaining": -250.00,
"budget_used_percentage": 112.5,
"tracked_times_count": 5,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 6,
"name": "UX Researcher"
}
}
]
},
{
"id": 2,
"name": "Design Phase",
"description": "UI/UX design and prototyping",
"position": 2,
"status": "in_progress",
"billing_type": "fixed_fee",
"allow_time_tracking": "allowed",
"percentage_complete": 45,
"currency": "AUD",
"start_date": "2025-02-01",
"end_date": "2025-03-15",
"duration": 120.0,
"budget": 15000.00,
"invoiced_amount": 0.00,
"total_cost": 6750.00,
"budget_invoiced_percent": 0.0,
"plan_only": false,
"purchase_number": null,
"claim_items_count": 0,
"tasks": [
{
"id": 3,
"name": "Wireframe Development",
"note": "Create low-fidelity wireframes for all pages",
"position": 1,
"item_type": "task",
"status": "completed",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": "2025-02-15",
"start_date": "2025-02-01",
"estimated_start_date": null,
"completed_date": "2025-02-14T14:00:00Z",
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 125.00,
"original_duration": 24.0,
"original_total": 3000.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 24.0,
"actual_total": 3000.00,
"budget": 3000.00,
"total": 3000.00,
"remaining": 0.00,
"budget_used_percentage": 100.0,
"tracked_times_count": 8,
"costs_count": 0,
"booked_bookings_count": 0,
"resource_type": {
"id": 6,
"name": "UX Researcher"
}
},
{
"id": 4,
"name": "High-Fidelity Mockups",
"note": "Design visual mockups based on approved wireframes",
"position": 2,
"item_type": "task",
"status": "in_progress",
"allow_time_tracking": "allowed",
"active": true,
"visible": true,
"currency": "AUD",
"due_date": "2025-03-01",
"start_date": "2025-02-15",
"estimated_start_date": null,
"completed_date": null,
"budget_type": "hourly",
"original_quantity_unit": "hour",
"original_rate": 150.00,
"original_duration": 40.0,
"original_total": 6000.00,
"variation_duration": 0.0,
"variation_total": 0.0,
"actual_duration": 25.0,
"actual_total": 3750.00,
"budget": 6000.00,
"total": 6000.00,
"remaining": 2250.00,
"budget_used_percentage": 62.5,
"tracked_times_count": 12,
"costs_count": 0,
"booked_bookings_count": 1,
"resource_type": {
"id": 7,
"name": "Senior Designer"
}
}
]
}
]
}Error Responses
The Projects API uses standard HTTP response codes to indicate success or failure.
HTTP Status Codes
Status Code | Description |
200 | Success - The request was successful. |
401 | Unauthorised - Missing, invalid, or expired API token. |
403 | Forbidden - The authenticated user lacks the required API permissions (api_read, api_create, api_update, or api_delete). |
404 | Not Found - The requested account or project does not exist, or the authenticated user does not have access. |
Error Response Format
Error responses include a standard structure with details about what went wrong:
{
"error": {
"message": "Project not found or not accessible",
"type": "not_found",
"code": 404
}
}Common Error Scenarios
401 Unauthorised
Occurs when:
No
Authorisationheader is providedThe API token is invalid or malformed
The API token has expired
Solution: Verify your API token is valid and properly included in the Authorization header.
403 Forbidden
Occurs when:
The authenticated user's role lacks the required API permissions
The account user has been archived or deactivated
Solution: Contact your account administrator to verify your API permissions. Admin users automatically have all API permissions.
404 Not Found
Occurs when:
The specified account ID doesn't exist or you don't have access
The specified project ID doesn't exist within the account
The project exists but belongs to a different account
The ID refers to an opportunity (use the Opportunities API instead)
Solution: Verify the account_id and project id are correct and that you have access to the account. If you receive a 404 when you know the ID exists, check if it's an opportunity (project_type: "opportunity") rather than a won project.
Rate Limiting
Currently, rate limiting is not enforced on API requests. However, infrastructure is in place for future rate limiting:
General API: 300 requests per 5 minutes per IP address
Per endpoint throttling may be introduced as needed
We recommend implementing exponential backoff in your API client to handle potential future rate limits gracefully.
API Permissions
The Projects API requires multiple levels of permissions:
Base API Permissions
Required based on HTTP method:
Method | Required Permission |
GET |
|
POST |
|
PUT/PATCH |
|
DELETE |
|
Project Visibility Permissions
In addition to api_read, users need one of the following permissions to view projects:
Permission | Description |
| Access all projects in the account |
| Access projects assigned to team members |
| Access only projects where user is directly assigned |
Financial Data Permissions
Financial data visibility is controlled by additional permissions:
Permission | Data Included |
| Basic financial data: |
| Profitability metrics: |
Note: Without these permissions, financial fields will be completely excluded from API responses. This ensures sensitive financial data is only visible to authorised users.
Permission Hierarchy
Account administrators automatically have all API permissions
Other users must be granted permissions through their account role configuration
Financial permissions are additive:
view_gross_profitrequiresview_project_metricsto be useful
Notes
Multi-tenancy: All projects are scoped to accounts. Users can only access projects from accounts they belong to.
Authorisation: The API enforces permission-based access. Users are restricted to projects they have permission to view based on their role configuration.
Soft Deletes: Deleted projects are soft-deleted (archived) rather than permanently removed. Archived projects are not returned by the API.
Money Format: All monetary amounts are returned in decimal format (e.g., 75000.00 for $75,000). The
currencyfield indicates the currency code.Date Format: Dates are returned in ISO 8601 format (YYYY-MM-DD). Date times include time zone information.
Project vs Opportunity: This endpoint returns only won projects (project_type: "project"). Opportunities (sales pipeline projects) are accessed through the Opportunities API. If you attempt to access an opportunity through this endpoint, you will receive a 404 Not Found response.
Nested Data: The show endpoint includes nested
deliverablesandtasksarrays, ordered bypositionfield. The index endpoint excludes this nested data for performance.Polymorphic Clients: Projects can be associated with either a Company (external client) or BusinessOverhead (internal work). The
clientobject includes atypefield to distinguish between these.Permission-Gated Fields: Financial and profitability data are conditionally included based on user permissions. API clients should handle missing fields gracefully.
Eager Loading: The API uses efficient eager loading to minimise database queries. Large projects with many deliverables/tasks may still result in substantial response payloads.
