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