# Statuses and states

> Every activity has two related notions of “where it is in its lifecycle”:

Canonical HTML page: https://conclude.io/doc/reference/statuses/
Last updated: 2026-11-02

---

Every activity has two related notions of "where it is in its lifecycle":

- **State** — the coarse lifecycle: open, closed, or pending. The state drives
  behavior: closing archives the activity and fires `onConclude`; reopening
  un-archives it.
- **Status** — the finer, app-defined value shown and selected in the UI
  (`open`, `in_progress`, `on_hold`, ...). Each status maps to one state.

Changing the status can move the state (selecting a `closed`-state status
concludes the activity), and changing the state updates the status to that
state's default. External systems (Zendesk, Jira) sync against the state, with
status preserved where a mapping exists.

## Activity states

| State | Meaning |
|---|---|
| `open` | Active work; appears in open lists, triggers fire |
| `closed` | Concluded and archived; `onConclude` has run |
| `pending` | Awaiting review/acceptance (only when the app has a `review:` config) |
| `ejected` | Removed from the app's flow (internal; not a selectable status) |

## Built-in statuses

These status names are recognized everywhere. An app's `status` attribute can
use any subset, relabel them, or add custom ones (see below).

| Status | State | Typical label |
|---|---|---|
| `open` | open | Open |
| `in_progress` | open | In progress / Waiting for input |
| `on_hold` | open | On hold / Waiting for a third party |
| `pending` | pending | Pending review |
| `closed` | closed | Resolved / Closed |
| `duplicate` | closed | Duplicate |
| `rejected` | closed | Rejected |

A status with no explicit binding falls back to these defaults. When only the
state is known, the default status is `open`, `closed`, or `pending`
respectively.

## Custom statuses on the `status` attribute

The `status` attribute is a `select`. Each option may set `state:` to bind a
custom status name to a lifecycle state, and `external:` to map it to an
external system value (see [Attributes](https://conclude.io/doc/reference/attributes/#options-select-tag-button)).

```yaml
- name: status
  type: select
  label: Status
  visible: edit,conclude
  options:
    - name: open
      label: Open ticket
    - name: in_progress
      label: Waiting for input
      state: open
    - name: on_hold
      label: Waiting for a third party
    - name: closed
      label: Resolved        # no state: → defaults to the closed state
```

Resolution order for a status → state:
1. Built-in name (`open`, `closed`, `pending`) wins directly.
2. Otherwise the option's own `state:` field.
3. If neither resolves, the state is left unchanged.

## Zendesk mapping

Zendesk has six built-in ticket statuses. Conclude maps to them as follows.

| Zendesk status | Meaning | Reopenable? |
|---|---|---|
| `new` | Created, not yet triaged | — |
| `open` | Agent working on it | — |
| `pending` | Waiting on the requester | — |
| `hold` | Waiting on a third party (off by default in Zendesk) | — |
| `solved` | Resolved | Yes, by a customer reply within the retention window |
| `closed` | Archived | No — a follow-up ticket is created instead |

**Conclude → Zendesk:**

| Conclude status | Zendesk status |
|---|---|
| `open` | `open` |
| `in_progress` | `pending` |
| `on_hold` | `hold` |
| `closed` | `solved` |
| `duplicate` | `closed` |
| `rejected` | `closed` |
| `pending` | `pending` |
| (other / unknown) | `new` |

Closing maps to `solved`, not `closed`, so the Zendesk ticket can still be
reopened.

> **`closed` is terminal in Zendesk.** Once a ticket reaches `closed` it cannot
> be reopened; a customer reply spawns a linked follow-up ticket instead. This
> is why Conclude maps a concluded activity to `solved`, leaving the reopen
> window (e.g. a customer reply within 30 days) intact.

**Zendesk → Conclude:**

| Zendesk status | Conclude status |
|---|---|
| `open` | `open` |
| `pending` | `in_progress` |
| `hold` | `on_hold` |
| `solved` | `closed` |
| `closed` | `closed` |
| `new` (and other) | `open` |

An option's `external:` value overrides both directions: if a status option
sets `external: solved`, that option is used for the `solved` ↔ Conclude
mapping instead of the defaults above.

### `external:` override vs. the close event

Conclude pushes a status to Zendesk in two ways, and only one of them honors
the `external:` override:

- **Close/reopen events:** concluding always sends
  `solved`, reopening always sends `pending` — both hard-coded, regardless of
  any `external:` value.
- **Status-value sync** (used when the status attribute changes): honors the option's `external:` value, falling back to
  the table above.

These normally agree. They diverge only if a closed-state status option sets
`external: closed`: the status-value path would send the **terminal** `closed`
(no reopen window), while the close event still sends `solved`. Map a closed
state to `solved`, not `closed`, unless you deliberately want tickets to become
unreopenable.

## Jira mapping

Jira workflows differ per project, so Conclude maps against Jira's **status
category** (`To Do`, `In Progress`, `Done`) rather than specific status names.

**Jira → Conclude state:**

| Jira status category | Conclude state |
|---|---|
| `To Do` | open |
| `In Progress` | open |
| `Done` | closed |

**Conclude → Jira:** Conclude resolves a concrete Jira status by category for
the issue type, using the project's configured statuses:

| Conclude action | Jira status category |
|---|---|
| Open / reopen | `To Do` (falls back to `In Progress`) |
| In progress | `In Progress` |
| Conclude (close) | `Done` |

Because the mapping is category-based, a project that renames its statuses
(e.g. `Backlog`, `Selected for Development`, `Shipped`) still syncs correctly
as long as each status keeps its standard category.

### Typical Jira statuses

Conclude reads each status's `StatusCategory.Name`, so the status names below
are only examples — what matters is the category. Common statuses across Jira
workflows, grouped by the category they normally carry:

| Jira status | Usual category | Conclude state |
|---|---|---|
| Open | To Do | open |
| Reopened | To Do | open |
| Selected for Development | To Do | open |
| In Progress | In Progress | open |
| In Review | In Progress | open |
| Blocked | In Progress | open |
| Resolved | Done | closed |
| Closed | Done | closed |

Caveats — the list above mixes workflow templates, and category assignment is
configurable per project:

- **Open / Resolved / Reopened / Closed** are the classic company-managed
  default workflow. Team-managed projects default instead to bare `To Do` /
  `In Progress` / `Done` (status name = category name).
- **Selected for Development** and **In Review** come from the Scrum/Kanban
  board templates, not the base workflow.
- **Blocked** is almost always a *custom* status (or a flag), not a built-in,
  and an admin may file it under `To Do` instead of `In Progress`. Either way
  it stays open in Conclude.
- **Reopened** is legacy — newer Jira workflows drop the dedicated status and
  reopen straight back to `To Do` / `Open`.

The only practical consequence for Conclude: any `Done`-category status
(`Resolved`, `Closed`, `Done`, ...) closes the activity; everything else keeps
it open.

## See also

- [Attributes](https://conclude.io/doc/reference/attributes/#options-select-tag-button) — the `status`
  attribute, option `state:` and `external:` fields.
- [Connectors](https://conclude.io/doc/reference/connectors/) — Jira and Zendesk connector configuration.

