Projects
A project is won work that is active or completed. Drum stores opportunities in the same table, but these endpoints return delivery projects only. For pipeline work, use Opportunities.
GET /api/v1/projects
Lists the delivery projects the token’s user can read. Deleted projects are left out. Paginated (see Pagination). Rows are not returned in a guaranteed order.
Filters
| Parameter | Meaning |
|---|---|
project_number |
Exact project number. Surrounding spaces are ignored |
status |
Project status id, or an array of ids (status[]=401&status[]=402). all turns the filter off |
project_status |
One project status id |
assigned_to |
Member id, or an array of ids. Include none_assigned to also return projects with nobody in a project role |
project_tag_list |
A tag name (project_tag_list=Civil) or an array of tag names (project_tag_list[]=Civil&project_tag_list[]=Roads). A project must carry every tag |
active_only |
true for projects whose status is not complete |
completed_only |
true for projects whose status is complete. Cannot be sent with active_only |
completed_from, completed_to |
Completed on or after, or on or before, a yyyy-mm-dd date |
project_template_ids |
Array of project template ids |
team_ids |
Array of team ids |
client_ids |
Array of client company ids |
custom_fields |
Up to 10 rows of {custom_field_id, values}, for select and multiselect custom fields of project templates. In a query string: custom_fields[0][custom_field_id]=5&custom_fields[0][values][]=NSW |
An invalid value for one of the last eight filters returns 422 invalid_input.
Response
Each row is a compact project:
[
{
"id": 20488,
"name": "Riverside fit-out",
"project_number": "2026-088",
"description": "Ground floor refurbishment",
"currency": "AUD",
"project_type": "project",
"start_date": "2026-10-01",
"end_date": "2026-12-15",
"completed_date": null,
"project_status": {"id": 410, "name": "In Progress", "complete_status": false},
"client": {"id": 789, "name": "Acme Corporation", "type": "Company"},
"team": {"id": 42, "name": "Fit-out"},
"total_budget": 48500.0,
"gross_profit": {"realised_percentage": 31.2, "projected_percentage": 28.0},
"planned": false
}
]
project_status, client and team are left out when the project has none. total_budget and gross_profit follow the rules under Money fields.
GET /api/v1/projects/:id
Returns one delivery project with its deliverables and tasks, contacts, addresses and custom fields.
curl -H "Authorization: Bearer $DRUM_API_TOKEN" \
https://app.getdrum.com/api/v1/projects/20488
Project fields
| Field | Meaning |
|---|---|
id, name, description, project_number, currency |
As recorded |
project_type |
Always project here |
progress_claim_mode |
How the project claims progress |
invoice_payment_terms, invoice_payment_terms_type |
The project’s payment terms |
start_date, end_date, completed_date |
Dates, or null. completed_date is set when the project moves to a complete status |
project_status |
{id, name, complete_status} |
client |
{id, name, type}. type is Company for a client, or BusinessOverhead for internal work |
referrer_company |
{id, name} of the company that referred the work, or null |
referrer_contact |
{id, name, email} of the person who referred the work, or null |
team |
{id, name} |
members |
[{id, name, project_role}]. One row for each project role a member holds. id is the member id. project_role is {id, name} |
quotes_count, invoices_count, progress_claims_count, costs_count |
Counts |
project_tags |
Tag names |
planned, skip_planning |
Resource planning flags |
deliverables |
See below |
contacts |
[{id, first_name, last_name, name, email, mobile_phone, office_phone, title, description, pinned, position}] |
addresses |
[{id, address_type, billing_address, primary, line_one, line_two, suburb, state, post_code, country, lot_number, note}]. Primary and billing addresses come first |
custom_fields |
[{id, position, custom_field_id, label, field_type, value}] |
Money fields
All project money is a decimal in the project’s currency, tax exclusive.
| Fields | Shown when |
|---|---|
total_budget, and on a project with retention: retention_percent, retention_amount, retention_withheld, retention_released, retention_outstanding |
The token’s user can see the project’s budget: view_project_metrics, or a project role on this project that can view budgets |
total_invoiced, costs_to_date, committed, unbilled_costs |
As above, and the account uses time tracking |
has_time_and_materials_deliverables, time_and_materials_budget_total, time_and_materials_earned_revenue, time_and_materials_unbilled_revenue, time_and_materials_only |
As above, on a project with time and materials deliverables |
work_in_progress |
As above, and the account shows WIP on the project list |
remaining_cost_to_complete |
As above, and the account uses cost to complete estimates and shows them on the project list |
gross_profit (realised_percentage, projected_percentage, realised, realised_costs, projected, projected_revenue, actual_costs) |
view_gross_profit, and the account shows gross profit. The list returns the two percentages only |
A field that is not shown is left out of the response.
has_time_and_materials_procedures is a deprecated copy of has_time_and_materials_deliverables. Use the new name.
Deliverables and tasks
deliverables is ordered by position. Each deliverable has:
| Field | Meaning |
|---|---|
id, name, description, position, status, currency |
As recorded |
budget_type |
How the deliverable is priced |
allow_time_tracking |
Whether time can be logged |
percentage_complete, claim_items_count |
Progress |
start_date, end_date, duration |
Schedule |
project_phase_id |
Present when the deliverable is in a phase |
budget, invoiced_amount, total_cost, budget_invoiced_percent |
Money. Shown under the same rule as total_invoiced |
tasks |
The deliverable’s tasks, ordered by position |
Each task has:
| Field | Meaning |
|---|---|
id, name, note, position, item_type, status, currency |
As recorded |
allow_time_tracking, active, visible |
Flags |
due_date, start_date, estimated_start_date, completed_date |
Dates |
tracked_times_count, costs_count, booked_bookings_count |
Counts |
resource_type |
{id, name}, when the task has one |
budget_type, original_quantity_unit, original_rate, original_duration, original_total, variation_duration, variation_total, actual_duration, actual_total, budget, total, remaining, budget_used_percentage |
Money and budget. Shown under the same rule as total_invoiced |
Use a task id as the task_id when you log time or record a cost.
Permissions
| Endpoint | Needs |
|---|---|
GET /projects |
api_read, and read_all_projects, read_team_projects or read_assigned_projects. A timesheet-only member cannot list projects |
GET /projects/:id |
api_read, and read access to that project |
Errors
| Status | Body | When |
|---|---|---|
403 |
{"error": "Forbidden"} |
GET /projects without a project read permission |
404 |
Empty | The id does not exist in the token’s account, belongs to another account, is deleted, is an opportunity, or is a project the token’s user cannot read |
422 |
{"error": ..., "code": "invalid_input", "field": ...} |
A filter value could not be read |