Users
The user object
| Attribute | Type | Description |
|---|---|---|
id |
integer | Unique ID for the user. |
first_name |
string | The first name of the user. |
last_name |
string | The last name of the user. |
email |
string | The email address of the user. |
telephone |
string | The user’s telephone number. |
timezone |
string | The user’s timezone. |
has_access_to_all_future_projects |
boolean | Whether the user should be automatically added to future projects. |
is_contractor |
boolean | Whether the user is a contractor or an employee. |
is_active |
boolean | Whether the user is active or archived. |
saml_exempt |
boolean | Whether the user is exempt from required single sign-on (SSO). Exempt users sign in with their email, password, and multi-factor authentication instead. Only returned to Administrators on accounts that require SSO with exemptions enabled. |
weekly_capacity |
integer | The number of hours per week this person is available to work in seconds, in half hour increments. For example, if a person’s capacity is 35 hours, the API will return 126000 seconds. |
default_hourly_rate |
decimal | The billable rate to use for this user when they are added to a project. |
cost_rate |
decimal | The cost rate to use for this user when calculating a project’s costs vs billable amount. |
roles |
array of strings | Descriptive names of the business roles assigned to this person. They can be used for filtering reports, and have no effect in their permissions in Harvest. |
access_roles |
array of strings | Access role(s) that determine the user’s permissions in Harvest. Possible values: administrator, manager or member. Users with the manager role can additionally be granted one or more of these roles: project_creator, billable_rates_manager, managed_projects_invoice_drafter, managed_projects_invoice_manager, client_and_task_manager, time_and_expenses_manager, estimates_manager. On accounts using the newer permissions model, the possible values are administrator, executive_manager, people_admin, accounting, project_manager or member, and you can send the name of one of the account’s custom profiles instead. |
permissions_profile |
string | The name of the profile this person’s permissions currently match: one of the account’s custom profiles when their permissions match one, otherwise their access role. Owner for the account owner. Writable on create and update — see custom profiles. |
avatar_url |
string | The URL to the user’s avatar image. |
created_at |
datetime | Date and time the user was created. |
updated_at |
datetime | Date and time the user was last updated. |
Required permissions
You must be an Administrator or Manager with assigned teammates in order to interact with the /v2/users endpoint, except when retrieving the currently authenticated user. Managers cannot edit emails, roles, or permissions, nor can they archive, restore, or delete assigned temmates. Managers with permission to see billable rates will have access to their teammates’ default hourly rates. Insufficient permissions will result in a 403 Forbidden status code.
List all users
Returns a list of your users. The users are returned sorted by creation date, with the most recently created users appearing first.
The response contains an object with a users property that contains an array of up to per_page users. Each entry in the array is a separate user object. If no more users are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your users.
GET /v2/users
| Parameter | Type | Description |
|---|---|---|
is_active |
boolean | Pass true to only return active users and false to return inactive users. |
updated_since |
datetime | Only return users that have been updated since the given date and time. |
page |
integer | DEPRECATED The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1) |
per_page |
integer | The number of records to return per page. Can range between 1 and 2000. (Default: 2000) |
page parameter.
For more information, visit the pagination guide.
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example response:
{
"users":[
{
"id":3230547,
"first_name":"Jim",
"last_name":"Allen",
"email":"[email protected]",
"telephone":"",
"timezone":"Mountain Time (US & Canada)",
"has_access_to_all_future_projects":false,
"is_contractor":false,
"is_active":true,
"created_at":"2020-05-01T22:34:41Z",
"updated_at":"2020-05-01T22:34:52Z",
"weekly_capacity":126000,
"default_hourly_rate":100.0,
"cost_rate":50.0,
"roles":["Developer"],
"access_roles": ["member"],
"avatar_url":"https://cache.harvestapp.com/assets/profile_images/abraj_albait_towers.png?1498516481"
},
{
"id":1782959,
"first_name":"Kim",
"last_name":"Allen",
"email":"[email protected]",
"telephone":"",
"timezone":"Eastern Time (US & Canada)",
"has_access_to_all_future_projects":true,
"is_contractor":false,
"is_active":true,
"created_at":"2020-05-01T22:15:45Z",
"updated_at":"2020-05-01T22:32:52Z",
"weekly_capacity":126000,
"default_hourly_rate":100.0,
"cost_rate":50.0,
"roles":["Designer"],
"access_roles": ["member"],
"avatar_url":"https://cache.harvestapp.com/assets/profile_images/cornell_clock_tower.png?1498515345"
},
{
"id":1782884,
"first_name":"Bob",
"last_name":"Powell",
"email":"[email protected]",
"telephone":"",
"timezone":"Mountain Time (US & Canada)",
"has_access_to_all_future_projects":false,
"is_contractor":false,
"is_active":true,
"created_at":"2020-05-01T20:41:00Z",
"updated_at":"2020-05-01T20:42:25Z",
"weekly_capacity":126000,
"default_hourly_rate":100.0,
"cost_rate":75.0,
"roles":["Founder", "CEO"],
"access_roles": ["administrator"],
"avatar_url":"https://cache.harvestapp.com/assets/profile_images/allen_bradley_clock_tower.png?1498509661"
}
],
"per_page":2000,
"total_pages":1,
"total_entries":3,
"next_page":null,
"previous_page":null,
"page":1,
"links":{
"first":"https://api.harvestapp.com/v2/users?page=1&per_page=2000",
"next":null,
"previous":null,
"last":"https://api.harvestapp.com/v2/users?page=1&per_page=2000"
}
}Retrieve the currently authenticated user
Retrieves the currently authenticated user. Returns a user object and a 200 OK response code.
GET /v2/users/me
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users/me" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example response:
{
"id":1782884,
"first_name":"Bob",
"last_name":"Powell",
"email":"[email protected]",
"telephone":"",
"timezone":"Mountain Time (US & Canada)",
"has_access_to_all_future_projects":false,
"is_contractor":false,
"is_active":true,
"created_at":"2020-05-01T20:41:00Z",
"updated_at":"2020-05-01T20:42:25Z",
"weekly_capacity":126000,
"default_hourly_rate":100.0,
"cost_rate":75.0,
"roles":["Founder", "CEO"],
"access_roles": ["administrator"],
"avatar_url":"https://cache.harvestapp.com/assets/profile_images/allen_bradley_clock_tower.png?1498509661"
}Retrieve a user
Retrieves the user with the given ID. Returns a user object and a 200 OK response code if a valid identifier was provided.
GET /v2/users/{USER_ID}
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users/3230547" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])"
Example response:
{
"id":3230547,
"first_name":"Jim",
"last_name":"Allen",
"email":"[email protected]",
"telephone":"",
"timezone":"Mountain Time (US & Canada)",
"has_access_to_all_future_projects":false,
"is_contractor":false,
"is_active":true,
"created_at":"2020-05-01T22:34:41Z",
"updated_at":"2020-05-01T22:34:52Z",
"weekly_capacity":126000,
"default_hourly_rate":100.0,
"cost_rate":50.0,
"roles":["Developer"],
"access_roles": ["member"],
"avatar_url":"https://cache.harvestapp.com/assets/profile_images/abraj_albait_towers.png?1498516481"
}Create a user
Creates a new user object and sends an invitation email to the address specified in the email parameter. Returns a user object and a 201 Created response code if the call succeeded.
POST /v2/users
| Parameter | Type | Required | Description |
|---|---|---|---|
first_name |
string | required | The first name of the user. |
last_name |
string | required | The last name of the user. |
email |
string | required | The email address of the user. |
timezone |
string | optional | The user’s timezone. Defaults to the company’s timezone. See a list of supported time zones. |
has_access_to_all_future_projects |
boolean | optional | Whether the user should be automatically added to future projects. Defaults to false. |
is_contractor |
boolean | optional | Whether the user is a contractor or an employee. Defaults to false. |
is_active |
boolean | optional | Whether the user is active or archived. Defaults to true. |
saml_exempt |
boolean | optional | Whether the user is exempt from required single sign-on (SSO), signing in with their email, password, and multi-factor authentication instead. Defaults to false. Can only be set by an Administrator on an account that requires SSO with exemptions enabled. |
weekly_capacity |
integer | optional | The number of hours per week this person is available to work in seconds. Defaults to 126000 seconds (35 hours). |
default_hourly_rate |
decimal | optional | The billable rate to use for this user when they are added to a project. Defaults to 0. |
cost_rate |
decimal | optional | The cost rate to use for this user when calculating a project’s costs vs billable amount. Defaults to 0. |
roles |
array of strings | optional | Descriptive names of the business roles assigned to this person. They can be used for filtering reports, and have no effect in their permissions in Harvest. |
access_roles |
array of strings | optional | Access role(s) that determine the user’s permissions in Harvest. Possible values: administrator, manager or member. Users with the manager role can additionally be granted one or more of these roles: project_creator, billable_rates_manager, managed_projects_invoice_drafter, managed_projects_invoice_manager, client_and_task_manager, time_and_expenses_manager, estimates_manager. On accounts using the newer permissions model, the possible values are administrator, executive_manager, people_admin, accounting, project_manager or member, and you can send the name of one of the account’s custom profiles instead. |
permissions_profile |
string | optional | The profile to put this person on: an access role or one of the account’s custom profiles. Takes a single name, and cannot be combined with access_roles in the same request. |
Access Roles
To set permissions for a user, use the access_roles parameter. A user must be one of the following: member, manager, or administrator.
- If no
access_roleparameter is sent, a user defaults to ‘member’. - If a user is a
managerthey can have other access roles set for more specific permissions in Harvest. - The role of
people_manageris determined by whether the user has teammates assigned to them, which can be added through the teammates api. If you downgrade a People Manager’s access role to Member, they will no longer be a People Manager and their assigned teammates will be removed.
| Access Role Name | Description |
|---|---|
administrator |
For users who need the most control to manage your account. Administrators can see and do everything. |
manager |
For users who need more access to people and project reports. Managers can track time and expenses, and edit, approve, and run reports for all time and expenses tracked to selected projects and people. |
member |
For users who just need to track time and expenses. |
| Additional Manager Access Role Names | Description |
|---|---|
project_creator |
User can create projects, and edit projects that they manage. |
billable_rates_manager |
User can see billable rates and amounts for projects and people they manage. |
managed_projects_invoice_drafter |
User can create and edit draft invoices for projects they manage. |
managed_projects_invoice_manager |
User can send and fully manage all invoices for projects they manage (record payments, edit non-drafts, send reminders and thank-yous, delete, etc). |
client_and_task_manager |
User can create and edit all clients and tasks on the account. |
time_and_expenses_manager |
User can create and edit time and expenses for people and projects they manage. |
estimates_manager |
User can create and edit all estimates on the account. |
Learn more about team permissions
Custom profiles
Accounts on the newer permissions model can build custom profiles: a named set of permissions the account defines for itself. To put someone on one, send its name as the only value of access_roles:
{"access_roles":["Team Lead"]}
Profile names are matched ignoring case and surrounding whitespace. A name that matches neither an access role nor one of the account’s custom profiles returns a 422 Unprocessable Entity and nothing is changed; it is never ignored. If a custom profile has the same name as an access role, the request is rejected too — rename the profile so we can tell which one you mean. You cannot create or edit custom profiles through the API.
permissions_profile takes one name, and it is the same field the user object reports, so a sync can read it, compare it, and write it back:
GET /v2/users/3230547 -> { "permissions_profile": "Team Lead", ... }
PATCH /v2/users/3230547 <- {"permissions_profile":"Team Lead"} # no change
PATCH /v2/users/3230547 <- {"permissions_profile":"member"} # moves them to Member
Sending the profile someone is already on leaves their individually granted permissions untouched, so a sync can safely repeat the same payload every run. Moving them to a different profile replaces those permissions with the new profile’s.
Send permissions_profile or access_roles, never both in the same request — a request carrying both is rejected. access_roles remains fully supported and is the field to use on accounts still on the older permissions model, or to give a manager one of the additional manager access roles listed above, which permissions_profile cannot express.
One difference worth knowing if you use access_roles on an account with custom profiles: access_roles does not report a custom profile when you read a user. A custom profile is stored as an access role plus the extra permissions the profile adds, so access_roles returns the access role underneath it, and only permissions_profile names the profile itself. Two people can look identical in access_roles while being on different profiles:
{
"access_roles": ["project_manager"],
"permissions_profile": "Team Lead"
}
{
"access_roles": ["project_manager"],
"permissions_profile": "Project Manager"
}
Because access_roles is authoritative when you write it, sending the same access_roles back for the first person moves them onto the plain project_manager access role and drops the extra permissions Team Lead granted — the request looks like a no-op but is not. Use permissions_profile for read-modify-write syncs and this cannot happen.
Changing someone’s permissions can remove them as a project manager. Whenever the profile or access roles you set leave a person without access to projects — including member — they are removed as project manager from every project they manage. This applies to every account, not only ones using custom profiles.
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])" \
-X POST \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","first_name":"George","last_name":"Frank","access_roles":["manager","project_creator","time_and_expenses_manager"]}'
Example response:
{
"id": 3,
"first_name": "George",
"last_name": "Frank",
"email": "[email protected]",
"telephone": "",
"timezone": "Eastern Time (US & Canada)",
"has_access_to_all_future_projects": false,
"is_contractor": false,
"is_active": true,
"weekly_capacity":126000,
"default_hourly_rate": 0,
"cost_rate": 0,
"roles": [],
"access_roles": [
"manager",
"project_creator",
"time_and_expenses_manager"
],
"avatar_url": "https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/assets/profile_images/big_ben.png?1485372046",
"created_at": "2020-01-25T19:20:46Z",
"updated_at": "2020-01-25T19:20:57Z"
}Update a user
Updates the specific user by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns a user object and a 200 OK response code if the call succeeded.
PATCH /v2/users/{USER_ID}
| Parameter | Type | Description |
|---|---|---|
first_name |
string | The first name of the user. Can’t be updated if the user is inactive. |
last_name |
string | The last name of the user. Can’t be updated if the user is inactive. |
email |
string | The email address of the user. Can’t be updated if the user is inactive. |
timezone |
string | The user’s timezone. Defaults to the company’s timezone. See a list of supported time zones. |
has_access_to_all_future_projects |
boolean | Whether the user should be automatically added to future projects. |
is_contractor |
boolean | Whether the user is a contractor or an employee. |
is_active |
boolean | Whether the user is active or archived. |
saml_exempt |
boolean | Whether the user is exempt from required single sign-on (SSO), signing in with their email, password, and multi-factor authentication instead. Can only be changed by an Administrator on an account that requires SSO with exemptions enabled, and not for yourself or the account owner. |
weekly_capacity |
integer | The number of hours per week this person is available to work in seconds. |
roles |
array of strings | Descriptive names of the business roles assigned to this person. They can be used for filtering reports, and have no effect in their permissions in Harvest. |
access_roles |
array of strings | Access role(s) that determine the user’s permissions in Harvest. Possible values: administrator, manager or member. Users with the manager role can additionally be granted one or more of these roles: project_creator, billable_rates_manager, managed_projects_invoice_drafter, managed_projects_invoice_manager, client_and_task_manager, time_and_expenses_manager, estimates_manager. On accounts using the newer permissions model, the possible values are administrator, executive_manager, people_admin, accounting, project_manager or member, and you can send the name of one of the account’s custom profiles instead. |
permissions_profile |
string | The profile to put this person on: an access role or one of the account’s custom profiles. Takes a single name, and cannot be combined with access_roles in the same request. |
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users/3237198" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])" \
-X PATCH \
-H "Content-Type: application/json" \
-d '{"roles":["Product Team"], "access_roles":["manager", "time_and_expenses_manager", "billable_rates_manager"]}'
Example response:
{
"id": 3237198,
"first_name": "Gary",
"last_name": "Brookes",
"email": "[email protected]",
"telephone": "",
"timezone": "Eastern Time (US & Canada)",
"has_access_to_all_future_projects": true,
"is_contractor": false,
"is_active": true,
"weekly_capacity":126000,
"default_hourly_rate": 120,
"cost_rate": 50,
"roles": ["Product Team"],
"access_roles": [
"manager",
"time_and_expenses_manager",
"billable_rates_manager"
],
"avatar_url": "https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/assets/profile_images/big_ben.png?1485372046",
"created_at": "2018-01-01T19:20:46Z",
"updated_at": "2019-01-25T19:20:57Z"
}Archive a user
Archives a specific user by setting the value of is_active to false. To make a user active again, simply set is_active to true again. Returns the updated user object and a 200 OK response code if the call succeeded.
PATCH /v2/users/{USER_ID}
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users/3226125" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])" \
-X PATCH \
-H "Content-Type: application/json" \
-d '{"is_active":false}'
Example response:
{
"id": 3226125,
"first_name": "Rachel",
"last_name": "Halliday",
"email": "[email protected]",
"telephone": "",
"timezone": "Eastern Time (US & Canada)",
"has_access_to_all_future_projects": true,
"is_contractor": false,
"is_active": false,
"weekly_capacity":126000,
"default_hourly_rate": 120,
"cost_rate": 50,
"roles": ["Developer"],
"access_roles": ["member"],
"avatar_url": "https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/assets/profile_images/big_ben.png?1485372046",
"created_at": "2018-01-01T19:20:46Z",
"updated_at": "2019-01-25T19:20:57Z"
}Delete a user
Delete a user. Deleting a user is only possible if they have no time entries or expenses associated with them. Returns a 200 OK response code if the call succeeded.
DELETE /v2/users/{USER_ID}
Example requests:
Postman Collection
We have a collection of API requests in Postman that makes it easy to try this out. Click here to learn more!
curl "https://api.harvestapp.com/v2/users/3237198" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Harvest-Account-Id: $ACCOUNT_ID" \
-H "User-Agent: MyApp ([email protected])" \
-X DELETE