Start a Workflow

A workflow starts when someone submits a form, when another system sends a web request to the workflow's address, on a schedule, when a shift starts or ends, when someone checks in or out, when someone asks for or takes a shift, or when chat messages are left unread.

Choose what starts a workflow

In the workflow editor, click the Starts when box on the left side of the canvas. Then, in What starts it, choose one of these:

  • A form is submitted: Someone fills in a form and clicks Submit.
  • A web request: Another system, like an online store, a booking site, or a form builder, sends a request to the workflow’s web address.
  • On a schedule: At a time of day, or every few hours between two times, every day or on the days you choose.
  • A shift starts or ends: For each shift, at its start or end, or a set amount of time before or after. It can check whether the person checked in, was late, or didn’t show up.
  • Someone arrives or leaves: When someone checks in or out. Only when Checking in and out is turned on, or when people clock in with Square.
  • A shift request: When someone asks for cover or a swap, or when someone takes a shift. A workflow can approve or deny it. Only when Schedule is turned on.
  • Messages left unread: When someone has a chat message they haven’t read for a set amount of time. Only when Team chat is turned on.
  • A store event: When catalog items or stock counts change, or an order is placed or updated.
  • Nothing yet: You can build the workflow first and choose what starts it later.

Whatever starts it, the run begins at the step the Starts when box is connected to.

Start from a form

Choose the form. When someone clicks Submit, the answers on the form are saved, and a run starts with them. Steps use the answers as data.values.<field>, like data.values.email for a field whose key is email.

If the form has an action button, choose it in Only when pressed. The run then starts only if the button is pressed at submit, and wasn't pressed at the last submit.

One form can start more than one workflow, because each workflow points to the form, not the other way around.

Start on a schedule

In Runs, choose Once a day and a Time, or choose Every few hours (every 1, 2, 3, 4, 6, 8, or 12 hours), with a From time and an Until time. For example, every 4 hours from 8:00 until 20:00 runs at 8:00, 12:00, 16:00, and 20:00. Then choose the Days it runs. The default is every day. Times are in your account's time zone, which an admin can set in Account under General. A workflow set to run at 6 p.m. runs at 6 p.m. local time, in winter and in summer.

A scheduled run starts within a minute of its time. If Skidle can't start it on time, for example during an outage, it starts late, up to an hour late. After an hour, that day's run is skipped. A new schedule doesn't start runs for times before it was published.

The run can use when it started:

  • data.schedule.at: The exact time, in UTC.
  • data.schedule.date: Your account's local date, like 2026-09-24. This is useful in an email subject.
  • data.schedule.from: The scheduled time before this one, where "since the last run" starts. If the workflow runs every 4 hours, it's four hours ago. On Monday morning, for a weekday schedule, it's Friday's last run. A Board report set to Since last run uses this.

A common use is summarizing what was collected. For example: every day at 6 p.m. → Look something up with From the last set to 24h → an email with the results.

Start when a shift starts or ends

Shifts come from a connected point-of-sale system (currently Square), or from your own system through the Skidle API (POST /accounts/{account_id}/shifts). You can use both, and triggers treat every shift the same way no matter where it came from. Choose:

  • When: A shift starts, or a shift ends.
  • Timing: Right then, or a number of minutes or hours before or after, up to 12 hours.
  • Days: The days the shift starts on, in your account's time zone. The default is every day.
  • Identities: Optional. Only shifts for people who fit one of these identities count, based on where the shift is. Choose none to include everyone. Every person is already an identity, so "only Jon, only on Tuesdays" means choosing Jon's identity and selecting Tuesday under Days. For a role at one location, or two people together, create an identity in People under Identities.

One workflow covers everyone. Each shift on the schedule starts its own run, assigned to the person working it. Photo, To do, and other steps that wait for a person then appear on that person's Dashboard. The run can use the shift's details:

  • data.shift.person.name: Who's working it.
  • data.shift.startAt and data.shift.endAt: When it starts and ends.
  • data.shift.location.name: Where the shift is.
  • data.shift.checkedIn: Whether the person had checked in for it when the run started.
  • data.shift.late: Whether they checked in later than Late after in schedule settings.
  • data.shift.noShow: Whether they still hadn't checked in, and No-show after has passed.
  • data.shift.checkIn.at: When they checked in. Blank if they haven't.
  • data.shift.checkIn.minutesAfterStart: How many minutes after the start they checked in. A negative number means they were early.

A check-in counts for a shift if it was made for that shift, or if it started between an hour before the shift and the shift's end. For example: "30 minutes after a shift starts" → a Route step with a way out for when No-show is on → a message to the manager. Set the trigger's timing to match No-show after, or later.

Only published shifts count. Draft shifts that no one has been told about don't. If a shift is moved, the trigger uses its new time. A canceled shift doesn't start anything. Changes usually arrive within seconds. Skidle also reads the whole schedule again every day, which catches a shift that was deleted or a change that didn't come through.

To check which shifts a trigger will start for, click Schedule.

For example: "30 minutes before a shift ends" → a Photo step that asks for "The station, cleaned."

Start when someone arrives or leaves

When checking in and out is turned on, choose Someone checks in or Someone checks out. If Square is your time clock, clocking in and out in Square starts these too, usually within seconds. A timecard added or fixed in Square more than an hour after the fact doesn't start anything. In Only for, you can optionally choose the people or roles it applies to. It doesn't matter whether they had a shift. Each check-in or check-out starts its own run, assigned to that person, so a step that waits for a person appears on their Dashboard. The run can use:

  • data.presence.person.name: Who it was.
  • data.presence.at: When they checked in or out.
  • data.presence.arrivedAt: When they checked in, also available on a check-out run.
  • data.presence.shift.startAt, data.presence.shift.endAt and data.presence.shift.location.name: The shift they checked in for. Blank when they had no shift.
  • data.presence.late: Whether they checked in later than Late after in schedule settings. Off when they had no shift.
  • data.presence.minutesAfterStart: How many minutes after the shift's start they checked in. A negative number means they were early. Blank when they had no shift.
  • data.presence.minutesBeforeEnd: On a check-out, how many minutes before the shift's end they left. A negative number means they stayed late. Blank on a check-in, or when they had no shift.

A check-in is for a shift when it happens between an hour before the shift starts and when it ends. This works the same for Square check-ins. Taking a break and coming back doesn't start anything.

To start something a while after someone checks in, add a Wait step right after the trigger. For example: "Someone checks in" → Wait 10 minutes → Create a task with the opening checklist. The checklist still arrives if they check out during the wait.

If an admin checks someone out because they forgot, nothing starts. For example: "Someone checks out" → Create a task with the End of day form, which they see before they leave.

Start when someone asks for or takes a shift

When the schedule is turned on, choose A shift request, then choose When: Someone takes a shift (cover, a swap, or an open shift) or Someone asks for cover or a swap. Each request starts its own run, assigned to the person who asked. The run can use:

  • data.request.kind: cover, swap, or pickup.
  • data.request.from.name and data.request.taker.name: Who asked, and who took it.
  • data.request.part.startAt, data.request.part.endAt, and data.request.part.minutes: The part of the shift it's about. data.request.part.whole is on when it's the whole shift.
  • data.request.shift.location: Where the shift is.
  • data.request.takerWeekMinutes and data.request.takerMonthMinutes: The taker's minutes this week and this month, including this shift.
  • data.request.takerOutsideAvailability: Whether the shift is outside when the taker said they can work.
  • data.request.hoursUntil: How many hours until the shift starts.

To answer the request, end with a Decide request step: approve it, deny it with a reason both people see, or send it to an admin. If no workflow decides, the setting in Schedule settings does. For example: "Someone takes a shift" → a Route step with a way out for data.request.takerWeekMinutes > 2400 → Decide request set to deny, with the reason "That would put {{ data.request.taker.name }} over 40 hours."

Start when messages are left unread

When team chat is turned on, choose Messages left unread, then choose how long a message waits in Unread for, from 15 minutes to a week. In Only for, you can optionally choose the people or roles it applies to.

It starts once per person, not once per message. Someone with twenty unread messages gets one run that covers all twenty. After that, it starts again for them only when a newer message has also waited the full time. So someone who doesn't open the app all week gets at most one run per waiting period, and only while new messages keep arriving. Reading their messages stops it. Messages sent before you publish the workflow never count, so publishing it doesn't start a run for every old unread message.

Skidle checks every five minutes, so a run starts up to five minutes after a message reaches the time limit. Each run is assigned to the person with the unread messages, and can use:

  • data.unread.person.name and data.unread.person.email: Who it is.
  • data.unread.count: How many messages they haven't read, across all their conversations.
  • data.unread.oldestAt: When the oldest one was sent.
  • data.unread.conversations: Each conversation with unread messages, most recent first, with its title (who it's with), how many messages are unread, and its most recent message's lastFrom, lastPreview, and lastAt.

What happens next is up to you. For example: "Unread for 4 hours" → Send an email to data.unread.person.email, → Send a notification to a manager about who hasn't read their messages, or → Send a web request to post in your team's Telegram or Slack.

Start from a web request (webhook)

Choose A web request. The panel shows the workflow's address, which looks like https://api.skidle.com/hooks/whk_…. Enter that address in the other system as its webhook URL. Most systems have a setting called "webhook," "notification URL," or "callback URL."

When that system sends a request to the address, a run starts. What it sent is in data.request:

  • data.request.body: What it sent. Read as JSON if it's JSON, as form fields if it sent a form, and as text otherwise. Example: data.request.body.order.total.
  • data.request.query: Anything after ? in the address. For example, ?source=shop becomes data.request.query.source.
  • data.request.headers: Some of the headers: the content type, the sender's software, and any header that starts with x- (where many systems put an event name or signature).
  • data.request.receivedAt: When it arrived.

Passwords, cookies, and Authorization headers are never kept.

Test a web request before going live

Click Listen for a test, then have the other system send a request (most have a "Send test" button). The request appears in the panel under Last request received. After that, Insert value shows its fields by name, like "order › total" or "customer › email," so you never have to type a path.

Until the workflow is published, requests to its address are saved as a test and don't start runs. The address responds to the sender with 202 and "started": false. After you publish, each request starts a run.

Keep the address safe

Anyone who has the address can start the workflow, so treat it like a password and don't post it publicly. If someone gets it who shouldn't, click Create new address. The old address stops working right away, and you'll need to give the new one to the other system.

Web request limits

Each address accepts up to 60 requests a minute and 5,000 a day. Past that, it responds with 429 Too Many Requests and a Retry-After header that says how many seconds to wait, and nothing starts. A request body can be up to 256 KB. Larger requests are refused with 413.

Start from a store event

A workflow can start when your Square catalog or stock counts change, or when an order is placed or updated. Schedules and timecards don't need this.

  1. In Integrations, open Square's Settings and find Store activity.
  2. Turn on Catalog, Inventory, or Orders, and click Save. The first time, Square asks you to approve it.
  3. In the workflow, set What starts it to A store event, then choose the event.

Each step reads what happened. A catalog change runs only when an item is added or renamed, and gives its old and new names. An order gives its id, state, and location. Square doesn't say who made a change.