Quick Start
This guide will walk you through creating your first workflow with Stations. By the end, you’ll have created stations, built a route, and tracked its progress.
Prerequisites
Before you begin, you’ll need:
- A Stations account (sign up at stations.build)
- Your API endpoint URL and authentication credentials
- A GraphQL client (we’ll use examples compatible with any client)
Authentication
Stations uses AWS Cognito for authentication. After signing in, you’ll receive a JWT token to include in your API requests.
// Include the JWT in your request headersconst headers = { 'Authorization': 'Bearer YOUR_JWT_TOKEN', 'Content-Type': 'application/json'};Your First Workflow
Let’s create a simple document approval workflow with three steps:
- Submit Document
- Manager Review
- Final Approval
-
Create your stations
First, create the stations that will serve as stops in your workflow:
mutation CreateSubmitStation {addStation(input: {name: "Submit Document"description: "Initial document submission"}) {idname}}mutation CreateReviewStation {addStation(input: {name: "Manager Review"description: "Manager reviews and provides feedback"}) {idname}}mutation CreateApprovalStation {addStation(input: {name: "Final Approval"description: "Final sign-off on the document"}) {idname}}Save the returned
idvalues - you’ll need them in the next step. -
Create a route
Now create a route that connects these stations. The
instructionsarray defines how stops are added:mutation CreateApprovalRoute {addRoute(input: {name: "Q4 Report Approval"instructions: [{trackType: stopaction: startWithactionStationOrRouteTemplateId: "SUBMIT_STATION_ID"},{trackType: stopaction: addAfteractionStationOrRouteTemplateId: "REVIEW_STATION_ID"actionTargetStopId: "stop-id-from-previous"},{trackType: stopaction: addAfteractionStationOrRouteTemplateId: "APPROVAL_STATION_ID"actionTargetStopId: "stop-id-from-previous"}]}) {idnamestatusstops {idnamestatus}}} -
Track your route
View the current state of your route:
query GetMyRoute {getRoute(id: "YOUR_ROUTE_ID") {idnamestatusstops {idnamestatusstation {description}}actionLog {actiontimestampstopName}}} -
Mark stops as completed
As work progresses, mark stops as completed:
mutation CompleteSubmission {markStopCompleted(routeId: "YOUR_ROUTE_ID"stopId: "SUBMIT_STOP_ID") {idstops {idnamestatus}}} -
Subscribe to updates
Get real-time notifications when routes change:
subscription WatchRouteUpdates {routeUpdated(tenantId: "YOUR_TENANT_ID") {idnamestatusstops {idstatus}}}
Understanding Route Instructions
When creating routes, the instructions array tells Stations how to build the route structure. Each instruction has several fields:
Instruction Fields
| Field | Type | Description |
|---|---|---|
trackType | TrackType | What type of element to add |
action | Action | How to position the element |
actionStationOrRouteTemplateId | ID | The station or template to add |
actionTargetStopId | String | The existing stop to position relative to |
enableAsynchronousChildren | Boolean | Allow parallel child stops |
Track Types
| Value | Description |
|---|---|
stop | Add a station as a stop in the route |
routeTemplate | Embed an entire route template |
route | Reference another route |
Actions
| Action | Description | Requires actionTargetStopId |
|---|---|---|
startWith | Creates the first stop in the route | No |
addAfter | Adds a stop after the target stop | Yes |
addBefore | Adds a stop before the target stop | Yes |
addAsFirstChild | Adds as first parallel child of target | Yes |
addAsLastChild | Adds as last parallel child of target | Yes |
replace | Replaces the target stop | Yes |
remove | Removes the target stop | Yes |
Key Fields Explained
actionStationOrRouteTemplateId: The ID of the station or route template you want to add. When trackType is stop, this is a station ID. When trackType is routeTemplate, this is a template ID.
actionTargetStopId: The ID of an existing stop in the route that you want to position relative to. Required for all actions except startWith. This is the stop ID returned when the stop was created, not the station ID.
Example: Building a Route Step by Step
instructions: [ { # First instruction must use startWith trackType: stop action: startWith actionStationOrRouteTemplateId: "station-abc-123" # Station ID }, { # Add second stop after the first trackType: stop action: addAfter actionStationOrRouteTemplateId: "station-def-456" # Another station ID actionTargetStopId: "stop-xyz-789" # Stop ID from previous instruction }, { # Add parallel branches trackType: stop action: addAfter actionStationOrRouteTemplateId: "station-ghi-789" actionTargetStopId: "stop-from-step-2" enableAsynchronousChildren: true # Children can run in parallel }]Working with Route Templates
If you’ll use this workflow pattern again, save it as a template:
mutation CreateTemplate { addRouteTemplate(input: { name: "Document Approval Template" instructions: [ { trackType: stop action: startWith actionStationOrRouteTemplateId: "SUBMIT_STATION_ID" }, { trackType: stop action: addAfter actionStationOrRouteTemplateId: "REVIEW_STATION_ID" actionTargetStopId: "previous-stop-id" }, { trackType: stop action: addAfter actionStationOrRouteTemplateId: "APPROVAL_STATION_ID" actionTargetStopId: "previous-stop-id" } ] }) { id name }}Managing Route Status
Routes can be paused, resumed, or cancelled:
mutation PauseRoute { pauseRoute(id: "YOUR_ROUTE_ID") { id status }}mutation ResumeRoute { resumeRoute(id: "YOUR_ROUTE_ID") { id status }}mutation CancelRoute { cancelRoute(id: "YOUR_ROUTE_ID") { id status }}Example: Complete Workflow Script
Here’s a complete example using JavaScript:
import { GraphQLClient } from 'graphql-request';
const client = new GraphQLClient('YOUR_GRAPHQL_ENDPOINT', { headers: { Authorization: `Bearer ${YOUR_JWT_TOKEN}`, },});
async function createWorkflow() { // 1. Create stations const stations = await Promise.all([ client.request(` mutation { addStation(input: { name: "Step 1" }) { id } } `), client.request(` mutation { addStation(input: { name: "Step 2" }) { id } } `), ]);
// 2. Create route const route = await client.request(` mutation CreateRoute($instructions: [RouteInstructionInput]!) { addRoute(input: { name: "My Workflow" instructions: $instructions }) { id name status stops { id name status } } } `, { instructions: [ { trackType: 'stop', action: 'startWith', actionStationOrRouteTemplateId: stations[0].addStation.id } ] });
console.log('Created route:', route.addRoute); return route.addRoute;}
createWorkflow();Next Steps
You’ve created your first workflow! Here’s what to explore next:
- Stations Deep Dive - Advanced station features
- Routes Deep Dive - Complex route patterns
- API Reference - Complete API documentation