Product that suits modern B2B Tech companies

Book Demo
B
Book demo call-to-action illustration
BACK
B

7shifts API authentication, versioning and data access

Platform APIs
October 10, 2024
Summarise the blog with AI
Open in ChatGPT
Ask questions about this page
Open in Claude
Ask questions about this page

Key takeaways

Check these requirements before relying on an authenticated connection for production retrieval:

  • Company access tokens serve own-company and limited-company integrations, while partner OAuth serves distributed products whose customers grant access.
  • Partner OAuth requests require both bearer authorization and company context, not an access token alone.
  • Explicit request-version selection keeps your implementation from relying on a credential default that may differ from the published reference.
  • Complete list retrieval requires cursor-chain completion, not merely a successful first response.
  • Valid credentials do not establish plan and feature entitlement to every requested resource.
  • A complete initial read still needs ongoing reconciliation because schedules and time punches can be corrected retrospectively.

For an own-company or single-client 7shifts integration, use a company access token. For a distributed customer-facing product, use partner OAuth. Authentication is only the first check.

Your requests must identify the right customer, your parsers must match the selected version, and your retrieval must include every relevant page and record state. Test each requirement separately. Do not use one successful response to validate the connection.

7shifts' Introduction describes REST access to scheduling, labor, sales, and employee data at https://api.7shifts.com/v2. Most resources are company-scoped, and published request versions are date-based.

7shifts' Authentication guide also assigns proof-of-concept and non-vetted, limited-company integrations to the company-token path. Partner OAuth requires partnership review and technical certification. OAuth clients are not self-serve, so most teams start on an access token either way.

This reference covers credential selection, authorization, versioning, company mapping, retrieval and reconciliation for engineers building customer-facing integrations.

Establish the company-token contract

A company access token is long-lived, bound to one company, and grants admin-level access that cannot be scoped by resource or action. Under 7shifts' Authentication reference, requests use bearer authorization without x-company-guid.

Before creating a token, identify its technical contact. That person must be an active admin who has logged in at least once. The token depends operationally on both its stored value and that contact's status.

Create the credential and plan how you will maintain it:

  1. Company Settings > Developer Tools > Access Tokens: create the company token and assign a valid technical contact. Record which company and application the token serves.
  2. Authorization: Bearer {ACCESS_TOKEN}: send the token in this header from your backend. Do not add the company-GUID header required by the partner OAuth path.
  3. Maintain the technical contact: check the contact's status when authentication stops. Deactivation or loss of admin status interrupts authentication; assigning a valid contact restores it.
  4. Delete deliberately: deleting the token immediately prevents applications using it from authenticating. Identify dependent applications before removing it.

Keep credential handling server-side. 7shifts' Introduction explicitly distinguishes CORS support from safe credential exposure: tokens and OAuth client secrets do not belong in browser code.

OWASP's NHI2:2025 Secret Leakage identifies source code, configuration files, logs, and other development stores as places secrets can leak. It recommends dedicated secret management and automated detection of committed secrets. Apply those controls to the stored token and review the paths through which requests are logged.

A long-lived token removes a recurring issuance step. Ownership checks and deliberate revocation are still necessary.

Connect the OAuth grant to the customer's requests

Partner OAuth separates customer authorization, token issuance, and request context. In 7shifts' OAuth Authentication guide, the customer grant supplies a company GUID, while the issued bearer token supplies token-scoped authorization.

Build requests with the documented operations and inputs below:

Operation or input Documented contract
Customer authorization An admin grants access through https://app.7shifts.com/generate_token?client_id={CLIENT_ID}.
Redirect correlation Optional state is returned during the redirect.
Customer identifier The grant creates a GUID mapped one-to-one to a company. With a redirect URL configured, the redirect carries both guid and company_id. Without one, the admin copies the GUID from Company Settings > Developer Tools > Connected Apps.
Token operation Form-encoded POST https://app.7shifts.com/oauth2/token.
Token form parameters grant_type=client_credentials, client_id, client_secret, and scope.
API authorization Authorization: Bearer {ACCESS_TOKEN} together with x-company-guid.

Check each step separately before accepting the connection:

  1. Capture the customer grant: have the customer's admin authorize access and associate the returned GUID with the correct customer connection. If you send a redirect-correlation value, verify its returned value.
  2. Request a bearer token: use the form-encoded token operation with your client credentials and the scopes your application needs. Keep the customer GUID distinct from the issued token.
  3. Apply request context: send both required API headers. The bearer token does not replace the customer GUID, and the GUID does not replace bearer authorization.
  4. GET /v2/whoami: verify identity before accepting the connection as ready for company-scoped retrieval.

The token request, followed by an identity check under the customer's GUID:

Request
curl -X POST "https://app.7shifts.com/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id=" \
  --data-urlencode "client_secret=" \
  --data-urlencode "scope="

curl "https://api.7shifts.com/v2/whoami" \
  -H "Authorization: Bearer " \
  -H "x-company-guid: " \
  -H "x-api-version: 2026-01-01"

The token response contains expires_in: 3600, meaning the issued bearer token expires after one hour. Obtain another through the same client-credentials operation. There is no refresh-token exchange in this documented flow; that lifetime applies to the issued token, not to the company-token path or client registration.

Protect the client secret more carefully than the tokens it produces. 7shifts cannot recover a lost secret, and resetting an OAuth client requires every customer you have already integrated with to authorize again. Treat a reset as a customer-facing event, with a plan for reaching each admin.

The documented scope stems each have read and write variants:

Resource stem Read scope Write scope
Companies companies:read companies:write
Departments departments:read departments:write
Locations locations:read locations:write
Roles roles:read roles:write
Users users:read users:write
Sales sales:read sales:write
Shifts shifts:read shifts:write
Time punches time_punches:read time_punches:write
Events events:read events:write

Requested scopes restrict that token. 7shifts does not currently restrict which scopes a client requests, so choose the scopes your implementation needs rather than treating the available scope list as a default.

The IETF's January 2025 RFC 9700, Section 2.3, recommends limiting access-token privileges to the minimum required for the application or use case. This reduces excess access and the impact of token leakage; it is security guidance, not an additional 7shifts enforcement mechanism.

Customer authorization also has a lifecycle. Admins can disconnect a grant, and authorization.revoked notifies subscribers. Handle revoked access in your connection state. Successful token issuance does not establish continuing customer permission.

Pin the published request version

Set x-api-version explicitly to the published version your implementation targets. 7shifts' Versioning reference calls the header optional but strongly recommends it because credential defaults can differ from the published documentation.

Use this matrix to configure and test version selection. Version statuses below are current as of October 2026.

Version-selection condition Effective behavior Implementation verification
Explicit x-api-version: 2026-01-01 Selects the current published version and overrides the credential default. Test requests and parsers against this target.
Explicit 2025-03-01 or 2023-04-01 Selects a supported published version and overrides the credential default. Record which supported contract your application implements.
No header, with a supported credential default Uses the credential default. Inspect that default; do not assume it matches the reference you used.
No header, with an unsupported credential default Falls back to the oldest supported version. Verify the effective contract rather than relying on the configured default.
Credential default differs from the implemented reference Omitting the header can select a different contract. Pin the tested version and align the default during rollout.

Version pinning selects the published contract; it does not make responses immutable. New published versions accompany breaking changes, but additive fields can appear within a version. Your parser should not interpret every unfamiliar field as a version mismatch.

Published versions receive at least 12 months of support, and retirement is announced in the changelog. The v1 API has been removed. Support provides a migration window rather than an indefinite guarantee.

Before upgrading, review the changelog and test the target header with your parsers. Deploy the tested change to production and align the credential default. Keeping the explicit header and the default aligned makes future requests that omit the header easier to reason about.

OWASP's API9:2023 Improper Inventory Management recommends recording API environments, network-access audiences, deployed versions, and integrated-service data flows. Record the chosen 7shifts version and its retirement tracking in that inventory. When upgrading, update the recorded implementation contract as well as the header string.

Discover the company and preserve its relationships

Discover the company ID before building company-scoped reads. Preserve the organizational relationships rather than flattening each user into one location or role. 7shifts' Introduction describes optional departments and users who can hold multiple roles across locations.

For example, a user's role need not belong to a department. A role attached directly to a location can have department_id: 0; your mapping should not reject that record merely because it lacks a department association.

Map each object using the documented relationships:

Object Relationship Mapping consequence
Company Contains locations; its id is returned by company discovery. Store the company ID used by company-scoped paths.
Location Belongs within a company and can have directly attached roles. Do not require every role to pass through a department.
Department Optional organizational layer. Allow company mappings without departments.
Role Can belong to a department or directly to a location. Preserve the attachment represented by the source record.
User Can hold multiple roles across locations. Model assignments without forcing one role or location per user.

Build the initial company mapping with these reads, then verify the returned records:

  1. GET /v2/companies: retrieve the company ID and associate it with the intended customer connection.
  2. GET /v2/company/{COMPANY_ID}/locations: use that ID to verify a company-scoped read under your selected credential and version.
  3. data: inspect the location records in the successful response and compare them with the company's intended mapping.

For OAuth connections, keep this company-ID mapping alongside the grant context established earlier. Check discovery and request authorization separately.

Broad access to employee or labor data does not establish complete payroll or benefits-object coverage. Validate the specific objects and fields your product requires; the category names alone are not a coverage contract.

The first company-scoped response verifies your starting point. You still need to check that retrieval includes every relevant record.

Finish retrieval and diagnose failures

Complete retrieval means exhausting pagination, selecting the relevant record states, and verifying that access permits the requested data. A successful first response satisfies none of those checks by itself.

7shifts' Pagination reference says most list endpoints use limit and cursor. Pass meta.cursor.next into the next request's cursor parameter until it is null. Do not infer completion from the number of records on one page.

Python
def list_all(client, path, params):
    cursor = None
    while True:
        query = {**params, "limit": 100}  # 200 max on most endpoints; check the endpoint
        if cursor:
            query["cursor"] = cursor
        body = client.get(path, params=query).json()
        yield from body["data"]
        cursor = body["meta"]["cursor"]["next"]
        if cursor is None:
            return

The shift retrieval contract also requires separate passes. In 7shifts' Synchronizing Shifts for Data Warehousing, ordinary reads return published, non-deleted shifts; deleted shifts require deleted=true, and drafts require draft=true when relevant. Do not combine those filters, and paginate each pass independently.

Check both the retrieval plan and how it runs:

  1. Select the required passes: decide whether the dataset requires published shifts, deleted shifts, and drafts. Keep the separate passes visible in your retrieval plan.
  2. Exhaust each cursor chain: continue until the documented completion signal appears for that pass. Record completion per pass, not just per company.
  3. Budget requests by token: coordinate workers sharing a token rather than giving each worker an independent allowance.
  4. Investigate exceptions: check credentials, entitlement, parameters, features, and throttling separately before accepting the resulting dataset.

7shifts' Errors reference documents a limit of 600 requests per minute, with a one-minute block after a 429. Its Employee Sync and Labor Integration guides state the limit as 10 requests per second per token across all endpoints. Budget against both, coordinate workers that share a token, and back off rather than repeating the same volume.

Access can fail independently of authentication. Under 7shifts' Plan Requirements guide, partner onboarding determines the integration's minimum customer plan, and both OAuth company grants and endpoint access can undergo plan checks. Feature availability can also explain unexpectedly empty data. Webhooks are plan-gated too: company-level webhooks require a Premium (formerly Gourmet) plan or higher, and OAuth partners arrange webhooks by emailing 7shifts API support rather than configuring them in the app.

Use this matrix to investigate responses and symptoms. A symptom can have more than one cause, so check the relevant contracts before drawing a conclusion:

Observed response or symptom Contract to inspect Verification action
Authentication rejection Selected credential path Recheck bearer handling and the applicable company-token contact or OAuth grant, token, and company-context requirements.
403 Forbidden Endpoint entitlement, alongside authorization inputs Check the customer's plan against the integration requirement; a failed endpoint plan check returns this response.
Unexpectedly empty data Feature availability and retrieval selection Verify relevant feature availability, company mapping, parameters, and record-state passes before accepting an empty dataset.
Only the first page was stored Pagination completion Follow the next cursor until the completion signal is reached.
Page-size assumptions do not match an endpoint Endpoint-specific pagination contract The general default is 20 and maximum is 200 on most endpoints, unless the endpoint specifies otherwise. Verify exceptions separately.
Deleted or draft shifts are absent Shift retrieval filters Run the applicable separate passes and paginate each independently.
429 Per-token request budget Back off for the documented one-minute block and reduce coordinated request pressure.
A request is rejected after parameter changes Request and error contracts Inspect the documented error-body fields status, message, and error, then compare parameters with the selected endpoint contract.

Do not assign List Shifts a guaranteed maximum from the general pagination rule. Check endpoint exceptions separately before setting that assumption in your implementation.

Once every required pass is complete, check whether the stored dataset remains correct over time.

Reconcile changes after the initial read

A complete initial read gives you a starting state, not a permanent copy of the source. 7shifts' Introduction and Synchronizing Shifts for Data Warehousing explain that published schedules and time punches can be corrected retrospectively.

For shifts, schedule.published can trigger retrieval. Use that event as a reason to read source records, and keep reconciliation as a separate check.

Use these checks to verify ongoing correctness:

  1. Upsert by shift ID: apply reread shift records to existing records by their source identity rather than treating every response as a new shift.
  2. Reread a trailing window: revisit previously retrieved periods to capture retrospective corrections. Choose the window deliberately rather than assuming forward-only retrieval is sufficient.
  3. Test event-triggered retrieval: verify that a schedule-publication event initiates the intended shift read. Keep this path distinct from your reconciliation checks.
  4. Test webhook parsing separately: accept unfamiliar fields and verify the consumer without assuming the request-version header controls event payloads.

The shift guide suggests current and previous pay periods as a starting trailing window. It does not guarantee that this window captures every correction. Your acceptance criteria should account for edits outside the window you choose.

7shifts' Versioning reference places webhook payloads outside the request-version guarantees: they do not use x-api-version. Pinning API requests therefore does not freeze webhook payloads.

Test request parsers, webhook consumers, and reconciliation independently. A passing result for one check does not establish that the other two pass.

Where a unified API fits for 7shifts

Bindbee has a live 7shifts connector, and it is read-only today. Per Bindbee's model availability matrix, it reads Employee, Employment, Compensation, Company, Group, Location, Time Off and Timesheet Entry. It does not read payroll runs, benefits or time-off balances from 7shifts, and it does not write back.

Bindbee connects 7shifts through the access-token path described earlier, not partner OAuth. The customer's admin creates an access token under Company Settings > Developer Tools and pastes it into Bindbee's Magic Link, so no x-company-guid or client secret is involved. The token's dependencies come with it: if the technical contact loses admin status or the token is deleted, the connector moves to RELINK_NEEDED and the admin reconnects with a valid token. Bindbee's scoping still limits which models and fields it requests, even though the token itself grants admin-level access.

Against the work in this guide:

Requirement from this guide Direct 7shifts implementation With Bindbee
Customer context on every request x-company-guid per company, plus your company ID mapping One X-Connector-Token per customer connection
Version pinning You pin x-api-version and track the changelog Your parsers target Bindbee's unified schema, not a 7shifts version
Cursor completion and separate deleted or draft passes Your retrieval code You read Bindbee's copy of the last completed sync
Retrospective corrections You re-read a trailing window Changes a sync picks up arrive as updated events, and modified_after returns records changed since you last looked
Fields outside the unified model Your own mapping Custom Fields, through a JMESPath expression on the raw payload
7shifts operations Bindbee does not model, including writes Your code Passthrough, using the credentials Bindbee holds for that connection and limited to the access it was granted

Freshness is the question to settle first. Bindbee syncs every 24 hours by default, adjustable on request, and sends webhooks after each sync. Those events carry an id for deduplication and a per-connector sequence for ordering, and they report what a sync found. For payroll exports from corrected punches, a scheduled daily read often fits. For a live view of who is clocked in, it does not.

The three ways to reach a field your unified API doesn't have explains when to use each access path. To check your required fields and endpoints against the connector, see the 7shifts integration page or book a technical review.

Frequently asked questions

Does 7shifts have an API?

Yes. 7shifts offers a REST API at https://api.7shifts.com/v2 covering scheduling, labor, sales and employee data. Most resources are company-scoped, and request versions are date-based.

What is the difference between a 7shifts access token and OAuth?

An access token is long-lived, bound to one company and grants admin-level access that cannot be scoped. Partner OAuth is for vetted partners: tokens last one hour, carry requested scopes, and every request also needs x-company-guid.

What is the 7shifts API rate limit?

7shifts documents 600 requests per minute, with a one-minute block after a 429. Its Employee Sync and Labor Integration guides also state 10 requests per second per token. Budget against both.

Which 7shifts API version should I use?

Pin x-api-version to the version you tested against. As of October 2026, 2026-01-01 is current and 2025-03-01 and 2023-04-01 are supported. Without the header, the credential default applies.

How does 7shifts API pagination work?

Most list endpoints use limit and cursor. Pass meta.cursor.next into the next request until it returns null. The default page size is 20 and the maximum is 200 on most endpoints.

Kunal Tyagi
CTO
Bindbee
VIEW AUTHOR
BLOG_

Related blogs