API reference

A REST API with familiar conventions — if you have tooling built against Harvest v2, it mostly ports by changing the base URL and token. Machine-readable spec: /api/v1/openapi.json (imports straight into Postman).

Authentication

Send Authorization: Bearer <token>. Two token kinds, both created on the in-app Developer page:

Endpoints marked manager+ or admin refuse lower-grade personal tokens — money (rates, invoices, reports) never reaches member tokens.

Conventions

Company

The authenticated workspace.

GET/v1/companyRetrieve the company

Time entries

Tracked time. Member-grade personal tokens see and modify only their own entries; submitted or approved weeks are locked.

GET/v1/time_entriesList time entries
PARAMETERS
  • fromOnly entries on/after this date (YYYY-MM-DD)
  • toOnly entries on/before this date
  • user_idFilter to one member
  • client_idFilter by client
  • project_idFilter by project
  • task_idFilter by task
  • billabletrue/false
  • is_billedtrue = already invoiced
  • is_runningtrue = timer currently running
  • approval_statusunsubmitted, submitted, or approved
  • external_reference_idMatch an external reference
  • updated_sinceISO 8601 datetime
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/time_entriesCreate a time entry

Personal tokens log as their owner. Weeks already submitted for approval refuse new time (422).

BODY
  • project_idUUID, required
  • task_idUUID, required
  • spent_dateYYYY-MM-DD, required
  • hoursDecimal hours (rounded per org policy)
  • notesEntry notes
  • billableDefaults true
  • external_reference.idExternal system reference (e.g. issue key)
  • user_idRequired with an organization key; ignored for personal tokens
GET/v1/time_entries/{id}Retrieve a time entry
PARAMETERS
  • id (required)The time entry id (UUID)
PATCH/v1/time_entries/{id}Update a time entry

Locked (approved/invoiced) and submitted entries return 422.

PARAMETERS
  • id (required)The time entry id (UUID)
BODY
  • project_idUUID
  • task_idUUID
  • spent_dateYYYY-MM-DD (target week must be open)
  • hoursDecimal hours
  • notesEntry notes
  • billabletrue/false
  • external_reference.idSet or replace the external reference
DELETE/v1/time_entries/{id}Delete a time entry
PARAMETERS
  • id (required)The time entry id (UUID)
PATCH/v1/time_entries/{id}/restartRestart the timer on an entry · personal token

Personal tokens only — timers belong to a person. Stops any other running timer.

PARAMETERS
  • id (required)The time entry id (UUID)
PATCH/v1/time_entries/{id}/stopStop the running timer on an entry
PARAMETERS
  • id (required)The time entry id (UUID)
DELETE/v1/time_entries/{id}/external_referenceRemove an entry’s external reference
PARAMETERS
  • id (required)The time entry id (UUID)

Clients

Clients and their currencies.

GET/v1/clientsList clients
PARAMETERS
  • nameCase-insensitive name fragment
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/clientsCreate a client · manager+
BODY
  • nameRequired
  • currency3-letter code
  • addressPostal address
  • notesNotes
GET/v1/clients/{id}Retrieve a client
PARAMETERS
  • id (required)The client id (UUID)
PATCH/v1/clients/{id}Update a client · manager+
PARAMETERS
  • id (required)The client id (UUID)
BODY
  • nameClient name
  • currency3-letter code
  • addressPostal address
  • notesNotes
DELETE/v1/clients/{id}Archive a client · manager+

Refuses (422) while the client has active projects.

PARAMETERS
  • id (required)The client id (UUID)

Projects

Projects, and who is assigned to them.

GET/v1/projectsList projects
PARAMETERS
  • client_idFilter by client
  • is_activetrue/false
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/projectsCreate a project · manager+
BODY
  • client_idUUID, required
  • nameRequired
  • codeShort code
  • hourly_rateProject hourly rate
  • starts_onYYYY-MM-DD
  • ends_onYYYY-MM-DD
GET/v1/projects/{id}Retrieve a project
PARAMETERS
  • id (required)The project id (UUID)
PATCH/v1/projects/{id}Update a project · manager+
PARAMETERS
  • id (required)The project id (UUID)
BODY
  • client_idUUID
  • nameProject name
  • codeShort code
  • is_activefalse archives, true restores
  • hourly_rateProject hourly rate
  • starts_onYYYY-MM-DD
  • ends_onYYYY-MM-DD
DELETE/v1/projects/{id}Archive a project · manager+
PARAMETERS
  • id (required)The project id (UUID)
GET/v1/projects/{id}/user_assignmentsList a project’s people
PARAMETERS
  • id (required)The project id (UUID)
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/projects/{id}/user_assignmentsAssign a person to a project · manager+
PARAMETERS
  • id (required)The project id (UUID)
BODY
  • user_idMember UUID, required
  • is_project_managerGrants the PM flag
  • hourly_ratePer-assignment billable rate
PATCH/v1/projects/{id}/user_assignments/{assignmentId}Update an assignment · manager+
PARAMETERS
  • id (required)The project id (UUID)
  • assignmentId (required)Assignment UUID
BODY
  • is_project_managerPM flag
  • hourly_ratePer-assignment billable rate
DELETE/v1/projects/{id}/user_assignments/{assignmentId}Remove an assignment · manager+
PARAMETERS
  • id (required)The project id (UUID)
  • assignmentId (required)Assignment UUID
GET/v1/projects/{id}/task_assignmentsList a project’s tasks (compatibility view)

Tasks belong to projects here, so each task is its own assignment.

PARAMETERS
  • id (required)The project id (UUID)
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)

Tasks

Tasks (each belongs to one project — a deviation from Harvest).

GET/v1/tasksList tasks
PARAMETERS
  • project_idFilter by project
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/tasksCreate a task · manager+
BODY
  • project_idUUID, required
  • nameRequired
  • billable_by_defaultDefaults true
  • default_hourly_rateTask rate
GET/v1/tasks/{id}Retrieve a task
PARAMETERS
  • id (required)The task id (UUID)
PATCH/v1/tasks/{id}Update a task · manager+
PARAMETERS
  • id (required)The task id (UUID)
BODY
  • nameTask name
  • billable_by_defaulttrue/false
  • default_hourly_rateTask rate
DELETE/v1/tasks/{id}Delete a task · manager+
PARAMETERS
  • id (required)The task id (UUID)

Users

Workspace members. Rates are money — manager+ tokens only.

GET/v1/usersList users
PARAMETERS
  • roleowner, admin, manager, or member
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
GET/v1/users/meRetrieve the token’s owner · personal token
GET/v1/users/{id}Retrieve a user
PARAMETERS
  • id (required)The user id (UUID)
GET/v1/users/{id}/billable_ratesList a user’s billable rates · manager+
PARAMETERS
  • id (required)The user id (UUID)
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
GET/v1/users/{id}/cost_ratesList a user’s cost rates · manager+
PARAMETERS
  • id (required)The user id (UUID)
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
GET/v1/users/{id}/project_assignmentsList a user’s project assignments
PARAMETERS
  • id (required)The user id (UUID)
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
GET/v1/users/{id}/teammatesList a user’s direct reports
PARAMETERS
  • id (required)The user id (UUID)
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)

Roles

Work roles (job functions), assignable to members.

GET/v1/rolesList roles
PARAMETERS
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/rolesCreate a role · manager+
BODY
  • nameRequired
PATCH/v1/roles/{id}Update a role · manager+
PARAMETERS
  • id (required)The role id (UUID)
BODY
  • nameRequired
DELETE/v1/roles/{id}Delete a role · manager+
PARAMETERS
  • id (required)The role id (UUID)

Invoices

Invoices, payments, and sending. Admin tokens or organization keys only.

GET/v1/invoicesList invoices
PARAMETERS
  • statedraft, open, partially_paid, paid, closed
  • client_idFilter by client
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/invoicesCreate an invoice · admin

Provide line_items OR period_start+period_end. Generated invoices mark hours billed so nothing is double-invoiced.

BODY
  • client_idUUID, required
  • line_itemsArray of {kind, description, quantity, unit_price} for a free-form invoice
  • period_startWith period_end: generate from uninvoiced time instead
  • period_endYYYY-MM-DD
  • groupingtask (default), person, or detailed
  • include_expensesDefaults true
  • subjectSubject line
  • issue_dateDefaults today
  • due_dateYYYY-MM-DD
  • taxPercent
  • discountPercent
GET/v1/invoices/{id}Retrieve an invoice (lines + payments)
PARAMETERS
  • id (required)The invoice id (UUID)
PATCH/v1/invoices/{id}Update a draft invoice · admin
PARAMETERS
  • id (required)The invoice id (UUID)
BODY
  • subjectSubject
  • notesNotes
  • issue_dateYYYY-MM-DD
  • due_dateYYYY-MM-DD
  • taxPercent
  • discountPercent
DELETE/v1/invoices/{id}Delete a draft invoice · admin
PARAMETERS
  • id (required)The invoice id (UUID)
POST/v1/invoices/{id}/messagesMark an invoice sent · admin

Moves draft → open. Email delivery stays a deliberate in-app action.

PARAMETERS
  • id (required)The invoice id (UUID)
POST/v1/invoices/{id}/paymentsRecord a payment · admin
PARAMETERS
  • id (required)The invoice id (UUID)
BODY
  • amountRequired
  • paid_dateYYYY-MM-DD, required
  • notesNotes
DELETE/v1/invoices/{id}/payments/{paymentId}Delete a payment · admin
PARAMETERS
  • id (required)The invoice id (UUID)
  • paymentId (required)Payment UUID

Estimates

Quotes that convert to invoices. Admin tokens or organization keys only.

GET/v1/estimatesList estimates · manager+
PARAMETERS
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/estimatesCreate an estimate · admin
BODY
  • client_idUUID, required
  • line_itemsArray of {kind, description, quantity, unit_price}, required
  • subjectSubject
  • issue_dateDefaults today
  • taxPercent
  • discountPercent
GET/v1/estimates/{id}Retrieve an estimate · manager+
PARAMETERS
  • id (required)The estimate id (UUID)
PATCH/v1/estimates/{id}Change estimate state · admin
PARAMETERS
  • id (required)The estimate id (UUID)
BODY
  • statesent, accepted, or declined
DELETE/v1/estimates/{id}Delete a draft estimate · admin
PARAMETERS
  • id (required)The estimate id (UUID)
POST/v1/estimates/{id}/convertConvert to a draft invoice · admin
PARAMETERS
  • id (required)The estimate id (UUID)

Expenses

Expenses and categories. Member tokens manage their own.

GET/v1/expensesList expenses
PARAMETERS
  • user_idRequired with an organization key
  • fromYYYY-MM-DD
  • toYYYY-MM-DD
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/expensesCreate an expense
BODY
  • spent_dateYYYY-MM-DD, required
  • total_costRequired
  • project_idUUID
  • expense_category_idUUID
  • billabletrue/false
  • is_reimbursabletrue/false
  • notesNotes
  • user_idRequired with an organization key
DELETE/v1/expenses/{id}Delete an expense
PARAMETERS
  • id (required)The expense id (UUID)
GET/v1/expense_categoriesList expense categories
PARAMETERS
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)
POST/v1/expense_categoriesCreate an expense category · manager+
BODY
  • nameRequired
  • unit_priceFor unit-based categories

Reports

Aggregations with money — manager+ tokens or organization keys.

GET/v1/reports/time/{dimension}Time report by clients, projects, tasks, or team · manager+
PARAMETERS
  • dimension (required)clients, projects, tasks, or team
  • from (required)YYYY-MM-DD
  • to (required)YYYY-MM-DD
GET/v1/reports/expenses/{dimension}Expense report by categories, projects, or team · manager+
PARAMETERS
  • dimension (required)categories, projects, or team
  • from (required)YYYY-MM-DD
  • to (required)YYYY-MM-DD
GET/v1/reports/project_budgetHours budget vs actual per project · manager+
PARAMETERS
  • from (required)YYYY-MM-DD
  • to (required)YYYY-MM-DD
GET/v1/reports/uninvoicedApproved, unbilled hours and amounts per project · manager+
PARAMETERS
  • pagePage number, starting at 1
  • per_pageItems per page (default 100, max 2000)