Back to Docs

Statuses & Workflows

Configure ticket statuses to match your support workflow. Start with the built-in system statuses and add custom ones as your process evolves.

System Statuses

Every brand starts with four system statuses that cannot be deleted. They represent the fundamental stages of a ticket's lifecycle:

StatusKeyColorMeaning
OpenopenBlue (#3b82f6)New ticket awaiting attention
PendingpendingAmber (#f59e0b)Waiting on customer or external input
ResolvedresolvedGreen (#22c55e)Issue addressed, awaiting confirmation
ClosedclosedGreen (#22c55e)Ticket finalized, no further action

System statuses can be renamed and recolored but not deleted. Their keys (open, pending, resolved, closed) remain constant for API compatibility.

Custom Statuses

Add custom statuses to model workflows beyond the basics. Custom statuses slot between the system statuses and can be reordered freely.

Examples

  • In Progress - Agent is actively working on the ticket
  • Waiting on Engineering - Escalated to the dev team
  • Scheduled - Issue will be addressed in a future release
  • On Hold - Paused, waiting for external dependency
  • Needs Review - Requires manager or QA approval
Create a custom status
const status = await dispatch.statuses.create('br_abc123', {
  name: 'In Progress',
  key: 'in_progress',    // Unique identifier, lowercase with underscores
  color: '#8b5cf6',      // Purple
  description: 'Agent is actively working on this ticket',
});

console.log(status.id); // 'sts_xyz789'

Status Properties

FieldRequiredDescription
nameYesDisplay name shown in the UI
keyYesUnique identifier (lowercase, underscores). Immutable after creation.
colorNoHex color for badges and indicators (default: #6b7280)
descriptionNoInternal description for your team

Status Lifecycle

There are no enforced transition rules. A ticket can move from any status to any other status. This keeps the system flexible for different workflows.

Typical Flow

Open ──→ In Progress ──→ Resolved ──→ Closed
  │           │               │
  │           ▼               │
  │      Waiting on Eng       │
  │           │               │
  └───────────┴───── Pending ─┘
                        │
                        ▼
                   (customer replies → reopens to Open)

When a ticket moves to a new status, the change is recorded in the ticket's activity log and watchers are notified. If the ticket has a webhook configured, a ticket.updated event is fired with the status change in the changes field.

Update ticket status
await dispatch.tickets.update('br_abc123', 'tkt_def456', {
  statusId: 'sts_xyz789', // Use status ID
});

// Or use the status key for system statuses
await dispatch.tickets.update('br_abc123', 'tkt_def456', {
  status: 'resolved',
});

Active vs. Inactive Statuses

Statuses are grouped into two categories for filtering:

  • Active - Tickets that need attention (open, pending, and custom statuses)
  • Inactive - Tickets that are done (resolved, closed)

The dashboard's default view shows active tickets. Use the status filter to include resolved or closed tickets.

Managing Statuses

Via the Dashboard

Go to Settings → Brand → Statuses to view, create, edit, and reorder statuses. Drag-and-drop to set the order they appear in dropdowns and filters.

Via the API

List all statuses
const statuses = await dispatch.statuses.list('br_abc123');

// Returns system + custom statuses in display order
statuses.forEach(s => {
  console.log(`${s.name} (${s.key}) - ${s.isSystem ? 'system' : 'custom'}`);
});
Reorder statuses
// Set display order for all statuses
await dispatch.statuses.reorder('br_abc123', {
  statusIds: [
    'sts_open',
    'sts_in_progress',
    'sts_pending',
    'sts_waiting_eng',
    'sts_resolved',
    'sts_closed',
  ],
});
Get ticket counts per status
const stats = await dispatch.statuses.stats('br_abc123');

// Returns: [{ statusId, statusName, count }, ...]
stats.forEach(s => {
  console.log(`${s.statusName}: ${s.count} tickets`);
});

Deleting Custom Statuses

When you delete a custom status, you must specify a replacement status for any tickets that currently have it. System statuses cannot be deleted.

Deleting a status is permanent. All tickets with that status will be moved to the replacement status you choose.

Automations

Dispatch Tickets includes built-in automations that update ticket status based on activity:

Auto-Reopen on Customer Reply

When a customer replies to a resolved or closed ticket (via email or portal), the ticket automatically reopens to open. This ensures customer follow-ups don't get missed.

Webhook-Based Workflows

For more complex automations, use webhooks to listen for status changes and trigger custom logic:

Automation via webhooks
// Example: Auto-assign tickets based on category
app.post('/webhooks/dispatch', (req, res) => {
  const event = req.body;

  if (event.type === 'ticket.created') {
    const { ticket } = event.data;

    // Route billing tickets to the billing team
    if (ticket.category?.key === 'billing') {
      dispatch.tickets.update(ticket.brandId, ticket.id, {
        assigneeEmail: '[email protected]',
        status: 'in_progress',
      });
    }
  }

  res.status(200).send('OK');
});

Integration Triggers

Combine status changes with external integrations:

  • Notify Slack when a ticket moves to "Waiting on Engineering"
  • Create a Jira issue when priority is set to "urgent"
  • Send a satisfaction survey when a ticket is resolved
  • Update your CRM when a ticket is closed