Learn how to integrate the Square Labor API into your application to record team member work hours.
Labor API

Build with the Labor API

Use the Labor API to create shift records that capture the start, breaks, and end of a team member's shift and the hourly rate for the shift.

This topic provides step-by-step guidance for integrating with the Labor API. For information about how the Labor API works, see How It Works.

To use the Labor API, the following must be true:

  • You have a Square account. Create a Square account in minutes if you do not already have one.

  • You have added team members to at least one location in the Seller Dashboard.

This topic also makes the following assumptions:

  • The Seller Dashboard for your account has at least one active team member.

  • You have assigned at least one wage type per team member in the Seller Dashboard.

Did you know?

You can assign wage types to a team member by using the Team API.

To use the steps in this topic, you need:

  • You need a valid access token. You should test with Sandbox credentials whenever possible. For more information, see Access Tokens and Other Square Credentials.

  • An active location ID. Copy a developer account location ID from the Locations page of your Square application in the Developer Dashboard or set the Developer Dashboard to Sandbox mode and then copy a Sandbox location ID.

This topic walks you through the process of starting and ending a team member shift:

Start a shift

  1. Configure the Labor API with a valid access token and location ID.

  2. Get a team member ID.

  3. Get the wage type for the job to be done on the shift.

  4. Check for a previous open shift record for the team member.

  5. Create and send a CreateShift request to create a new shift record and start a shift.

End a shift

  1. Search for the open shift record.

  2. Update the record with an end time to end it.

Before you can use the Labor API, you must set the location ID where the API is used and then get an access token to authorize the API to access Shift and TeamMember resources for that location.

Follow these steps to get the access token and location ID used in this walkthrough.

  1. Sign in to the Developer Dashboard and open your application. If you do not have a Square account, see Get Started to learn how to create an account and an application.

  2. Get your Sandbox access token:

    1. At the top of the page, in the Sandbox and Production toggle, choose Sandbox.

    2. On the Credentials page, under Sandbox Access Token, choose Show and then copy the token. All Square API requests require an access token for authorization. This personal access token grants full access to the Sandbox resources in your account.

      Important

      The Sandbox access token is a secure secret. Do not share it with anyone.

  3. Get your location ID:

    1. In the left pane, choose Locations.

    2. On the Locations page, keep Default Test Account selected and copy a location ID.

An animation showing how to get the Sandbox access token and location ID in the Developer Dashboard.

Note

To retrieve location IDs programmatically, call ListLocations.

If you are using an OAuth access token, request EMPLOYEES_READ and TIMECARDS_WRITE permissions.

Use the Team API to retrieve a list of active team members for a location and select a team member from the list. Use the following logic to get active team members for a location:

Search Team Members
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
curl https://connect.squareup.com/v2/team-members/search \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "filter": {
        "location_ids": [
          "0G5P3VGACMMQZ"
        ],
        "status": "ACTIVE"
      }
    },
    "limit": 3
  }'

The response carries an array of TeamMember objects representing the active team members for the specified location:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
{
  "team_members": [
    {
      "id": "-3oZQKPKVk6gUXU_V5Qa",
      "reference_id": "12345678",
      "is_owner": false,
      "status": "ACTIVE",
      "given_name": "Johnny",
      "family_name": "Cash",
      "email_address": "[email protected]",
      "created_at": "2019-07-10T17:26:48Z",
      "updated_at": "2020-04-28T21:49:28.957Z",
      "assigned_locations": {
        "assignment_type": "ALL_CURRENT_AND_FUTURE_LOCATIONS"
      }
    },
    {
      "id": "1AVJj0DjkzbmbJw5r4KK",
      "reference_id": "abcded",
      "is_owner": false,
      "status": "ACTIVE",
      "given_name": "Lombard",
      "family_name": "Smith",
      "phone_number": "+14155552671",
      "created_at": "2020-03-24T18:14:01.127Z",
      "updated_at": "2020-06-09T17:38:05.423Z",
      "assigned_locations": {
        "assignment_type": "ALL_CURRENT_AND_FUTURE_LOCATIONS"
      }
    },
    {
      "id": "2JCmiJol_KKFs9z2Evim",
      "is_owner": false,
      "status": "ACTIVE",
      "given_name": "Monica",
      "family_name": "Sway",
      "created_at": "2020-03-24T01:09:25.010Z",
      "updated_at": "2020-03-24T01:09:25.010Z",
      "assigned_locations": {
        "assignment_type": "ALL_CURRENT_AND_FUTURE_LOCATIONS"
      }
    }
  ],
  "cursor": "N:9UglUjOXQ13-hMFypCft"
}

Use the Team API to get the wage settings of the team member.

A TeamMember can have multiple wage types and job titles. To assign the correct wage to a shift, get all the WageSetting objects for the team member and find the wage type for the job that the team member is performing in this shift.

Did you know?

The first WageSetting in the set of returned items is the default team member wage. Use the default wage unless you are choosing a WageSetting based on a matching job title.

Retrieve Wage Setting
  • 1
  • 2
  • 3
  • 4
curl https://connect.squareup.com/v2/team-members/1yJlHapkseYnNPETIU1B/wage-setting \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json'

The response carries an array of the WageSetting objects associated with a team member ID:

A new shift record cannot be created for a team member until the previous shift record is closed.

The following shift search request asks for a set of shift records with the following instructions:

  • Shifts for one specified team member.

  • At a specified location.

  • With shifts whose status is OPEN.

This filter always returns zero or one Shift record. A team member can have a maximum of one open shift.

Search Shifts
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
curl https://connect.squareup.com/v2/labor/shifts/search \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "filter": {
        "status": "OPEN",
        "team_member_ids": [
          "A_TEAM_MEMBER_ID"
        ]
      }
    }
  }'

The response to the shift search request is an empty object if the team member does not have an OPEN shift:

To create a new shift, use the location ID, team member ID, and WageSetting hourly rate to set values in a new ShiftWage. The shift start_at field can be set to local time or GMT. If you use GMT, the Square Labor endpoint calculates the local time based on the location of the shift.

Use the following logic to create the shift.

Create Shift
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
curl https://connect.squareup.com/v2/labor/shifts \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "idempotency_key": "UUID",
    "shift": {
      "team_member_id": "A_TEAM_MEMBER_ID",
      "location_id": "YOUR_LOCATION_ID",
      "start_at": "2019-02-05T12:00:00Z",
      "wage": {
        "title": "Photographer",
        "hourly_rate": {
          "amount": 4500,
          "currency": "USD"
        }
      }
    }
  }'

Important

You must include a wage object with a pay rate so that the labor cost is recorded. If you do not include a wage, there is no pay amount associated with the shift record.

The job title and compensation rate that may be associated with the team member is not used as a default value for the wage in the created shift.

Get the open shift for the team member by using the example in Step 3.

The response to the shift search request is an array of Shift objects that match the filter criteria:

To close a shift, an end_at field is added to the open shift. If the shift has an open break, it must be closed before the shift can be closed.

Update Shift
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
curl https://connect.squareup.com/v2/labor/shifts/{id} \
  -X PUT \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "shift": {
      "id": "3DBHNF9E8CG27",
      "team_member_id": "aq8XS-F0-VA0UrgH6h3w",
      "location_id": "YOUR_LOCATION_ID",
      "timezone": "America/Los_Angeles",
      "start_at": "2018-10-16T04:00:00-07:00",
      "end_at": "2018-10-16T12:00:00Z",
      "wage": {
        "title": "Photographer",
        "hourly_rate": {
          "amount": 4500,
          "currency": "USD"
        }
      },
      "status": "OPEN",
      "version": 3,
      "created_at": "2019-02-21T20:22:10Z",
      "updated_at": "2019-02-21T20:24:34Z"
    }
  }'

Before you POST the updated shift, look for an array of Break objects that are present if the employee took any breaks during the shift. If you find these object, confirm that they contain end_at properties and that those properties are not null.

The response is an updated version of the shift object with a CLOSED status and an incremented version number:

We've made improvements to our docs.
Prefer the old format?