When I Work Punch API

A punch is an event where a user clocks in or clocks out. Punches can be managed to restrict where an employee can clock in/out and from what devices. If a user forgets to clock out, they will be allowed to clock in after 9 hours from the end of their scheduled shift. If there is no scheduled shift, the user can clock in again after 18 hours from when they originally clocked in.

Documentation

Specifications

Schemas & Data

Other Resources

OpenAPI Specification

when-i-work-punch-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  version: 1.0.0
  title: When I Work API Documentation Accounts Punch 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: Punch
  description: 'A punch is an event where a user clocks in or clocks out. Punches can be managed to restrict where an employee can clock in/out and from what devices.


    If a user forgets to clock out, they will be allowed to clock in after 9 hours from the end of their scheduled shift. If there is no scheduled shift, the user can clock in again after 18 hours from when they originally clocked in.

    '
paths:
  /2/times/clockin:
    post:
      summary: Clock In
      description: Punch the current user or another user in. The punch creator's ID will also be recorded.
      tags:
      - Punch
      requestBody:
        $ref: '#/components/requestBodies/ClockInRequest'
      responses:
        '200':
          description: Valid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PunchResponse'
        '400':
          description: Bad request contains missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V2Error'
        '403':
          description: Forbidden access, account setting or permissions do not allow this action
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V2Error'
  /2/times/clockout:
    post:
      summary: Clock Out
      description: Punch the current user or another user out. The punch creator's ID will also be recorded.
      tags:
      - Punch
      requestBody:
        $ref: '#/components/requestBodies/ClockOutRequest'
      responses:
        '200':
          description: Valid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PunchResponse'
        '400':
          description: Bad request contains missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V2Error'
        '403':
          description: Forbidden access, account setting or permissions do not allow this action
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V2Error'
  /2/punch/state:
    get:
      summary: Punch State
      description: Gets a users punch state and allowed actions
      tags:
      - Punch
      parameters:
      - in: query
        description: User ID if looking up the punch state for another user, may allow additional actions
        name: userId
        required: false
        schema:
          type: integer
      - in: query
        description: Location ID (schedule) used to verify if the user can punch in at this location
        name: locationId
        required: false
        schema:
          type: integer
      - in: query
        description: Job site used to verify if the user can punch in at this site
        name: siteId
        required: false
        schema:
          type: integer
      - in: query
        description: Shift ID used to verify if the user can punch into this shift
        name: shiftId
        required: false
        schema:
          type: integer
      - in: query
        description: Type of device used to perform the punch
        name: deviceType
        required: false
        schema:
          type: string
          enum:
          - web
          - mobile
          - terminal
      - in: query
        description: Current latitude used to verify punch restrictions for strict location validation
        name: latitude
        required: false
        schema:
          type: number
      - in: query
        description: Current longitude used to verify punch restrictions for strict location validation
        name: longitude
        required: false
        schema:
          type: number
      - in: query
        description: Expand the location search area by a given confidence to the provided location
        name: confidence
        required: false
        schema:
          type: number
      responses:
        '200':
          description: The current punch state and allowed actions for the user
          content:
            application/json:
              schema:
                type: object
                properties:
                  canClockIn:
                    description: Can the user be clocked in
                    type: boolean
                    example: false
                  canClockOut:
                    description: Can the user be clocked out
                    type: boolean
                    example: false
                  canStartBreak:
                    description: Can the user start a break
                    type: boolean
                    example: false
                  canEndBreak:
                    description: Can the user end their break
                    type: boolean
                    example: true
                  needsBreakConfirmation:
                    description: True if the user is required to report on unused paid breaks
                    type: boolean
                    example: false
                  needsUnpaidBreakConfirmation:
                    description: True if the user is required to report on unused unpaid breaks
                    type: boolean
                    example: false
                  punchStartTime:
                    description: Time when the user punched in, date in ISO 8601 format (UTC timezone)
                    type: string
                    example: '2017-09-27T18:28:52'
                  punchTimeId:
                    description: The ID of the time object associated with the punch
                    type: integer
                    example: 1
                  errorCode:
                    description: 'Error code describing why punch in or punch out is not allowed

                      * `101` - Bad device location received

                      * `102` - Bad shift location received

                      * `103` - Out of range for shift location

                      * `104` - Not near the punch location

                      * `105` - Clock-in time too early

                      * `106` - No shift scheduled, or manual selection required (see: availableShifts)

                      '
                    type: integer
                    enum:
                    - 101
                    - 102
                    - 103
                    - 104
                    - 105
                    - 106
                  schedules:
                    example: 1
                    oneOf:
                    - schedule: null
                      type: integer
                      description: The schedule ID to punch in at or the schedule currently punched in at
                    - scheduled: null
                      type: string
                      description: URL used to load a listing of possible schedules
                  jobSites:
                    example: 1
                    oneOf:
                    - site: null
                      type: integer
                      description: The job site ID to punch in at or the job site currently punched in at
                    - sites: null
                      type: string
                      description: URL used to load a listing of possible job sites
                  positions:
                    example: 1
                    oneOf:
                    - position: null
                      type: integer
                      description: The position ID to punch in at or position currently punched in as
                    - positions: null
                      type: string
                      description: URL used to load a listing of possible positions
                  shift:
                    example: 1
                    description: The shift ID that should be used when punching in or the shift ID currently punched in as
                    type: integer
                  break:
                    description: The break object currently punched into if currently on a punched break
                    type: object
                    $ref: '#/components/schemas/PunchStateRootShiftBreak'
                  availableShifts:
                    description: A list of available shift IDs the user is allowed to punch in to
                    example:
                    - 4
                    - 6
                    - 7
                    type: array
                    items:
                      type: integer
                  recordingUnpaidBreaksAllowed:
                    description: True if the user is allowed to record unpaid breaks
                    type: boolean
                    example: true
                  recordingPaidBreaksAllowed:
                    description: True if the user is allowed to record paid breaks
                    type: boolean
                    example: true
                  scheduledBreaks:
                    type: array
                    description: A list of scheduled breaks if the clocked in time has a shift which has scheduled breaks. (Only provided when clocked in, there's a shift, and the shift has scheduled breaks)
                    items:
                      type: object
                      $ref: '#/components/schemas/PunchStateScheduledBreak'
                  unscheduledBreaks:
                    type: array
                    description: A list of any taken unscheduled breaks. (Only provided when clocked in and there are shift breaks for the time)
                    items:
                      type: object
                      $ref: '#/components/schemas/PunchStateNestedShiftBreak'
        '400':
          description: Bad request contains missing or invalid parameters
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    description: A list of validation errors
                    example:
                    - Invalid value for userID
                    - Missing required parameter deviceType
                    type: array
                    items:
                      type: string
        '403':
          description: Forbidden access, account setting or permissions do not allow this action
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    description: A list of validation errors
                    example:
                    - Web punch state not active on account
                    type: array
                    items:
                      type: string
        '404':
          description: Not found, requested resource could not be found
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    description: A list of validation errors
                    example:
                    - User not found
                    type: array
                    items:
                      type: string
components:
  schemas:
    PunchResponse:
      type: object
      properties:
        time:
          description: The Time object that the punch is associated with
          $ref: '#/components/schemas/Time'
        overtime_alert:
          description: Was an over-time alert triggered
          type: boolean
          example: false
        user:
          description: The User that has punched in
          $ref: '#/components/schemas/User'
        punches:
          description: 'Array of punches associated with the current Time

            * Punch in/out

            * Punch break start/stop

            '
          type: array
    PunchStateRootShiftBreak:
      allOf:
      - $ref: '#/components/schemas/PunchStateShiftBreakBase'
      - type: object
        properties:
          start:
            description: The break start time
            type: string
            format: date-time
            example: 2025-05-19T10:45:00-0400
          end:
            description: The break end time. Will always be an empty string; once the break has an end, it is no longer returned by this endpoint under the `break` key
            type: string
            format: date-time
            example: ''
          length:
            description: The break length from the database model once the break is complete, in minutes. Until the break is complete, this value remains zero. However, once the break is complete, the `break` object is not longer returned by this endpoint. Hence, break length should be calculated based on the `start` instead
            type: integer
            example: 0
    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.
    PunchStateShiftBreakBase:
      type: object
      properties:
        id:
          description: The shift break id
          type: integer
          example: 2
        account_id:
          description: The account id associated with the break
          type: integer
          example: 3
        time_id:
          description: The time id associated with the break
          type: integer
          example: 1
        type:
          description: The type of break (1=paid, 2=unpaid)
          type: integer
          example: 2
        creator_id:
          description: The id of the user who created the break
          type: integer
          example: 238
        auto_deducted:
          description: Whether the break was auto deducted (0 = false, 1 = true)
          type: integer
          example: 0
        edited_by:
          description: The id of the user who edited the break
          type: integer
          example: 238
        skipped:
          description: Whether the break was skipped (0 = false, 1 = true)
          type: integer
          example: 0
        created_at:
          description: Date and time the break was created at
          type: string
          format: date-time
          example: 2025-05-19T11:25:04-0400
        updated_at:
          description: Date and time the break was last updated
          type: string
          format: date-time
          example: 2025-05-19T11:25:04-0400
        scheduledbreaks_id:
          description: The scheduled break associated with this shift break, if it is a scheduled break. Otherwise `0`
          type: integer
          example: 0
    PunchStateNestedShiftBreak:
      allOf:
      - $ref: '#/components/schemas/PunchStateShiftBreakBase'
      - type: object
        properties:
          start:
            description: The break start time. Null if the break does not have an start time. Perhaps because it was added on Timesheets.
            type: string
            format: date-time
            nullable: true
            example: 2025-05-19T10:00:00-0400
          end:
            description: The break end time. Null if the break does not have an end time. Perhaps because it was added on Timesheets.
            type: string
            format: date-time
            nullable: true
            example: 2025-05-19T10:08:00-0400
          length:
            description: The length of the break if it's completed, in minutes. Length will be zero until the break has ended
            type: integer
            example: 6
    User:
      properties:
        account_id:
          description: ID of the primary account for this user.
          type: integer
        activated:
          description: Whether the manager has activated this user.
          type: boolean
        email:
          description: The email address of this user.
          format: email
          type: string
        employee_code:
          description: 'The user''s employee code. This code can be used to clock in instead of

            the user''s email address, or it can be used to help map users in When

            I Work to other services.

            '
          type: string
        first_name:
          description: The first name of this user.
          type: string
        hourly_rate:
          description: 'The base hourly rate for this user. The user can have additional wages

            based on the position they are working at the time. There is no currency

            attached, so customers are expected to input correct values for their

            currency or do their own conversion from USD.

            '
          format: float
          type: number
        hours_max:
          description: 'The max hours that this user prefers to work. A manager may still

            schedule the user beyond this value.

            '
          format: float
          type: number
        hours_preferred:
          description: The preferred number of hours for this user to work.
          format: float
          type: number
        id:
          description: Unique identifier for the user.
          type: integer
        is_deleted:
          description: Whether the user has been deleted.
          type: boolean
        is_hidden:
          description: Whether the user has been hidden from the scheduler.
          type: boolean
        is_payroll:
          description: 'Whether the user has access to payroll. (Only available for managers

            and supervisors.)

            '
          type: boolean
        is_private:
          description: 'Whether the user has privacy enabled, which will hide their contact

            details from other employees. Supervisors+ can not hide their

            email/phone from other employees.

            '
          type: boolean
        is_trusted:
          description: Whether the user can edit their own timesheet.
          type: boolean
        last_login:
          description: The date and time when this user last logged in.
          format: date-time
          type: string
        last_name:
          description: The last name of this user.
          type: string
        locations:
          description: An array of location IDs to be applied to this user.
          items:
            type: integer
          type: array
        login_id:
          description: Unique identifier for the login belonging to the user.
          type: integer
        notes:
          description: Notes about this user. Visible only to supervisors+.
          type: string
        phone_number:
          description: The phone number of this user.
          type: string
        positions:
          description: An array of position IDs to be assigned to this user.
          items:
            type: integer
          type: array
        role:
          description: The user's role.
          enum:
          - 1 = Admin
          - 2 = Manager
          - 3 = Employee (Default)
          - 4 = Lead (Unused)
          - 5 = Supervisor
          type: integer
        type:
          description: 'A bitwise flag representing additional wage options:

            1 = hourly employee

            2 = salaried employee

            4 = Exempt from overtime

            '
          type: integer
      type: object
    PunchStateScheduledBreak:
      allOf:
      - type: object
        properties:
          id:
            type: integer
            description: Scheduled Break Id
            example: 1
          account_id:
            type: integer
            description: Account Id associated with this break
            example: 3
          start_time:
            description: The start time of the break. Null if the break does not have a start time
            type: string
            example: '2025-05-19T14:30:00+00:00'
          end_time:
            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
            example: '2025-05-19T14:45:00+00:00'
          length:
            description: The length of the break (seconds)
            type: integer
            example: 900
          paid:
            description: Whether the break is a paid rest break (true) or unpaid meal break (false)
            type: boolean
            example: true
          created_by:
            description: The id of the user who created the break
            type: integer
            example: 201
          created_at:
            description: Date and time the break was created at
            type: string
            example: '2025-05-10T14:45:00+00:00'
          updated_by:
            description: The id of the user who last edited the break
            type: string
            example: '202'
          updated_at:
            description: Date and time the break was last updated
            type: string
            example: '2025-05-10T15:45:00+00:00'
          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
          shift_id:
            type: integer
            example: 1234
            description: The ID of the shift that the break applies to
            readOnly: true
          shift_break:
            type: object
            description: When not null, at least a start time was created for an associated shift break. Otherwise, no breaks have been taken for this scheduled break
            $ref: '#/components/schemas/PunchStateNestedShiftBreak'
    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:
    ClockOutRequest:
      description: Clock Out (Punch) request data
      content:
        application/json:
          schema:
            type: object
            properties:
              id:
                type: integer
                description: The ID of the user you are creating the clock-in for
                example: 14
              notes:
                type: string
                description: Optional notes that can be added to the punch that will show up on the timesheets
                example: Punching out late there was a delay in the shift change
                required: false
              coordinates:
                type: array
                description: The GPS coordinates of the clock-out. This is an optional parameter.
                example:
                - 44.983791
                - -93.2774416
                required: false
              altitude:
                type: number
                description: The altitude that the user is currently at in meters.
                example: 20
                required: false
              accuracy:
                type: number
                description: The accuracy in meters of the coordinates being sent.
                example: 20
                required: false
              terminal:
                type: boolean
                description: Is the user clocking out from a terminal (web or mobile/tablet terminal app)
                example: true
                required: false
                default: false
              cashTips:
                description: The amount of cash tips reported for the shift.
                type: string
                format: decimal
                example: '54.32'
    ClockInRequest:
      description: Clock In (Punch) request data
      content:
        application/json:
          schema:
            type: object
            properties:
              id:
                type: integer
                description: The ID of the user you are creating the clock-in for
                example: 14
              site_id:
                type: integer
                description: The ID of the job site to punch in at. This is an optional parameter.
                example: 1
                required: false
              position_id:
                type: integer
                description: The ID of the position the user is clocking in as. This is an optional parameter.
                example: 102
                required: false
              shift_id:
                type: integer
                description: The Shift ID for the shift to punch in for, 0 if punching into an unscheduled shift.
                example: 0
                required: false
              location_id:
                type: integer
                description: The Schedule ID for the schedule the user is punching in at. This is an optional parameter.
                example: 1
                required: false
              notes:
                type: string
                description: Optional notes that can be added to the punch that will show up on the timesheets.
                example: Punching in today, running a little late due to traffic problems
                required: false
              coordinates:
                type: array
                description: The GPS coordinates of the clock-in. This is an optional parameter.
                example:
                - 44.937422
                - -93.084009
                required: false
              altitude:
                type: number
                description: The altitude that the user is currently at in meters.
                example: 20
                required: false
              accuracy:
                type: number
                description: The accuracy in meters of the coordinates being sent.
                example: 20
                required: false
              terminal:
                type: boolean
                description: Is the user clocking in from a terminal (web or mobile/tablet terminal app)
                example: true
                required: false
                default: false
  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

# --- truncated at 32 KB (33 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/when-i-work/refs/heads/main/openapi/when-i-work-punch-api-openapi.yml