openapi: 3.0.3
info:
version: 1.0.0
title: When I Work API Documentation Accounts Payrolls API
description: 'The When I Work API is thorough, flexible, and restful. Its methods are logically grouped and follow standard conventions. Make a selection from the left to jump to the method group you would like to know more about.
When designing your integration, When I Work recommends leveraging our Webhooks subscriptions if you plan to regularly pull data to sync records in your data store. This may be preferable to using our API for tasks like staying up to date about shifts or time entries in your account. Frequent large API requests may run into rate limitations.
Find out more about Webhooks at our [Help Center](https://help.wheniwork.com/articles/webhooks-reference/) or contact our [Customer Care team](mailto:support@wheniwork.com) for assistance.
For more information about obtaining an API key, or general API questions, please refer to the [Help Center](https://help.wheniwork.com/articles/api-services-reference-guide/).
'
servers:
- url: https://api.wheniwork.com
description: Production
security:
- W-Token: []
tags:
- name: Payrolls
description: 'Payrolls allows you to select a pay period date range and hours worked within that range. Default range if not supplied is today + 3 days.
> Please note that payrolls cannot be created or deleted via the API
For more info about managing Payroll, visit the [Help Center](https://help.wheniwork.com/articles/close-and-export-payroll/).
'
paths:
/2/payrolls:
get:
summary: List Payrolls
description: Listing of payroll periods and totals within a specified date range for an account.
tags:
- Payrolls
parameters:
- name: start
in: query
description: Start date of search range (datetime formatted ISO8601)
schema:
type: date-time
default: now
- name: end
in: query
description: End date of search range (datetime formatted ISO8601)
schema:
type: date-time
default: now + 3 days
x-code-samples:
- lang: shell
source: 'curl -X Get https://api.wheniwork.com/2/payrolls
-H "W-Token: ilovemyboss"
'
responses:
'200':
description: Valid
content:
application/json:
schema:
type: object
properties:
payrolls:
type: array
items:
$ref: '#/components/schemas/Payroll'
/2/payrolls/{id}:
get:
summary: Get Payroll
description: Get an existing payroll period by ID
tags:
- Payrolls
parameters:
- name: id
in: path
description: The ID of the payroll period requested.
schema:
type: integer
required: true
- Payrollhours
x-code-samples:
- lang: shell
source: 'curl -X Get https://api.wheniwork.com/2/payrolls/{Id}
-H "W-Token: ilovemyboss"
'
responses:
'200':
description: Valid
content:
application/json:
schema:
type: object
properties:
payroll:
$ref: '#/components/schemas/Payroll'
payrollhours:
type: array
description: 'The final unchanging snapshot of hours for a closed out payroll. Broken out by type, split as needed when crossing pay periods.
**🔥WARNING🔥**
Only for a closed payroll (see is_closed) please use `hourstats` for a payroll that is currently open.
'
items:
$ref: '#/components/schemas/PayrollHours'
put:
summary: Update Payroll
description: Update a selected payroll. The PUT body can include fields from the Payroll Object.
tags:
- Payrolls
requestBody:
$ref: '#/components/requestBodies/PayrollRequest'
responses:
'200':
description: Valid
content:
application/json:
schema:
type: object
properties:
payroll:
$ref: '#/components/schemas/Payroll'
/2/payrolls/{id}/stats:
get:
summary: Get Payroll Statistics for current hours
description: Get the aggregate statistics for payroll period by ID
tags:
- Payrolls
parameters:
- name: id
in: path
description: The ID of the payroll period requested.
schema:
type: integer
required: true
- name: mapObjects
in: query
description: Force structured listings to use maps by ID and not arrays
required: false
schema:
type: boolean
x-code-samples:
- lang: shell
source: 'curl -X Get https://api.wheniwork.com/2/payrolls/{Id}/Stats
-H "W-Token: ilovemyboss"
'
responses:
'200':
description: Valid
content:
application/json:
schema:
type: object
properties:
payroll:
$ref: '#/components/schemas/Payroll'
/2/payrolls/notices:
get:
summary: List Notices
description: 'Get all attendance notices since the last time they were dismissed. Attendance notices can be generated by
absences, early/late clock ins/outs, no shows, etc.
'
tags:
- Payrolls
parameters:
- name: ignoreDismissedAt
in: query
schema:
type: boolean
description: 'Sometimes you may want to view notices that have already been dismissed. Set this parameter to `true` to view
all notices regardless of when they''ve been dismissed.
'
required: false
example: true
- name: rangeInDays
in: query
schema:
type: integer
description: 'Limit the range of the notices that will be returned. By default, the endpoint will pull in everything since
the last time the user dismissed notices. This parameter can help restrict the window further.
'
required: false
example: -7
responses:
'200':
description: Valid
content:
application/json:
schema:
type: object
properties:
absences:
type: array
description: Any absences that generated a notice.
items:
$ref: '#/components/schemas/Absence'
notices:
type: array
description: Attendance anomalies that may need to be reviewed.
items:
$ref: '#/components/schemas/Notice'
punches:
type: array
description: All punches associated with times that generate a notice.
items:
$ref: '#/components/schemas/Punch'
shifts:
type: array
description: Any shifts that were associated with absences or times that generated a notice.
items:
$ref: '#/components/schemas/Shift'
times:
type: array
description: Any times that generated a notice.
items:
$ref: '#/components/schemas/Time'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/V2Error'
example:
error: You do not have permission to do this.
code: 3005
components:
schemas:
ShiftScheduledBreak:
allOf:
- $ref: '#/components/schemas/BaseScheduledBreak'
- type: object
properties:
shift_id:
type: integer
example: 1234
description: The ID of the shift that the break applies to.
readOnly: true
start_time:
example: Mon, 08 May 2023 9:30:00 -0600
description: The start time of the break. Null if the break does not have a start time.
type: string
end_time:
example: Mon, 08 May 2023 10:00:00 -0600
description: The end time of the break. Null if the break does not have an end time. Calculated from the start time of the break and the length.
type: string
readOnly: true
Notice:
type: object
properties:
time_id:
type: integer
description: The ID of the time that generated the notice.
user_id:
type: integer
description: The ID of the user who the notice is for.
shift_id:
type: integer
description: 'The ID of the shift that generated the notice of is associated with the time or absence which generated the
notice.
'
title:
type: string
description: The title of the notice, matches the code.
enum:
- Wrong Location
- Forgot to Clock Out
- Not Scheduled
- Absent
- No Show
- Clocked In Early
- Clocked In Late
- Clocked Out Early
- Clocked Out Late
- Missed Clock In
code:
type: integer
description: 'The type of notice. Matches the title.
* `103` - Wrong Location
* `107` - Forgot to Clock Out
* `110` - Not Scheduled
* `121` - Absent
* `120` - No Show
* `131` - Clocked In Early
* `132` - Clocked In Late
* `133` - Clocked Out Early
* `134` - Clocked Out Late
* `135` - Missed Clock In
'
punch_id:
type: integer
description: The ID of the punch that generated the notice.
absence_id:
type: integer
description: The ID of the absence that generate the notice.
created_at:
type: string
format: date-time
description: 'The time the notice was created at. This depends on the kind of entity that generated the notice. For
example, this could be the `created_at` time of the punch, `start_time` of the time, `start_time` or
`end_time` of the shift, or the `created_at` time of the absence.
'
Absence:
type: object
required:
- userId
- shiftId
- shiftStartTime
- shiftEndTime
- locationId
- creatorId
properties:
id:
type: string
example: '1'
description: ID of the absence
readOnly: true
accountId:
type: string
example: '7'
description: Account ID of the absence
readOnly: true
userId:
type: string
example: '226'
description: User ID of the absence
shiftId:
type: string
example: '9'
description: Shift ID of the absence
shiftStartTime:
type: string
format: date-time
example: '2016-12-19T16:39:57-08:00'
description: Start time of the shift
shiftEndTime:
type: string
format: date-time
example: '2016-12-19T16:39:57-08:00'
description: End time of the shift
locationId:
type: string
example: '13'
description: Location ID of the absence
siteId:
type: string
example: '10'
description: Site ID of the absence
positionId:
type: string
example: '38'
description: Position ID of the absence
creatorId:
type: string
example: '226'
description: User ID of the creator of the absence
notes:
type: string
example: Absence note
description: Note of the absence
actions:
type: array
description: List of actions taken on a shift.
items:
$ref: '#/components/schemas/AbsenceActions'
readOnly: true
createdAt:
type: string
format: date-time
example: '2016-12-19T16:39:57-08:00'
description: Time the absence was created
readOnly: true
updatedBy:
type: integer
example: 226
description: User ID of the last updater of the absence
updatedAt:
type: string
format: date-time
example: '2016-12-19T16:39:57-08:00'
description: Time the absence was last updated
readOnly: true
isDeleted:
type: boolean
example: false
description: Whether the absence has been deleted
readOnly: true
Time:
type: object
properties:
id:
type: integer
readOnly: true
example: 10000
description: The time id
account_id:
type: integer
readOnly: true
example: 10000
description: The account id
user_id:
type: integer
example: 101
description: The user assigned to the time.
creator_id:
type: integer
readOnly: true
example: 100
description: The user that created the time.
position_id:
type: integer
example: 19483
description: Position the time belongs to. 0 if unassigned.
location_id:
type: integer
example: 1045
description: Location the time belongs to. 0 if unassigned.
site_id:
type: integer
example: 4351
description: Site the time belongs to. 0 if unassigned.
shift_id:
type: integer
example: 5451
description: A shift tied to this time. 0 if unassigned.
start_time:
type: string
format: date-time
example: Fri, 07 Mar 2016 08:30:00 -0600
description: The start time
end_time:
type: string
format: date-time
example: Fri, 07 Mar 2016 14:30:00 -0600
description: The end time
rounded_start_time:
type: string
format: date-time
example: Fri, 07 Mar 2016 08:30:00 -0600
description: The rounded start time. If rounding is not enabled this field will not be present.
rounded_end_time:
type: string
format: date-time
example: Fri, 07 Mar 2016 14:30:00 -0600
description: The rounded end time. If rounding is not enabled this field will not be present.
notes:
type: string
example: A time note
description: Notes for a time
length:
type: float
readOnly: true
example: 8
description: The length of the time in hours.
rounded_length:
type: float
readOnly: true
example: 8
description: The rounded length calculated from the rounded_start_time and rounded_end_time. If rounding is not enabled this field will not be present.
hourly_rate:
type: float
readOnly: true
example: 15
description: The base hourly rate for this time.
cash_tips:
type: string
format: decimal
nullable: true
description: 'Any cash tips reported for the shift.
Note: the tips feature is required to see and use this field.
'
example: '123.45'
alert_type:
type: integer
readOnly: true
example: 16
description: The type of alert for this time
is_approved:
type: boolean
example: false
description: If the time is approved
modified_by:
type: integer
readOnly: true
example: 18438
description: The user that modified the time
sync_id:
type: string
readOnly: true
example: ''
description: The quickbooks sync id
sync_hash:
type: string
readOnly: true
example: ''
description: The quickbooks sync hash
updated_at:
type: string
readOnly: true
format: date-time
example: Tue, 17 Mar 2020 14:48:43 -0700
description: When the time was updated
created_at:
type: string
readOnly: true
format: date-time
example: Tue, 17 Mar 2020 14:25:48 -0700
description: When the time was created
split_time:
type: string
readOnly: true
format: date-time
example: Fri, 07 Mar 2016 00:00:00 -0600
description: If the time crosses payroll periods, when to split it
is_alerted:
type: boolean
readOnly: true
example: false
description: If alert_type > 0
paid_break_note:
type: string
default: null
readOnly: true
example: I am a note entered for the shift break paid record
description: The note associated with the shift break paid record. The include_paid_break_note query param must be set to true for this to be returned.
BaseScheduledBreak:
type: object
required:
- length
- paid
properties:
id:
example: 1234
type: integer
description: ID of the break. Provide in the request when updating an existing break.
account_id:
example: 1234
type: integer
readOnly: true
length:
example: 1800
description: The length of the break (seconds).
type: integer
paid:
description: Whether the break is a paid rest break (true) or unpaid meal break (false)
type: boolean
sort:
type: integer
description: Breaks are sorted by start time if it is available. If no start time is provided, breaks are sorted by their position in the request. In a mixed list, breaks without a start time keep their original position, while breaks with a start time are sorted amongst themselves.
readOnly: true
created_at:
description: Date and time the break was created at.
type: string
readOnly: true
created_by:
description: The id of the user who created the break.
type: integer
readOnly: true
updated_at:
description: Date and time the break was last updated.
type: string
readOnly: true
updated_by:
description: The id of the user who last edited the break.
type: integer
readOnly: true
Payroll:
type: object
description: 'Payroll is a pay period (start and end) and a collection paid hours (worked or paid time off)
within that pay period.
'
properties:
id:
type: integer
readOnly: true
example: 100000
description: The payroll ID
account_id:
type: integer
example: 100000
description: The ID of the account that the payroll belongs to
creator_id:
type: integer
example: 1000000
description: The ID of the user that created the payroll (pay period)
start_date:
type: string
format: date-time
example: Sun, 16 May 2021 00:00:00 -0500
description: When the pay period for this payroll starts (RFC 2822)
end_date:
type: string
format: date-time
example: Sat, 29 May 2021 23:59:59 -0500
description: When the pay period for this payroll ends (RFC 2822)
offset:
type: string
format: time
example: 00:00:00
description: Time offset from midnight for when the pay period should start or end (hours:mins:seconds)
notes:
type: string
example: Holiday payroll run.
description: Notes about this pay period
deprecated: true
is_edited:
type: boolean
example: false
description: Has the payroll been edited after being generated
deprecated: true
is_closed:
type: boolean
example: false
description: 'If the payroll (pay period) is closed.
**Note**
An open pay period will build out live data from `hourstats`.
A closed pay period will have a snapshot of the data from the time of closing called `payrollhours`
'
closed_at:
type: string
format: date-time
example: Sun, 16 May 2021 00:00:00 -0500
description: When the payroll (pay period) was closed (RFC 2822)
deprecated: true
is_finalized:
type: boolean
example: false
description: A finalized pay period that has been reviewed and fully approved
deprecated: true
finalized_at:
type: string
format: date-time
example: Sun, 16 May 2021 00:00:00 -0500
description: When the payroll (pay period) was finalized (RFC 2822)
deprecated: true
nullable: true
created_at:
type: string
format: date-time
example: Mon, 03 May 2021 09:35:38 -0500
description: Time when the pay period was created (RFC 2822)
updated_at:
type: string
format: date-time
example: Thu, 10 Jun 2021 10:19:47 -0500
description: Time when the pay period was last updated (RFC 2822)
Punch:
type: object
properties:
id:
type: integer
description: The ID of the punch.
account_id:
type: integer
description: The ID of the account the punch is associated with.
location_id:
type: integer
description: The ID of the schedule that the punch is associated with.
alert_type:
type: integer
description: 'A bitmask representing any alerts that might apply to the punch.
'
method:
type: integer
description: A bitmask representing how the punch was created. See `method_name` for a human readable version.
method_name:
type: string
nullable: true
description: How the punch was created.
enum:
- Third Party App
- Mobile
- Computer
- Terminal
site_id:
type: integer
description: The ID of the site the punch is associated with.
type:
type: integer
description: A code representing whether the punch was an "In" (`1`) or "Out" (`2`) punch.
time_id:
type: integer
description: The ID of the time the punch is associated with.
user_id:
type: integer
description: The ID of the user who is punching in or out.
accuracy:
type: number
format: float
description: The radius of uncertainty for the punch coordinates in meters.
altitude:
type: number
format: float
description: The altitude of the punch in meters.
latitude:
type: number
format: float
description: The latitude coordinate of the punch.
longitude:
type: number
format: float
description: The longitude coordinate of the punch.
ip_address:
type: string
description: The IP address of the device used to create the punch.
notes:
type: string
description: Any notes associated with the punch.
Shift:
type: object
required:
- start_time
- end_time
- location_id
properties:
id:
type: integer
readOnly: true
example: 10000
account_id:
type: integer
example: 10000
user_id:
type: integer
example: 101
description: The user assigned to the shift. Set to `0` for an Open Shift.
location_id:
type: integer
example: 1045
description: Location the shift belongs to
position_id:
type: integer
example: 19483
site_id:
type: integer
example: 4351
start_time:
type: string
format: date-time
example: Mon, 08 May 2023 08:30:00 -0600
end_time:
type: string
format: date-time
example: Mon, 08 May 2023 14:30:00 -0600
break_time:
type: double
example: 0.5
description: Length of the unpaid breaks for the shift in hours.
breaks:
description: An array of breaks for the shift. When updating a shift, any existing breaks for the shift that are not included in the request will be deleted.
type: array
items:
$ref: '#/components/schemas/ShiftScheduledBreak'
color:
type: string
example: cc000
description: Assign color to shift
notes:
type: string
example: Shift test
description: Text notation for a Shift
alerted:
type: boolean
example: false
description: Is the shift Alert sent
linked_users:
type: array
items:
type: integer
default: null
description: Array of user IDs that can take this openshift. Null means all users are eligible.
shiftchain_key:
type: string
example: 1eizfwp
description: The ID to associate shifts in a repeating pattern
published:
type: boolean
example: false
description: Is the shift published
published_date:
type: string
format: date-time
example: Mon, 01 May 2023 08:30:00 -0600
notified_at:
type: string
format: date-time
example: Mon, 01 May 2023 08:32:00 -0600
instances:
type: integer
example: 3
default: null
created_at:
type: string
format: date-time
example: Mon, 24 Apr 2023 07:30:00 -0600
updated_at:
type: string
format: date-time
example: Wed, 26 Apr 2023 11:30:00 -0600
acknowledged:
type: boolean
example: 0
description: If enabled; When the user confirmed the shift
acknowledged_at:
type: string
format: date-time
example: Fri, 21 Apr 2023 13:30:00 -0600
description: If enabled; When the user confirmed the shift
creator_id:
type: integer
example: 101
description: The user that created the shift
is_open:
type: boolean
example: false
requires_openshift_approval:
description: Does this shift require OpenShift Approval
type: boolean
example: true
openshift_approval_request_id:
description: ID of the associated OpenShift Approval request
type: integer
example: 5232
readOnly: true
is_approved_without_time:
description: Used to indicate that a manager or supervisor has approved a missing time entry for this shift
type: boolean
example: false
readOnly: true
is_shared:
description: Is the shift a shared OpenShift
type: boolean
example: false
is_trimmed:
description: Is rounding active for shift
type: boolean
example: false
PayrollHours:
type: object
description: The paid time for users within a given payroll (broken out by type, split as needed when crossing pay periods)
properties:
id:
description: The unique ID of the payroll hours object.
type: integer
payroll_id:
description: The ID of the Payroll this object belongs to.
type: integer
type:
type: integer
description: "The type of time associated with the payroll hours\n * `1` - Regular Time\n * `2` - Over Time\n * `3` - Paid Time Off\n * `4` - Holiday\n * `5` - Double Time\n * `6` - Sick\n * `7` - Time Off (custom type, unpaid time-off not included)\n"
type_label:
description: The label for the type of time off if a timeoff type (Personal, Sick, Holiday)
type: string
readOnly: true
user_id:
description: The ID of the user who these hours belong to.
type: integer
position_id:
description: The ID of the position that is associated with these hours. Default 0 for none.
type: integer
hours:
description: The number hours.
type: number
format: float
rate:
description: The hourly rate paid for these hours.
type: number
format: float
total:
description: The total wages for these hours.
type: number
format: float
AbsenceActions:
type: object
required:
- actionType
- createdBy
- createdAt
properties:
actionType:
type: string
enum:
- timeoff
- drop
- swap
- moved-to-open
description: Type of action taken on the shift
createdBy:
type: string
description: The user ID of who created the action.
example: '221'
createdAt:
type: string
format: date-time
readOnly: true
shiftId:
type: string
description: Will be present if move to open action was taken.
example: '221'
requestId:
type: string
description: Will be present if a time-off action was taken.
example: '125'
swapId:
type: string
description: Will be present if a swap or drop action was taken.
example: '312'
V2Error:
type: object
required:
- error
properties:
error:
type: string
description: A description of the specific error
code:
oneOf:
- type: integer
- type: string
description: The API error code
requestBodies:
PayrollRequest:
content:
application/json:
schema:
$ref: '#/components/schemas/Payroll'
description: The payroll data
securitySchemes:
W-Token:
type: http
scheme: bearer
bearerFormat: JSON Web Token
description: "Authentication with When I Work is based on a token model using [JSON Web Tokens](https://jwt.io/). First, you authenticate using a private developer key and the username and password of a When I Work user. Your developer key can be used like the following in the headers.\n```\ncurl -X POST \\\n https://api.login.wheniwork.com/login \\\n -H 'W-Key: <INSERT_DEVELOPER_KEY_HERE>' \\\n -H 'content-type: application/json' \\\n -d '{\"email\":\"<INSERT_USERNAME_HERE>\",\"password\":\"<INSERT_PASSWORD_HERE>\"}'\n```\n\nAuthenticating returns back a person object containing a token that is used to authenticate all future requests. You can now use this token to fetch all the users tied to your person. The token may be included in the headers, as a cookie, or in the query string using the key ‘W-Token’ or ‘Authorization’. If the authenticated user belongs to more than one Workplace you will need to get the User listing to obtain the user-id value\n```\ncurl -X GET \\\n 'https://api.wheniwork.com/2/login?show_pending=true' \\\n -H 'Host: api.wheniwork.com' \\\n -H 'Authorization: Bearer <INSERT_TOKEN_HERE>'\n```\n\nThe response will also
# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/when-i-work/refs/heads/main/openapi/when-i-work-payrolls-api-openapi.yml