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 |
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 |
team | object | null | Team assignment with |
Financial Metrics
Note:
total_budgetfollows the sameview_project_metricscheck used on the HTML project page.total_invoiced,costs_to_date, andunbilled_costsare only included when time tracking is enabled and the user can view project metrics, matching the HTML project page's financial views.On the index endpoint,
total_budgetfollows the same rules as the HTML projects index financial column: time tracking must be enabled and the user must have project insights access.
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. |
Project Health Metrics
Note:
work_in_progressis only included when the account is configured to show WIP on project financial views.remaining_cost_to_completeis only included when cost-to-complete estimates are enabled and shown for projects.Both fields also require the same time-tracking and
view_project_metricsaccess needed for the HTML project financial views.
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. See Deliverable Object. |
contacts | array | Array of contact objects associated with the project, ordered by |
addresses | array | Array of address objects associated with the project. Ordered with |
Example Payloads
For concrete JSON payloads, see:
List all projects — the index (lightweight) shape
Retrieve a project — the show shape with nested
deliverables,contacts, andaddresses
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. |
claim_items_count | integer | Number of progress claim items. |
project_phase_id | integer | null | Associated phase ID if grouped. Only included when set. |
tasks | array | Array of task objects. See Task Object. |
Requires the same access as the HTML project deliverables view (omitted otherwise): time tracking must be enabled and the user must have view_project_metrics.
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. |
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 |
Requires the same access as the HTML project tasks view (omitted otherwise): time tracking must be enabled and the user must have view_project_metrics.
Contact Object
A contact represents a person associated with the project — typically the client-side point of contact, site representative, or other stakeholder. Contacts are ordered by the position field.
Attributes
Attribute | Type | Description |
id | integer | Unique identifier for the contact. |
first_name | string | Contact's first name. |
last_name | string | null | Contact's last name. |
name | string | Full name (first + last). |
string | null | Email address. | |
mobile_phone | string | null | Mobile phone number. |
office_phone | string | null | Office phone number. |
title | string | null | Job title or role (e.g., "Project Manager", "CEO"). |
description | string | null | Notes about this contact's involvement in the project. |
pinned | boolean | Whether the contact is pinned/highlighted on the project. |
position | integer | null | Sort order within the project's contacts list. |
Address Object
An address represents a physical location associated with the project — typically the site address, billing address, or other location-specific details. A project may have multiple addresses.
Attributes
Attribute | Type | Description |
id | integer | Unique identifier for the address. |
address_type | string | null | Either |
billing_address | boolean | Whether this is the billing address for the project. |
primary | boolean | Whether this is the primary address for the project. |
line_one | string | First address line (e.g., street number and name). |
line_two | string | null | Second address line (e.g., unit number). |
suburb | string | null | Suburb or city. |
state | string | null | State, province, or region. |
post_code | string | null | Postal or ZIP code. |
country | string | null | Two-letter ISO country code (e.g., |
lot_number | string | null | Lot number (used primarily for construction projects in AU/NZ markets). |
note | string | null | Freeform notes about the address. |
List all projects
Returns a paginated list of projects for the authenticated account. Results can be filtered using query parameters.
Endpoint
GET /api/v1/accounts/:account_id/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.drumhq.com/api/v1/accounts/1/projects \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request with Filters
curl "https://app.drumhq.com/api/v1/accounts/1/projects?status=5&assigned_to=42&page=1&items=50" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request with Tags
curl "https://app.drumhq.com/api/v1/accounts/1/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",
"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",
"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/accounts/:account_id/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.drumhq.com/api/v1/accounts/1/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",
"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"
},
"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,
"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,
"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"
}
}
]
}
],
"contacts": [
{
"id": 301,
"first_name": "Jane",
"last_name": "Doe",
"name": "Jane Doe",
"email": "[email protected]",
"mobile_phone": "+61 400 000 000",
"office_phone": "",
"title": "Head of Marketing",
"description": "Primary approver for creative decisions",
"pinned": true,
"position": 1
},
{
"id": 302,
"first_name": "John",
"last_name": "Smith",
"name": "John Smith",
"email": "[email protected]",
"mobile_phone": "",
"office_phone": "+61 2 9000 0000",
"title": "Finance Manager",
"description": null,
"pinned": false,
"position": 2
}
],
"addresses": [
{
"id": 1001,
"address_type": "physical",
"billing_address": true,
"primary": true,
"line_one": "10 George Street",
"line_two": "Level 3",
"suburb": "Sydney",
"state": "NSW",
"post_code": "2000",
"country": "AU",
"lot_number": "",
"note": "Access via rear loading bay"
}
]
}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 | Unauthorized - 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 Unauthorized
Occurs when:
No
Authorizationheader 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 authorized 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
Soft Deletes: Deleted projects are archived (soft-deleted) and excluded from API responses.
Money Format: Monetary amounts are decimals (e.g.,
75000.00) in the currency indicated by thecurrencyfield.Date Format: Dates use ISO 8601 (
YYYY-MM-DD); datetimes include a time zone.Project vs Opportunity: This endpoint returns only won projects (
project_type: "project"). Opportunities are served by the Opportunities API; requesting an opportunity ID here returns 404.Nested Data: The show endpoint embeds
deliverables(withtasks),contacts, andaddresses. Deliverables, tasks, and contacts are ordered byposition; addresses surfaceprimarythenbillingfirst. Index excludes all nested data.Polymorphic Clients: A project's
clientcan be aCompany(external) orBusinessOverhead(internal). Theclient.typefield distinguishes them.Permission-Gated Fields: Financial and profitability fields are omitted entirely when the user lacks the relevant permission — clients should treat them as optional.
