Home Pricing Docs Blog Changelog About Log in Go to your tickets
Browse docs

Workflows

Overview

Workflows define conditions and actions that run against tickets. The trigger_type controls when a workflow fires:

  • on_new_ticket: runs once when a new ticket is created. Does not run on replies.
  • on_inbound_message: runs on every inbound message, including replies to existing tickets.
  • on_no_reply: runs when a customer message has been waiting for a reply longer than the configured duration. Requires trigger_parameters (see below). Fires once per waiting period and re-arms when the customer writes in again after a reply. With only_business_hours, durations in minutes or hours pause the clock outside the workspace's business hours, and durations in days count business days (days on which the workspace is fully closed do not count). Without it, days mean calendar days (2 days fires exactly 48 hours after the unanswered message).
  • on_tag_added: runs when a tag is added to a ticket. Optionally scope it to specific tags with trigger_parameters (see below).
  • on_tag_removed: runs when a tag is removed from a ticket. Optionally scope it to specific tags with trigger_parameters (see below).
  • manual: can be triggered from the ticket sidebar when conditions match.

Admin role is required to create, update, or delete workflows.

List Workflows

GET /api/workflows

Show Workflow

GET /api/workflows/{workflow}

The response includes nested conditions and actions arrays.

Create Workflow (admin only)

POST /api/workflows

Request Body

Field Type Required Description
name string Yes
description string No
trigger_type string Yes on_new_ticket, on_inbound_message, on_no_reply, on_tag_added, on_tag_removed, or manual
trigger_parameters object No Required for on_no_reply: { "value": 4, "unit": "hours", "only_business_hours": false }. Unit is minutes, hours (default), or days, capped at 30 days in total. With only_business_hours, only the workspace's business hours (or business days, for the days unit) count toward the duration. For on_tag_added and on_tag_removed, optionally { "tags": ["tag-ulid", ...] } to scope the trigger to specific tags; omit or leave empty to fire for any tag.
condition_match_type string No all (default) or any
is_enabled boolean No Defaults to true
conditions array No Array of { type, parameters } condition objects
actions array No Array of { type, parameters } action objects

Condition Types

  • body_contains
  • channel_is
  • channel_type_is
  • contact_is_new
  • does_not_have_tag
  • from_domain_equals
  • from_email_contains
  • from_email_equals
  • has_tag
  • is_first_message
  • subject_contains
  • subject_equals

Example Request

curl -X POST https://there-there.app/api/workflows \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "X-Workspace-Id: 1" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Auto-close spam",
    "trigger_type": "on_new_ticket",
    "condition_match_type": "any",
    "conditions": [
      { "type": "subject_contains", "parameters": { "value": "unsubscribe" } }
    ],
    "actions": [
      { "type": "set_status", "parameters": { "status": "spam" } }
    ]
  }'

On No Reply Example Request

curl -X POST https://there-there.app/api/workflows \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "X-Workspace-Id: 1" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Escalate waiting tickets",
    "trigger_type": "on_no_reply",
    "trigger_parameters": {
      "value": 4,
      "unit": "hours",
      "only_business_hours": true
    },
    "condition_match_type": "all",
    "actions": [
      { "type": "assign_ticket", "parameters": { "assign_type": "team", "team": "TEAM_ULID", "user": null } }
    ]
  }'

Update Workflow (admin only)

PUT /api/workflows/{workflow}

Omit fields to leave them unchanged. If conditions or actions is included, existing conditions/actions are replaced entirely.

Delete Workflow (admin only)

DELETE /api/workflows/{workflow}