Skip to content

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 headers
const headers = {
'Authorization': 'Bearer YOUR_JWT_TOKEN',
'Content-Type': 'application/json'
};

Your First Workflow

Let’s create a simple document approval workflow with three steps:

  1. Submit Document
  2. Manager Review
  3. Final Approval
  1. 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"
    }) {
    id
    name
    }
    }
    mutation CreateReviewStation {
    addStation(input: {
    name: "Manager Review"
    description: "Manager reviews and provides feedback"
    }) {
    id
    name
    }
    }
    mutation CreateApprovalStation {
    addStation(input: {
    name: "Final Approval"
    description: "Final sign-off on the document"
    }) {
    id
    name
    }
    }

    Save the returned id values - you’ll need them in the next step.

  2. Create a route

    Now create a route that connects these stations. The instructions array defines how stops are added:

    mutation CreateApprovalRoute {
    addRoute(input: {
    name: "Q4 Report Approval"
    instructions: [
    {
    trackType: stop
    action: startWith
    actionStationOrRouteTemplateId: "SUBMIT_STATION_ID"
    },
    {
    trackType: stop
    action: addAfter
    actionStationOrRouteTemplateId: "REVIEW_STATION_ID"
    actionTargetStopId: "stop-id-from-previous"
    },
    {
    trackType: stop
    action: addAfter
    actionStationOrRouteTemplateId: "APPROVAL_STATION_ID"
    actionTargetStopId: "stop-id-from-previous"
    }
    ]
    }) {
    id
    name
    status
    stops {
    id
    name
    status
    }
    }
    }
  3. Track your route

    View the current state of your route:

    query GetMyRoute {
    getRoute(id: "YOUR_ROUTE_ID") {
    id
    name
    status
    stops {
    id
    name
    status
    station {
    description
    }
    }
    actionLog {
    action
    timestamp
    stopName
    }
    }
    }
  4. Mark stops as completed

    As work progresses, mark stops as completed:

    mutation CompleteSubmission {
    markStopCompleted(
    routeId: "YOUR_ROUTE_ID"
    stopId: "SUBMIT_STOP_ID"
    ) {
    id
    stops {
    id
    name
    status
    }
    }
    }
  5. Subscribe to updates

    Get real-time notifications when routes change:

    subscription WatchRouteUpdates {
    routeUpdated(tenantId: "YOUR_TENANT_ID") {
    id
    name
    status
    stops {
    id
    status
    }
    }
    }

Understanding Route Instructions

When creating routes, the instructions array tells Stations how to build the route structure. Each instruction has several fields:

Instruction Fields

FieldTypeDescription
trackTypeTrackTypeWhat type of element to add
actionActionHow to position the element
actionStationOrRouteTemplateIdIDThe station or template to add
actionTargetStopIdStringThe existing stop to position relative to
enableAsynchronousChildrenBooleanAllow parallel child stops

Track Types

ValueDescription
stopAdd a station as a stop in the route
routeTemplateEmbed an entire route template
routeReference another route

Actions

ActionDescriptionRequires actionTargetStopId
startWithCreates the first stop in the routeNo
addAfterAdds a stop after the target stopYes
addBeforeAdds a stop before the target stopYes
addAsFirstChildAdds as first parallel child of targetYes
addAsLastChildAdds as last parallel child of targetYes
replaceReplaces the target stopYes
removeRemoves the target stopYes

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
}
}

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: