Read Payroll Period Data

The Payroll Period endpoints let you read the pay periods 7shifts has generated for a customer's company. Payroll periods define the start and end dates of each pay run, track when each location's period is closed for processing, and — when requested — surface whether the time punches inside a period have been reviewed and approved.

These endpoints are designed for payroll and Earned Wage Access (EWA) integrations that need to know when a pay period covers, whether it has been closed, and whether the underlying punch data is settled and safe to export.

📘

Payroll Period vs Time Punches

Payroll periods describe the calendar window for a pay run. The hours, wages, breaks, and tips that get paid out live on the underlying Time Punches for that window. Always pull time punches for the period's start/end dates — the payroll period record itself does not include hours or amounts.

Knowing when a period is ready to export

A payroll period has two layers of "doneness":

  • Per-location state (states[]) — each location closes its own pay period independently when the manager finishes reviewing and approving punches for that location.
  • Company-wide finalization (finalized) — true only when every location's state in the period is closed. This is the signal most payroll integrations poll on before exporting.
📘

Pair with webhooks

Instead of polling, subscribe to the payroll_period.closed webhook to be notified the moment a period (or a single location within a period) closes, then call Retrieve Payroll Period to fetch the current state before pulling punches.

List Payroll Periods

Retrieve a paginated list of payroll periods for a company, ordered with the most recent period first. Use this when discovering existing pay periods, when syncing on a schedule, or when you want richer status fields than the Retrieve endpoint returns.

Pass include_punches_status=true when you also need to know whether the punches inside each period have been approved by managers and reviewed by employees.

Request URL

curl --request GET \
  --url 'https://api.7shifts.com/v2/time_clocking/payroll_periods?company_id=12345&include_punches_status=true' \
  --header 'accept: application/json' \
  --header 'authorization: Bearer <ACCESS_TOKEN>'

Query parameters

ParameterTypeDescription
company_id requiredintThe 7shifts Company ID.
cursorstringCursor for the next or previous page of results. See Pagination.
limitintNumber of results per page.
include_punches_statusbooleanWhen true, populates all_punches_approved and employee_punch_approvals on each period. Defaults to false.

Response body

{
  "data": [
    {
      "id": 9876,
      "company_id": 12345,
      "start": "2024-01-15",
      "end": "2024-01-28",
      "closed": true,
      "finalized": true,
      "states": [
        {
          "id": 4567,
          "location_id": 222,
          "closed": true,
          "processed": "2024-01-30",
          "modified_by_user_id": 333,
          "closed_or_reopened_at": "2024-01-29T18:42:11+00:00"
        }
      ],
      "all_punches_approved": true,
      "employee_punch_approvals": "reviewed",
      "created": "2024-01-15T00:00:00+00:00",
      "modified": "2024-01-29T18:42:11+00:00"
    }
  ],
  "meta": {
    "cursor": {
      "next": "eyJpZCI6OTg3Nn0=",
      "prev": null
    }
  }
}

Here's an explanation of each field on a payroll period:

FieldTypeDescription
idintThe payroll period ID. Use this with the Retrieve endpoint.
company_idintThe 7shifts Company ID the period belongs to.
startdateFirst day of the pay period (YYYY-MM-DD).
enddateLast day of the pay period (YYYY-MM-DD).
closedbooltrue when at least one location's state in the period is closed.
finalizedbool / nulltrue only when all location states in the period are closed. This is the recommended "safe to export" signal for company-wide payroll pulls.
statesarrayOne entry per location, describing that location's close/process state (see below).
all_punches_approvedbool / nulltrue when every punch the requesting user can see for the period has been manager-approved. Only populated when include_punches_status=true.
employee_punch_approvalsenum / nullreviewed or pending, indicating whether employees have signed off on their punches. null if Compliance is not enabled. Only populated when include_punches_status=true.
createddatetimeWhen the period record was created, in UTC.
modifieddatetimeWhen the period was last modified, in UTC.

Each entry in states describes the close/process state for a single location:

FieldTypeDescription
idint / nullThe ID of the location's pay period state row.
location_idintThe 7shifts Location ID this state describes.
closedboolWhether this location's pay period is closed.
processeddate / nullThe date the period was last exported/processed for this location.
modified_by_user_idintUser ID that last modified the state. Negative values indicate a server process (e.g. automatic close).
closed_or_reopened_atdatetime / nullThe last time this location's state was closed or reopened, in UTC.

Retrieve Payroll Period

Fetch a single payroll period by its ID. Use this when you already know the period you care about — for example, after receiving a payroll_period.closed webhook, or when refreshing a period your integration has previously synchronized.

Request URL

curl --request GET \
  --url 'https://api.7shifts.com/v2/company/12345/payroll_periods/9876' \
  --header 'accept: application/json' \
  --header 'authorization: Bearer <ACCESS_TOKEN>'

Path parameters

ParameterTypeDescription
company_id requiredintThe 7shifts Company ID.
payroll_period_id requiredintThe ID of the payroll period.

Response body

{
  "object": "payroll_period",
  "data": {
    "id": 9876,
    "company_id": 12345,
    "closed": true,
    "start": "2024-01-15",
    "end": "2024-01-28",
    "states": [
      {
        "id": 4567,
        "location_id": 222,
        "closed": true,
        "processed": "2024-01-30",
        "modified_by_user_id": 333,
        "closed_or_reopened_at": "2024-01-29T18:42:11+00:00"
      }
    ]
  }
}

Here's an explanation of each field:

FieldTypeDescription
objectstringAlways payroll_period.
dataobjectThe payroll period payload (see below).
idintThe payroll period ID.
company_idintThe 7shifts Company ID the period belongs to.
startdateFirst day of the pay period (YYYY-MM-DD).
enddateLast day of the pay period (YYYY-MM-DD).
closedbooltrue when at least one location's state in the period is closed.
statesarrayPer-location close/process states. Same shape as the states array on the List endpoint (see above).
📘

Schema differences vs. List

The Retrieve endpoint wraps the payroll period in an object / data envelope and returns a focused set of fields. If you need finalized, all_punches_approved, employee_punch_approvals, created, or modified, use the List Payroll Periods endpoint with include_punches_status=true and filter the response client-side by id.

A typical payroll export flow

  1. On a schedule (or when you receive a payroll_period.closed webhook), call List Payroll Periods with include_punches_status=true.
  2. Identify periods where finalized is true and all_punches_approved is true — these are safe to export.
  3. For each such period, call List Time Punches filtered to the period's start and end dates to retrieve the actual hours and wages.
  4. Record the period's id and modified timestamp so you can detect re-opens — a manager can reopen a closed period to correct punches, after which modified (and the relevant location states[].closed_or_reopened_at) will advance.