Actions

Learn about the different action types in ThinkFleet: piece actions, code actions, branching, and loops.

5 min readBuilding Flows

Actions

Actions are the steps in your flow that perform work after the trigger fires. ThinkFleet provides several action types to handle different scenarios.

Piece Actions

Piece actions are operations provided by integration pieces. They interact with external services through their APIs.

Adding a Piece Action

  1. Click + below any step
  2. Search for a piece by name or browse by category
  3. Select the specific action
  4. Connect your account (or select an existing connection)
  5. Configure the action inputs

Example: Create a Google Sheets Row

Piece: Google Sheets
Action: Insert Row
Connection: my-google-account
Settings:
  Spreadsheet: "Sales Tracker"
  Sheet: "Sheet1"
  Values:
    Column A: "{{trigger.body.customerName}}"
    Column B: "{{trigger.body.email}}"
    Column C: "{{trigger.body.orderTotal}}"

Dynamic Inputs

Most piece action inputs support dynamic values using the data reference syntax:

Static value:    Hello World
Dynamic value:   {{trigger.body.name}}
Mixed:           Order #{{step_1.orderId}} confirmed

Code Actions

Code actions let you run custom JavaScript/TypeScript when pieces don't cover your use case.

Writing Code Actions

export const code = async (inputs) => {
  // inputs contains data you configure in the step settings
  const orders = inputs.orders;

  // Perform any computation
  const summary = {
    total: orders.reduce((sum, o) => sum + o.amount, 0),
    count: orders.length,
    average: orders.reduce((sum, o) => sum + o.amount, 0) / orders.length,
    highestOrder: Math.max(...orders.map(o => o.amount)),
  };

  // Return data for subsequent steps
  return summary;
};

Code Action Inputs

Define inputs in the step configuration panel to pass data from previous steps into your code:

Input Name Value
orders {{step_1.response.data}}
threshold 500

These become available as inputs.orders and inputs.threshold in your code.

Using npm Packages

You can import npm packages in code actions. Declare them in the Packages section of the step settings:

{
  "axios": "1.6.0",
  "lodash": "4.17.21",
  "date-fns": "3.0.0"
}

Then use them in your code:

import axios from 'axios';
import { groupBy } from 'lodash';
import { format } from 'date-fns';

export const code = async (inputs) => {
  const response = await axios.get('https://api.example.com/data', {
    headers: { Authorization: `Bearer ${inputs.apiKey}` },
  });

  const grouped = groupBy(response.data, 'category');

  return {
    data: grouped,
    fetchedAt: format(new Date(), 'yyyy-MM-dd HH:mm:ss'),
  };
};

Code Action Limitations

  • Timeout: Code actions have a maximum execution time (default: 30 seconds, configurable)
  • Memory: Limited to 256 MB by default
  • Network: Outbound HTTP is allowed; inbound connections are not
  • File system: Read-only access to a temporary directory

Branch (Conditional Logic)

Branch actions split your flow into two paths based on a condition.

Setting Up a Branch

  1. Click + and select Branch
  2. Configure the condition:
Component Example
Field 1 {{trigger.body.status}}
Operator Equals
Field 2 "approved"
  1. Add steps to the True branch (executes when condition is met)
  2. Add steps to the False branch (executes when condition is not met)

Available Operators

Operator Description
Equals Exact string/number match
Not Equals Does not match
Contains String contains substring
Does Not Contain String does not contain substring
Greater Than Numeric comparison
Less Than Numeric comparison
Is Empty Field is null, undefined, or empty string
Is Not Empty Field has a value
Starts With String starts with prefix
Ends With String ends with suffix

Multiple Conditions

Combine conditions with AND / OR logic:

IF (status equals "approved") AND (amount > 1000)
  → Route to finance team
ELSE
  → Route to standard processing

Nested Branches

You can nest branches inside other branches for complex decision trees:

IF region equals "US"
  IF tier equals "enterprise"
    → Assign to US Enterprise team
  ELSE
    → Assign to US General team
ELSE
  → Assign to International team

Loops

Loop actions iterate over an array and execute child actions for each element.

Setting Up a Loop

  1. Click + and select Loop
  2. Set Items to an array: {{step_1.response.items}}
  3. Add child actions inside the loop body

Accessing Loop Data

Inside a loop, use these references:

Reference Description
{{loop.item}} The current item in the iteration
{{loop.index}} The current index (0-based)

Example: Send Personalized Emails

Trigger: Schedule (daily at 9 AM)
Step 1: Query database for today's birthdays
Loop over: {{step_1.customers}}
  → Send Email:
      To: {{loop.item.email}}
      Subject: "Happy Birthday, {{loop.item.firstName}}!"
      Body: "Here's a special 20% discount code: BDAY-{{loop.item.customerId}}"

Loop Performance

  • Loops execute iterations sequentially
  • Each iteration counts as a separate task execution for billing purposes
  • For very large arrays (1000+ items), consider using batch APIs instead of looping

HTTP Request Action

The built-in HTTP Request action lets you call any REST API directly without needing a dedicated piece.

Configuration

Method: POST
URL: https://api.example.com/v1/records
Headers:
  Authorization: "Bearer {{connections['my-api-key']}}"
  Content-Type: "application/json"
Body:
  {
    "name": "{{trigger.body.name}}",
    "email": "{{trigger.body.email}}"
  }

Response Handling

The HTTP Request action returns:

{
  "status": 201,
  "headers": { "content-type": "application/json" },
  "body": { "id": "rec_123", "created": true }
}

Access the response in subsequent steps:

{{http_request_1.body.id}}      → "rec_123"
{{http_request_1.status}}       → 201

Action Execution Order

Actions execute sequentially from top to bottom. Each action waits for the previous action to complete before starting. Within a branch, only the matching path executes. Within a loop, the child actions execute sequentially for each iteration.

Next Steps