Profitability Report

The Profitability Report returns revenue, cost, profit and return-on-cost for a timeframe, grouped by project, client, team member or task. Results are ranked by total_profit descending.

The profitability result object

Attribute Type Description
project_id integer The ID of the project. Returned in the project grouping.
project_name string The name of the project. Returned in the project grouping. Includes the project code.
client_id integer The ID of the client. Returned in the project and client groupings.
client_name string The name of the client. Returned in the project and client groupings.
project_type string The project’s type: fixed_fee, time_and_materials, or non_billable. Returned in the project grouping.
user_id integer The ID of the user. Returned in the team grouping.
user_name string The name of the user. Returned in the team grouping.
task_id integer The ID of the task. Returned in the task grouping.
task_name string The name of the task. Returned in the task grouping.
is_active boolean Whether the subject had activity in the timeframe. For a client, this is the client’s own activity or that of a contributing fixed-fee project.
currency string The company’s ISO 4217 currency code. It applies to revenue, not to cost.
missing_rates boolean Whether a billable rate, a cost rate or a fixed-fee fee is missing.
missing_dates boolean Whether a fixed-fee project lacks a start or end date. Returned in every grouping; false where it does not apply.
total_revenue decimal Billable time and expenses, plus attributable fixed-fee revenue, in currency. The task grouping omits expenses.
total_cost decimal Time, expense and fixed-fee cost. Not limited to currency.
total_profit decimal Revenue minus cost. May mix currencies.
invoiced_revenue decimal Invoiced revenue. The task grouping omits expense revenue.
uninvoiced_revenue decimal Uninvoiced revenue, including fixed-fee revenue. The task grouping omits expense revenue.
return_on_cost integer Return on cost as a whole percentage: round(total_profit / total_cost * 100). It is null when cost is zero and profit is non-zero, and 0 when both are zero.
return_on_cost_unbounded string positive or negative when return_on_cost is null; otherwise null.

Required permissions

The profitability report must be enabled for the account. Results are limited to the projects the calling user can see, and the filters do not widen that scope.

Profitability Report

Beta endpoint. Fully available, but the response shape may still change. Until it is frozen, every response includes Harvest-Api-Stability: beta.

GET /v2/reports/profitability
Parameter Type Description
from date Required. Inclusive first day of the timeframe.
to date Required. Inclusive last day of the timeframe. The timeframe cannot exceed 365 days.
group_by string The grouping for the results: project, client, team, or task. When absent, it defaults to team if project_id is given, to project if client_id is given, and otherwise to client.
client_id integer Only report on the given client and its projects.
project_id integer Only report on the given project.
page integer The page number to use in pagination. (Default: 1)
per_page integer The number of records to return per page. Can range between 1 and 2000. (Default: 2000)

A query parameter the report does not support is refused rather than ignored.

Example Request:

curl "https://api.harvestapp.com/v2/reports/profitability?from=2026-09-01&to=2026-09-30&group_by=project" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Harvest-Account-Id: $ACCOUNT_ID" \
  -H "User-Agent: MyApp ([email protected])"

Example Response:

{
  "group_by": "project",
  "results": [
    {
      "project_id": 14307913,
      "project_name": "[MW] Marketing Website",
      "client_id": 5735774,
      "client_name": "ABC Corp",
      "project_type": "time_and_materials",
      "is_active": true,
      "currency": "USD",
      "missing_rates": false,
      "missing_dates": false,
      "total_revenue": 1250.0,
      "total_cost": 800.0,
      "total_profit": 450.0,
      "invoiced_revenue": 500.0,
      "uninvoiced_revenue": 750.0,
      "return_on_cost": 56,
      "return_on_cost_unbounded": null
    }
  ],
  "per_page": 2000,
  "total_pages": 1,
  "total_entries": 1,
  "next_page": null,
  "previous_page": null,
  "page": 1,
  "links": {
    "first": "https://api.harvestapp.com/v2/reports/profitability?from=2026-09-01&group_by=project&page=1&per_page=2000&to=2026-09-30",
    "next": null,
    "previous": null,
    "last": "https://api.harvestapp.com/v2/reports/profitability?from=2026-09-01&group_by=project&page=1&per_page=2000&to=2026-09-30"
  }
}

Errors

Status When
400 The User-Agent header is missing: User-Agent header required.
400 A date is missing or invalid, the range is reversed or exceeds 365 days, or a grouping, ID, page bound or unsupported query parameter is invalid. Messages include Cannot complete your request. Parameter is missing or the value is empty: from, Invalid from date provided: "nope", Invalid timeframe: from must not be later than to, Invalid timeframe: must not exceed 1 year, Invalid group_by provided: "clients", Invalid client_id integer provided: "one", Invalid page parameter: must be greater than 0, Invalid per_page parameter: must be from 1 to 2000, and Invalid <param>[, <param>…] parameter: not supported by this endpoint.
401 Authentication failed: Authentication failed for API request.
403 The profitability report is not enabled for the account: Profitability report is not enabled for this account.
403 The caller does not have permission to read the report: Not authorized!.
403 The account is inactive: Account inactive.
406 The Accept header disallows JSON.
422 The cursor parameter is malformed.
500 An unexpected failure.

Still have questions? We’re happy to help!

Contact Us