Skip to content
ShiftlyDevelopers
Documentation menu

Quickstart

Connect the sandbox business, list its shifts and create a draft shift. About ten minutes.

Before you start

  • Sandbox credentials from Shiftly: a client id, a client secret and the sandbox owner's sign-in. See Sandbox.
  • A return address on your side that Shiftly can send the owner back to, registered with your app. It must start with https://.
  • A way to run HTTP requests from your server or a terminal, not from a web page. The samples use curl.

1. Send the owner to Shiftly

Build a PKCE pair: a random verifier of 43 to 128 characters, and its challenge, the base64url SHA-256 of the verifier. Then send the owner's browser to the authorize address.

Authorize request
https://demo.shiftly.au/oauth/authorize
  ?response_type=code
  &client_id=shf_your_client_id
  &redirect_uri=https://yourapp.example/shiftly/callback
  &scope=roster:read%20roster:write%20offline_access
  &state=a-value-you-will-check-on-return
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

The owner signs in to Shiftly, sees your app's name and the permissions you asked for, chooses the business, and allows access. Shiftly sends them back to your return address with a code and your state.

Return to your app
https://yourapp.example/shiftly/callback?code=xxxxxxxx&state=a-value-you-will-check-on-return

2. Exchange the code

Within five minutes, exchange the code for credentials. Authenticate your app with HTTP Basic using the client id and secret, and send the verifier that matches the challenge.

Token request
curl -X POST https://demo.shiftly.au/oauth/token \
  -u "shf_your_client_id:shf_sk_your_client_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "xxxxxxxx",
    "redirect_uri": "https://yourapp.example/shiftly/callback",
    "code_verifier": "THE_VERIFIER_YOU_GENERATED"
  }'
Token response
{
  "access_token": "eyJhbGciOiJFUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 1800,
  "refresh_token": "shf_rt_...",
  "scope": "roster:read roster:write offline_access",
  "connection_id": "66f1c2a4b3d9e8f7a6b5c4d3",
  "business_id": "66f1c2a4b3d9e8f7a6b5c4d2"
}

Store the refresh token securely against the business. The access credential lasts 30 minutes; Stay connected covers renewing it.

3. List shifts

Every request goes to the v1 base address with the access credential as a bearer token. Date ranges are calendar days in the location's timezone.

List this week's shifts
curl "https://demo.shiftly.au/v1/shifts?from=2026-10-05&to=2026-10-11" \
  -H "Authorization: Bearer eyJhbGciOiJFUzI1NiIs..."
Response
{
  "data": [
    {
      "id": "66f1c2a4b3d9e8f7a6b5c4e1",
      "location_id": "66f1c2a4b3d9e8f7a6b5c4d9",
      "position_id": "66f1c2a4b3d9e8f7a6b5c4da",
      "employee_id": "66f1c2a4b3d9e8f7a6b5c4db",
      "roster_id": "66f1c2a4b3d9e8f7a6b5c4dc",
      "start_time": "2026-10-05T09:00:00+11:00",
      "end_time": "2026-10-05T17:00:00+11:00",
      "status": "published",
      "breaks": [{ "offset_minutes": 240, "duration_minutes": 30, "paid": false }],
      "notes": null,
      "paid_hours": 7.5,
      "created_by_app": null,
      "archived": false,
      "created_at": "2026-09-28T03:12:45Z",
      "updated_at": "2026-10-01T22:04:10Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

4. Create a draft shift

Send an Idempotency-Key so a retry never creates a second shift. Leave breaks out and Shiftly plans them from the award.

Create a shift
curl -X POST https://demo.shiftly.au/v1/shifts \
  -H "Authorization: Bearer eyJhbGciOiJFUzI1NiIs..." \
  -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
  -H "Content-Type: application/json" \
  -d '{
    "location_id": "66f1c2a4b3d9e8f7a6b5c4d9",
    "position_id": "66f1c2a4b3d9e8f7a6b5c4da",
    "employee_id": "66f1c2a4b3d9e8f7a6b5c4db",
    "start_time": "2026-10-07T09:00:00+11:00",
    "end_time": "2026-10-07T15:00:00+11:00"
  }'

The response is 201 with the shift. Its status is unpublished: it is a draft on the roster, and a manager publishes it in Shiftly. Open the sandbox business in Shiftly and you will see it on the roster.

What can go wrong

ResponseWhyWhat to do
401 token_expiredThe access credential has expired.Renew it with the refresh token and retry.
403 permission_deniedYou did not ask for roster:write, or the person who connected the app cannot edit rosters.Ask for the permission at consent, or have an owner connect the app.
422 validation_failedA field is wrong. The error names it.Fix the field named in error.field.
409 conflictThe person already has a shift at that time.Pick another time, or change the existing shift.

Next

Connect a business explains every parameter of the flow you just ran, what the owner sees, and what happens when they cancel.