Raxx · internal docs

internal · gated ↑ index

FreeScout ticket workflow

System: FreeScout helpdesk — tickets.raxx.app Owner: operator Created: 2026-05-14 UTC Last reviewed: 2026-05-14 UTC Related issue: #TBD (operator-decision: status implementation path)


The 5-state workflow

Received → Working → Waiting Response → Working → Resolved
              ↑__________________________|

Spam  (dead-end, separate from the main flow)

Unique states: Received, Working, Waiting Response, Resolved, Spam (5 total).

"Working" is a single state that a ticket re-enters after the customer responds from "Waiting Response." It is not a second distinct state.


FreeScout status mapping

FreeScout ships four hard-coded statuses: active, pending, closed, spam.

Raxx workflow state FreeScout status Notes
Received active New ticket; no operator action taken yet
Working active Operator has engaged; ticket in progress
Waiting Response pending Operator replied; waiting on customer
Resolved closed Issue confirmed resolved by operator
Spam spam Never reassigned; dead-end

Limitation with Option A (relabel only): "Received" and "Working" both map to active. They are not distinguishable in FreeScout without a tag or custom folder — see Implementation Options below.


Implementation options

Option A — Relabel existing statuses (no schema changes)

Use FreeScout's built-in translation override (Manage » Translate) to rename the four status labels as they appear in the operator UI:

FreeScout status Display label today Proposed label
active Active Working
pending Pending Waiting Response
closed Closed Resolved
spam Spam Spam (no change)

"Received" does not get a dedicated status. New tickets arrive as active (relabeled "Working"). To distinguish Received-but-not-yet-touched tickets from those actively in progress, use a tag: automatically apply tag received via a Workflow trigger on conversation creation; remove the tag when the operator first replies.

Gap: filtering or counting "Received" requires a saved search or custom folder, not a first-class status selector.

Relabel steps (UI-only; requires operator admin login):

  1. Log in to https://tickets.raxx.app (passes through CF Access first).
  2. Navigate to Manage » Translate.
  3. Click Import Translations.
  4. In the Group dropdown, select App.
  5. Select language English.
  6. Search for the string Active — override with Working.
  7. Search for Pending — override with Waiting Response.
  8. Search for Closed — override with Resolved.
  9. Click Publish translations.

Verification: open any existing ticket; the status dropdown and all status badges should show the new labels immediately (no cache flush needed).

Impact on existing tickets: zero data change. The underlying status column values (active, pending, closed, spam) are unchanged. All API calls, Workflow conditions, and Webhooks continue to use the internal values. Translation is display-only.

Impact on FreeScout upgrades: translation overrides survive FreeScout core updates because they are stored in the database, not in the application files. Re-import from Manage » Translate is not required after upgrades.


Option B — Custom Folders to simulate "Received" as a distinct view

The customfolders module (purchased, listed in vault at /MooseQuest/freescout/CUSTOM_FOLDERS_LICENSE_KEY) adds a sidebar folder that surfaces a filtered conversation list — it is NOT a true new status column value.

What Custom Folders can do for this workflow: - Create a folder called "Received" that shows all active tickets with tag received applied. - Create a folder called "Working" that shows all active tickets WITHOUT tag received.

This gives the operator a visual distinction between Received and Working even though both are stored as active.

To populate the tag automatically, create a Workflow (Workflows module, also purchased): Trigger: conversation created → Action: add tag "received". A second Workflow removes the tag when an operator replies: Trigger: conversation reply by user → Action: remove tag "received".

Operator steps for Option B (after module install — see docs/ops/runbooks/freescout-paid-module-install.md):

  1. Install and activate Custom Folders module (customfolders) via Manage » Modules.
  2. Install and activate Tags module (tags) and Workflows module (workflows) if not already active.
  3. Navigate to Manage » Custom Folders. Create two folders: - "Received" — filter: Status = active AND Tag = received - "Working" — filter: Status = active AND Tag NOT = received (or Status = active AND no tag)
  4. Navigate to Manage » Workflows. Create two workflows: - Workflow "Tag new tickets as received":
  5. Optionally apply Option A relabeling (translate active → "Working", pending → "Waiting Response", closed → "Resolved") in addition.

Limitation: Custom Folders are a view layer — they do not create a true database status. If a ticket has no received tag and is in active state, it appears in "Working" — which is correct. However if the tag automation is ever misconfigured, tickets fall out of the expected folder silently.


Option C — Defer; use defaults as-is for v1

Accept active/pending/closed/spam with no relabeling or custom folders. Ops staff mentally map: active = in progress (covers both Received and Working), pending = waiting on customer, closed = resolved.

Tradeoff: the "Received" distinction is lost. Acceptable for v1 with a small ticket volume and a single operator.


When to transition (rules of thumb)

Trigger Transition Action in FreeScout
Customer email arrives; nobody has responded Automatically lands in Received / Working (active) No action needed — auto status
Operator starts work on the ticket Received → Working Remove received tag (auto-removed on first reply); no status change
Operator sends a reply to customer Working → Waiting Response Set status to pending
Customer replies to an open ticket Waiting Response → Working FreeScout auto-moves pendingactive on customer reply
Issue is confirmed resolved Working → Resolved Set status to closed
Re-opening a resolved ticket Resolved → Working Set status to active; optionally add note
Identified as junk/automated spam Any → Spam Set status to spam; this is a dead-end

FreeScout auto-behavior to know: - When a customer replies to a pending ticket, FreeScout auto-sets it back to active. This implements the Waiting Response → Working transition automatically. - When an operator replies to a closed ticket, FreeScout auto-sets it to active. This correctly re-opens resolved tickets when customers follow up. - Spam is sticky — there is no automatic move out of Spam.


Spam handling

Spam is a dead-end status distinct from the main workflow:

Spam tickets are retained for audit reference. FreeScout does not auto-purge spam. Periodic manual bulk-delete is acceptable for tickets older than 90 days with no custom field values attached.


FreeScout API status values (for integrations)

Integrations (status.raxx.app webhook, future Queue API, etc.) use the internal status values, not display labels. These are stable regardless of which implementation option is chosen:

Internal value FreeScout API field Notes
active status: "active" Covers Received + Working in Option A
pending status: "pending" Waiting Response
closed status: "closed" Resolved
spam status: "spam" Spam

The Workflows webhook receiver (#607) and custom fields runbook (docs/ops/runbooks/freescout-status-fields.md) use these internal values. If Option B tag-based folders are used, the tag value received is the additional signal — pass it via the customFields block or via a webhook event when the tag is added/removed.


References