Hubstaff Clients, Invoices, and Payments API
Manage the clients projects are billed to, list client invoices, and list team payments (payroll) generated from tracked time.
Manage the clients projects are billed to, list client invoices, and list team payments (payroll) generated from tracked time.
openapi: 3.0.3
info:
title: Hubstaff API
description: 'The Hubstaff API v2 provides programmatic read and write access to Hubstaff''s time tracking,
timesheet, workforce management, and project management data - organizations, members, teams, projects,
tasks, clients, activities (10-minute tracked time blocks with activity percentages), daily activity
aggregates, time entries, timesheets and approvals, time off requests/policies/balances, attendance
schedules and shifts, screenshots, app and URL usage, invoices, team payments, and webhooks.
Authentication uses OpenID Connect / OAuth 2.0 through Hubstaff Account (https://account.hubstaff.com).
For server-side scripts, create a personal access token at https://developer.hubstaff.com/personal_access_tokens
- the PAT acts as an OAuth refresh token (90-day expiry) that you exchange for short-lived access
tokens at https://account.hubstaff.com/access_tokens. Send the access token as a Bearer token on every
request.
Rate limit: authenticated users are allowed 1,000 requests per hour per application; individual requests
time out after 30 seconds. All requests must use HTTPS. Collection endpoints use cursor pagination
via page_start_id and page_limit. This document is a curated OpenAPI 3.0 rendering of the live Swagger
2.0 definition published at https://api.hubstaff.com/v2/docs, covering the primary resource areas;
consult the live definition for the complete surface (insights, job sites, budgets, overtime policies,
integrations, and more).'
version: '2.0'
contact:
name: Hubstaff Developer Portal
url: https://developer.hubstaff.com/
termsOfService: https://hubstaff.com/terms
externalDocs:
description: Hubstaff API v2 reference (interactive)
url: https://developer.hubstaff.com/docs/hubstaff_v2
servers:
- url: https://api.hubstaff.com
description: Hubstaff production API (paths include the /v2 prefix)
security:
- oauth2:
- hubstaff:read
- personalAccessToken: []
tags:
- name: Organizations
description: Organizations the authenticated user belongs to, plus seat usage.
- name: Members
description: Organization membership - list, add, and update members and their pay/bill rates.
- name: Invites
description: Invite users to an organization.
- name: Teams
description: Teams within an organization and their membership.
- name: Users
description: The authenticated user and user profiles.
- name: Activities
description: Tracked time as 10-minute activity blocks and daily aggregates, with keyboard/mouse activity
percentages.
- name: Time Entries
description: Create time entries for a user (manual time via the API).
- name: Timesheets
description: Timesheet approval records - list and update status (open, submitted, approved, denied).
- name: Time Edit Logs
description: Audit trail of manual time edits.
- name: Projects
description: Projects within an organization, including budgets and project members.
- name: Tasks
description: Tasks (to-dos) within projects and organizations.
- name: Clients
description: Clients that projects are billed to.
- name: Client Invoices
description: Invoices issued to clients.
- name: Team Payments
description: Payments made to team members (payroll).
- name: Time Off
description: Time off requests, policies, and balances.
- name: Attendance
description: Expected work shifts (schedules), actual clock-in/clock-out shifts, and holidays.
- name: Screenshots
description: Screenshots captured while tracking time.
- name: App & URL Tracking
description: Application and URL usage captured while tracking, plus tracking settings.
- name: Webhooks
description: Webhook subscriptions delivering real-time event notifications (timer.start, timer.stop,
task.create, shift.late, etc.).
paths:
/v2/organizations:
get:
operationId: getV2Organizations
tags:
- Organizations
summary: List organizations
description: Returns a collection of organizations the authenticated user is an active member of.
parameters:
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
responses:
'200':
description: A list of organizations
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'429':
description: Rate limit exceeded
post:
operationId: postV2Organizations
tags:
- Organizations
summary: Create organization
description: 'Creates a new organization.
Returns the created organization.'
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Request payload. See the live Hubstaff API reference (https://api.hubstaff.com/v2/docs)
for the full schema.
responses:
'200':
description: An organization
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}:
get:
operationId: getV2OrganizationsOrganizationId
tags:
- Organizations
summary: Get organization
description: Returns the organization with the given ID.
parameters:
- name: organization_id
in: path
description: Organization ID
required: true
schema:
type: integer
format: int32
responses:
'200':
description: An organization
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/seats:
get:
operationId: getV2OrganizationsOrganizationIdSeats
tags:
- Organizations
summary: Get organization seats
description: "Returns billing seat counters for the specified organization.\n\n- Paid seats are\
\ the total number of seats you are currently paying for.\n- Occupied is the total number of seats\
\ that are currently filled.\n- Open seats will be filled automatically when new members are added.\n\
\ Any open seats will be removed automatically when a new billing cycle starts,\n bringing down\
\ the number of paid seats to match the number of seats occupied."
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
responses:
'200':
description: Organization seats counters
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/members:
get:
operationId: getV2OrganizationsOrganizationIdMembers
tags:
- Members
summary: List organization members
description: "Returns a collection of members for the given organization.\n\nResults can be filtered\
\ by search, user IDs, membership role, and date range.\n\n*trackable* - Whether the user can\
\ track time. This is one of 3 values\n- *false* -- meaning tracking has been explicitly disabled\
\ for this user regardless of their role\n- *true* -- meaning they are allowed to track time\n\
- *viewer* -- meaning they are allowed to track time, however as they are only a project viewer\
\ (or no\n memberships) they implicitly can not track on any project\n\n*membership_role* - The\
\ basic role in this organization\n- *owner* - An owner of the organization. This member can\
\ do anything within the organization.\n- *manager* - An manager of the organization. This member\
\ can do anything within the organization\n except things to do with money. (payroll, invoicing,\
\ account billing)\n- *user* - (By project). A member of the organization where permissions are\
\ defined by their project memberships\n\n*effective_role* - represents an effective role that\
\ combines a member's organization role and their project roles\n- *organization_owner* - The\
\ member is an organization owner\n- *organization_manager* - The member is an organization manager\n\
- *project_manager* - The member is an organization user and a manager on all projects and teams\n\
- *project_user* - The member is an organization user and a user on all projects and teams\n-\
\ *project_viewer* - The member is an organization user and a viewer on all projects and teams\n\
- *by_project* - The member is an organization user and has mixed roles on their projects and\
\ team memberships (advanced in the web UI)\n- *unassigned* - The member has no assigned role\
\ and no project memberships (No role in the web UI)\n\n*profile* - The profile information for\
\ the user. Only organization owners and managers may see this information.\n- *custom_fields*\
\ - The custom fields, defined for organization, in format of \"key\": \"value\". The meaning\n\
\ of keys is defined in organization.member_profile_fields.\n\n**Filtering by dates:**\n\nYou\
\ can filter members by when they were added to the organization using the `created_at` parameter:\n\
- Use `created_at[start]` to get members added on or after a specific date\n- Use `created_at[stop]`\
\ to get members added before a specific date\n- Use both to get members added within a date range\n\
\nYou can also filter by when membership was last updated using the `updated_at` parameter:\n\
- Use `updated_at[start]` to get members updated on or after a specific date\n- Use `updated_at[stop]`\
\ to get members updated before a specific date\n- Use both to get members updated within a date\
\ range"
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
- name: search[email]
in: query
description: An email to search for members
schema:
type: string
- name: search[name]
in: query
description: A name to search for members
schema:
type: string
- name: include_removed
in: query
description: Include members that were removed from the organization
schema:
type: boolean
default: false
- name: include_profile
in: query
description: Include member profile information
schema:
type: boolean
default: false
- name: include_projects
in: query
description: Include project memberships for this member
schema:
type: boolean
default: false
- name: project_statuses
in: query
description: Filter projects by status when include_projects=true
schema:
type: array
items:
type: string
enum:
- active
- archived
- deleted
- name: include_limits
in: query
description: Include member limits information
schema:
type: boolean
default: false
- name: membership_roles
in: query
description: Search by membership role
schema:
type: array
items:
type: string
enum:
- owner
- manager
- user
- unassigned
- name: created_at[start]
in: query
description: Start date for created_at filter (inclusive)
schema:
type: string
format: date-time
- name: created_at[stop]
in: query
description: End date for created_at filter (exclusive)
schema:
type: string
format: date-time
- name: updated_at[start]
in: query
description: Start date for updated_at filter (inclusive)
schema:
type: string
format: date-time
- name: updated_at[stop]
in: query
description: End date for updated_at filter (exclusive)
schema:
type: string
format: date-time
- name: user_ids
in: query
description: List of user IDs
schema:
type: array
items:
type: integer
format: int32
- name: include
in: query
description: Specify related data to side load.
schema:
type: array
items:
type: string
enum:
- users
- projects
responses:
'200':
description: A list of members
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
post:
operationId: postV2OrganizationsOrganizationIdMembers
tags:
- Members
summary: Create organization member
description: 'Creates a new user and adds them to the organization as a member.
Returns the created member.
Available roles:
- organization_manager - Organization manager
- project_manager - Project manager
- project_user - Project user
- project_viewer - Project viewer
Available pay periods:
- none - Disables automatic payments
- weekly - Pay users weekly
- twice_per_month - Pay users twice a month
- biweekly - Pay users bi-weekly
- monthly - Pay users monthly'
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Request payload. See the live Hubstaff API reference (https://api.hubstaff.com/v2/docs)
for the full schema.
responses:
'201':
description: A member
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/update_members:
put:
operationId: putV2OrganizationsOrganizationIdUpdateMembers
tags:
- Members
summary: Update organization members
description: 'Updates organization members.
Returns {success: true} on success.
Only pass in the members you want to change.
Available roles:
- user - Member role determined by project membership
- manager - Organization manager
- owner - Organization owner
- remove - Removes user from organization (and all projects/teams)
Limits: Specify full limits config. Missing limits will be removed. Empty "limits" removes all
limits.
Projects: Specify project memberships to change. Available project roles: viewer, user, manager,
remove.
Metadata: Only specify keys to change. Non-existent keys are created. Use null to remove a key.
Key requirements:
- 2-30 characters
- Lowercase letters, numbers, and underscores only
Value requirements:
- Valid UTF-8 string
- Maximum 200 characters
Batch size: Up to 150 members per request. Larger requests are rejected with HTTP 400 and code
"too_many_members".'
parameters:
- name: organization_id
in: path
description: Organization ID
required: true
schema:
type: integer
format: int32
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Request payload. See the live Hubstaff API reference (https://api.hubstaff.com/v2/docs)
for the full schema.
responses:
'200':
description: Updated successfully
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/invites:
get:
operationId: getV2OrganizationsOrganizationIdInvites
tags:
- Invites
summary: List organization invites
description: 'Returns a collection of invites for the given organization.
Results can be filtered by email and status.'
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
- name: email
in: query
description: An email to search for a pending invitation by
schema:
type: string
- name: status
in: query
description: Filter invites by status
schema:
type: string
enum:
- all
- pending
- accepted
- expired
default: pending
- name: include
in: query
description: Specify related data to side load.
schema:
type: array
items:
type: string
enum:
- users
- projects
responses:
'200':
description: A list of invites
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
post:
operationId: postV2OrganizationsOrganizationIdInvites
tags:
- Invites
summary: Create invite
description: 'Creates a new invite.
Returns the created invite.
Note: If there is an account for the email in Hubstaff, the invite will be auto accepted.
Note: There is a rate limit on how many invites you may create.
Available roles:
- organization_manager - Invited as an organization manager
- project_manager - Invited as a project manager
- project_user - Invited as a project user
- project_viewer - Invited as a project viewer
If no project_ids are set, any project_* role will default to project_viewer (no projects assigned).'
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Request payload. See the live Hubstaff API reference (https://api.hubstaff.com/v2/docs)
for the full schema.
responses:
'201':
description: An invite
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/teams:
get:
operationId: getV2OrganizationsOrganizationIdTeams
tags:
- Teams
summary: List organization teams
description: Returns a collection of teams for the given organization.
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
responses:
'200':
description: A list of teams
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
post:
operationId: postV2OrganizationsOrganizationIdTeams
tags:
- Teams
summary: Create team
description: 'Creates a new team.
Returns the created team.
Only name is required. Members can optionally be added with roles: viewer, user, or manager.
Note: When a member lead is set to true, the role is forced to manager.'
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Request payload. See the live Hubstaff API reference (https://api.hubstaff.com/v2/docs)
for the full schema.
responses:
'201':
description: A team
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/teams/{team_id}:
get:
operationId: getV2TeamsTeamId
tags:
- Teams
summary: Get team
description: Returns the team with the given ID.
parameters:
- name: team_id
in: path
description: Team ID
required: true
schema:
type: integer
format: int32
responses:
'200':
description: A team
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/teams/{team_id}/members:
get:
operationId: getV2TeamsTeamIdMembers
tags:
- Members
summary: List team members
description: 'Returns a collection of members for the given team.
Membership roles:
- manager - Can track time, view all data, change settings, and manage membership
- user - Can track time and view only their own data
- viewer - Can view reports but cannot make changes'
parameters:
- name: team_id
in: path
description: Team ID
required: true
schema:
type: integer
format: int32
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
- name: include
in: query
description: Specify related data to side load.
schema:
type: array
items:
type: string
enum:
- users
responses:
'200':
description: A list of members
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/users/me:
get:
operationId: getV2UsersMe
tags:
- Users
summary: Get current user
description: Returns the authenticated user.
responses:
'200':
description: A user
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'429':
description: Rate limit exceeded
/v2/users/{user_id}:
get:
operationId: getV2UsersUserId
tags:
- Users
summary: Get user
description: Returns the user with the given ID.
parameters:
- name: user_id
in: path
description: User ID
required: true
schema:
type: integer
format: int32
responses:
'200':
description: A user
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/activities:
get:
operationId: getV2OrganizationsOrganizationIdActivities
tags:
- Activities
summary: List organization activities
description: 'Returns a collection of activities (10-minute time blocks) for the given organization.
Results can be filtered by user, task, project, and time range (time_slot[start], time_slot[stop]).
For aggregated daily data, use the daily_activities endpoint instead.
Note: Data may be delayed up to 20 minutes.
Note: Date range limit is 7 days. Earliest date is 6 months ago.'
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
- name: time_slot[start]
in: query
description: Start time (ISO 8601)
required: true
schema:
type: string
format: date-time
- name: time_slot[stop]
in: query
description: Stop time (ISO 8601, Exclusive)
required: true
schema:
type: string
format: date-time
- name: user_ids
in: query
description: List of user IDs
schema:
type: array
items:
type: integer
format: int32
- name: task_ids
in: query
description: List of task IDs
schema:
type: array
items:
type: integer
format: int32
- name: global_todo_ids
in: query
description: List of global todo IDs
schema:
type: array
items:
type: integer
format: int32
- name: project_ids
in: query
description: List of project IDs
schema:
type: array
items:
type: integer
format: int32
- name: include
in: query
description: Specify related data to side load.
schema:
type: array
items:
type: string
enum:
- users
- projects
- tasks
- name: time_zone
in: query
description: The time zone name for the activity
schema:
type: string
responses:
'200':
description: A list of activities
'400':
description: Invalid parameters
'401':
description: Unauthorized
'403':
description: API access is only for organizations on an active plan
'404':
description: Could not find record
'429':
description: Rate limit exceeded
/v2/organizations/{organization_id}/activities/daily:
get:
operationId: getV2OrganizationsOrganizationIdActivitiesDaily
tags:
- Activities
summary: List organization daily activities
description: 'Returns daily aggregated time tracking data for the given organization.
Results can be filtered by user_ids[], task_ids[], project_ids[], and date[start]/[stop]. Data
is aggregated by organization timezone date.
Note: Date range limit is 31 days. Earliest date is 3 years ago.'
parameters:
- name: organization_id
in: path
required: true
schema:
type: integer
format: int32
- name: page_start_id
in: query
description: The page start ID.
schema:
type: integer
format: int32
default: 0
- name: page_limit
in: query
description: The default page size
schema:
type: integer
format: int32
default: null
- name: date[start]
in: query
description: Start date (ISO 8601)
required: true
schema:
type: string
format: date
- name: date[stop]
in: query
description: Stop date (ISO 8601, Inclusive)
required: true
schema:
type: string
format: date
- name: user_ids
in: query
description: List of user IDs
schema:
type: array
items:
type: integer
format: int32
- name: task_ids
in: query
description: List of task IDs
schema:
type: array
items:
type: integer
format: int32
- name: project_ids
in: query
description: List of project IDs
schema:
type: array
items:
type: integer
format: int32
- name: include
in: query
description: Specify related data to side load.
schema:
type: array
items:
type: string
enum:
- users
- projects
- tasks
responses:
'200':
description: A list of daily activities
'400':
description: Inv
# --- truncated at 32 KB (110 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/hubstaff/refs/heads/main/openapi/hubstaff-openapi.yml