# Enabling "Work item Types" via REST API silently and permanently prevents the project from ever having the native Epic type

**URL:** <https://forum.plane.so/t/enabling-work-item-types-via-rest-api-silently-and-permanently-prevents-the-project-from-ever-having-the-native-epic-type/291>\
**Category:** Bug reports\
**Created:** [August 4, 2026, 9:46pm UTC](https://forum.plane.so/t/enabling-work-item-types-via-rest-api-silently-and-permanently-prevents-the-project-from-ever-having-the-native-epic-type/291 "2026-08-04T21:46:03Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![cleybson](https://forum.plane.so/letter_avatar_proxy/v4/letter/c/e68b1a/32.png) [@cleybson](https://forum.plane.so/u/cleybson)\
**Post date:** [August 4, 2026, 9:46pm UTC](https://forum.plane.so/t/enabling-work-item-types-via-rest-api-silently-and-permanently-prevents-the-project-from-ever-having-the-native-epic-type/291/1 "2026-08-04T21:46:03Z")

</div>

**# Enabling “Work item Types” via REST API silently and permanently prevents the project from ever having the native Epic type**

**\*\*Product:\*\*** Plane Cloud (`app.plane.so` / `api.plane.so`, API `v1`)

**\*\*Workspace:\*\*** `cortex-intelligence` (plan: Pro)

**\*\*Observed:\*\*** 2026-08-04

**\*\*Auth used:\*\*** Personal Access Token (`X-API-Key`)

**\*\*Severity (our view):\*\*** high — the resulting project state is unrecoverable and the API gives no error

-–

**## Summary**

Enabling the **\*\*Work item Types\*\*** feature produces a _\*different result\*_ depending on

whether it is done through the web UI or through the REST API:

| Enabled via | Types created | `POST /epics/` afterwards |

|—|—|—|

| Web UI (`Project settings \> Work item Types \> Enable`) | `Task` (level 0) **\*\*and `Epic` (level 1)\*\*** | `400` — epic feature is on |

| REST API (`PATCH /projects/{id}/ {“is_issue_type_enabled”: true}`) | **\*\*only `Task` (level 0)\*\*** | `404 {“error”:“Epic is not enabled for this project”}` |

Three properties combine to make this unrecoverable:

1. The API path never creates the level-1 `Epic` type.

2. The UI itself states **\*\*“Once enabled, Work item Types can’t be disabled.”\*\*** — so

the operator cannot turn it off and re-enable it correctly through the UI.

3. There is no API way to create a level-1 / `is_epic` type afterwards (details in

_\*What we tried\*_, below). `POST /work-item-types/` accepts `level: 1` and

`is_epic: true`, returns `201`, and stores `level=0, is_epic=false`.

Net effect: \*\*a single API call permanently removes the ability to use native Epics

in that project\*\*, and it does so without any error, warning, or difference in the

project resource. The only recovery we found is to delete the project and recreate it.

**## Why this matters to us**

We provision Plane projects as code (idempotent plan/apply script over API v1) so

that every team’s project is born with the same structure: work item types, custom

properties, labels, states, modules, cycles and saved views. In our model the native

**\*\*Epic (level 1) is the monitored unit\*\*** — it carries the 7 custom properties our

rules engine reads (owner, sponsor, health, original due date, blocked reason, etc.).

Because our script enabled Work item Types over the API — the natural thing to do in

an automated provisioning flow — every project it created was silently left without

Epics, and could not be fixed after the fact. We only found out by diffing a

UI-created project against an API-created one.

**## Steps to reproduce**

Controlled experiment, two brand-new empty projects in the same workspace. Both start

identical: `is_issue_type_enabled: false`, zero work item types,

`POST /epics/` → `404`.

**\*\*Group A — enable through the UI\*\***

1. Create project `teste2` (UI or API).

2. Open `Project settings \> Work item Types` and click **\*\*Enable\*\*** (confirm the

“can’t be disabled” dialog).

3. `GET /api/v1/workspaces/{slug}/projects/{project_id}/work-item-types/`

Result: **\*\*2 types\*\*** — `Task` (level 0) and `Epic` (level 1, `is_epic: true`).

**\*\*Group B — enable through the API\*\***

1. Create project `teste3`.

2. `PATCH /api/v1/workspaces/{slug}/projects/{project_id}/` with

`{“is_issue_type_enabled”: true}` → `200`.

3. `GET …/work-item-types/`

Result: **\*\*1 type\*\*** — `Task` (level 0) only. Re-read after 4s and after 16s to rule

out asynchronous creation: still only `Task`.

**## Evidence**

Project ids replaced with `\<project_id:NAME\>`; everything else is verbatim.

**### E1 — Types after enabling: UI vs API**

```

GET /api/v1/workspaces/{slug}/projects/\<project\_id:TESTE2\>/work-item-types/ [enabled via UI]

→ 200 2 type(s): {name:“Task”, level:0, is\_epic:false}, {name:“Epic”, level:1, is\_epic:true}

GET /api/v1/workspaces/{slug}/projects/\<project\_id:TESTE3\>/work-item-types/ [enabled via API]

→ 200 1 type(s): {name:“Task”, level:0, is\_epic:false}

```

**### E2 — The project resource does not record the difference**

```

TESTE2 (UI) : is\_issue\_type\_enabled=true … is\_member=true issue\_views\_view=true page\_view=true intake\_view=false is\_voting\_enabled=true

TESTE3 (API): is\_issue\_type\_enabled=true … is\_member=true issue\_views\_view=true page\_view=true intake\_view=false is\_voting\_enabled=true

```

`is_issue_type_enabled` is `true` on both, and no other boolean on the project

resource distinguishes them. (`cycle_view`/`module_view` differ only because our

script later enabled those on TESTE2; they are unrelated to this issue.) So an

automated flow has **\*\*no way to detect\*\*** that it landed in the broken state, other

than noticing that no level-1 type exists.

**### E3 — `POST /epics/` as a probe for the epic state**

```

POST …/projects/\<project\_id:TESTE2\>/epics/ {} [enabled via UI]

→ 400 {“name”:[“This field is required.”]} ← feature is ON (validation error)

POST …/projects/\<project\_id:TESTE3\>/epics/ {} [enabled via API]

→ 404 {“error”:“Epic is not enabled for this project”}

```

This confirms the server has a notion of “epic enabled for this project”, and that

the API-enabled project is not in it.

**### E4 — A level-1 (epic) type cannot be created via API: `201` but stored as level 0**

```

POST …/projects/\<project\_id:TESTE3\>/work-item-types/ {“name”:“EvidenceEpic1”,“level”:1,“is\_epic”:true}

→ 201 stored as: level=0 is\_epic=false (requested level=1 is\_epic=true)

PATCH …/work-item-types/{id}/ {“level”:1,“is\_epic”:true}

→ 200 stored as: level=0 is\_epic=false (silently ignored)

POST …/projects/\<project\_id:TESTE3\>/work-item-types/ {“name”:“EvidenceEpic2”,“level”:1,“is\_epic”:true,“is\_active”:true,“rollout”:“none”,“governance\_mode”:“any”}

→ 201 stored as: level=0 is\_epic=false (requested level=1 is\_epic=true)

```

The second payload copies every field of a real `Epic` type read from a working

project (`is_active`, `rollout`, `governance_mode`, `logo_props`). Both `level` and

`is_epic` are accepted and dropped, with a success status.

**### E5 — No feature field accepts an epic toggle**

```

PATCH …/projects/{id}/ {“is\_epic\_enabled”:true} → 200 field present in GET afterwards: false

PATCH …/projects/{id}/ {“epic\_view”:true} → 200 field present in GET afterwards: false

PATCH …/projects/{id}/ {“is\_epics\_enabled”:true} → 200 field present in GET afterwards: false

PATCH …/projects/{id}/ {“epics\_view”:true} → 200 field present in GET afterwards: false

PATCH …/projects/{id}/ {“is\_epic\_view\_enabled”:true} → 200 field present in GET afterwards: false

```

Every unknown field returns `200 OK` and changes nothing — see _\*Secondary issue\*_ below.

**### E6 — `import-work-item-types` is plan-gated**

```

OPTIONS …/projects/{id}/import-work-item-types/ → 405 allow=POST

POST …/projects/{id}/import-work-item-types/ {} → 402 {“error”:“Payment required”,“error\_code”:1999}

POST …/projects/{id}/import-work-item-types/ {“work\_item\_type\_ids”:[…]} → 402 {“error”:“Payment required”,“error\_code”:1999}

```

The route exists and only accepts POST, but returns `402` for every payload shape,

including an empty one — so it is gated before validation and cannot be used as a

recovery path on our plan.

**### E7 — The internal route the web app uses rejects a PAT**

```

GET /api/workspaces/{slug}/projects/{id}/work-item-types/ (no /v1 segment)

→ 401 {“detail”:“Authentication credentials were not provided.”}

```

So we cannot replicate whatever call the UI’s **\*\*Enable\*\*** button performs.

**### E8 — UI copy that closes the loop**

- `Project settings \> Work item Types` (before enabling), confirmation dialog:

**\*\*“Once enabled, Work item Types can’t be disabled.”\*\***

- `Project settings \> Features \> Epics` (current builds): the page has **\*\*no toggle\*\*** ,

only the notice \*"Epics now live under Work Item Types. Configure epic properties,

layouts, and defaults from the Work Item Types page. Your existing epics aren’t

affected."\* This makes the state look enabled when it is not, and gives an operator

no way to fix an affected project.

**## What we tried (all failed)**

| Attempt | Result |

|—|—|

| `PATCH` project with 5 candidate epic feature fields (E5) | `200`, silently ignored |

| `POST /work-item-types/` with `level:1, is_epic:true` (E4) | `201`, stored as level 0 |

| Same, with the full field set copied from a working Epic type | `201`, stored as level 0 |

| `PATCH` an existing type to `level:1, is_epic:true` | `200`, ignored |

| Invented shapes (`{“type”:“EPIC”}`, `{“kind”:“epic”}`) | `201`, plain level-0 type |

| `POST /projects/{id}/import-work-item-types/` (E6) | `402 Payment required` (`error_code 1999`) |

| Internal (non-`/v1`) route with PAT (E7) | `401` |

| Waiting for async creation (4s, 16s) | no change |

| `GET /projects/{id}/epics/` as a detection probe | returns `200` + empty list whether the feature is on or off; only `POST` distinguishes |

**## Expected behavior**

Any one of these would resolve it, in our order of preference:

1. **\*\*`PATCH is_issue_type_enabled: true` should create the same types the UI creates\*\***

(`Task` **\*\*and\*\*** `Epic`). Same feature, same outcome, regardless of client.

2. Expose a documented way to enable epics for a project via API v1 — either a real

project field (e.g. `is_epic_enabled`) that is readable _\*and\*_ writable, or an

endpoint such as `POST /projects/{id}/epics/enable/`.

3. Allow `POST /work-item-types/` to honour `level: 1` / `is_epic: true` — or reject

it with `400` instead of returning `201` and silently downgrading to level 0.

4. At minimum: make the project resource expose the epic state so automation can

_\*detect\*_ the broken state, and make it recoverable without deleting the project.

**## Secondary issue: unknown fields are silently accepted**

`PATCH /projects/{id}/` returns `200 OK` for fields that do not exist on the

serializer (E5), changing nothing. The same applies to `level` / `is_epic` on work

item types (E4). This turns every typo and every version drift into a silent no-op:

we only discovered the original problem because we re-read the resource after every

write. Returning `400` for unknown or non-writable fields would have surfaced all of

this immediately.

**## Workaround we adopted**

Our provisioning script no longer writes `is_issue_type_enabled` at all. It only

**\*\*reads\*\*** it, and stops with an instruction when the feature is off:

_\> Work item Types is disabled. Do_ **\*\*not\*\*** _enable it via API: the PATCH creates only_

_\> the `Task` type, while enabling through the UI creates `Task` + `Epic` — and since_

_\> the feature cannot be disabled afterwards, enabling it here leaves the project_

_\> permanently without the native Epic. Enable it in_

_\> `Project settings \> Work item Types \> Enable`, then re-run._

So the required order for a new project is: create the project → \*\*enable Work item

Types in the UI (human step)\*\* → run the automation, which does everything else. We

would very much like to remove that human step.

**## Questions**

1. Is the UI’s **\*\*Enable\*\*** action expected to create the `Epic` type as a side effect?

If so, can the API path be made to do the same?

2. Is there any supported way, on the Pro plan, to add native Epics to a project that

was enabled through the API — without deleting and recreating the project?

3. Is `import-work-item-types` intended to be plan-gated (`402`), and which plan

includes it?

4. Does `Features \> Epics` still have a toggle in any current build, or has it been

fully replaced by the Work Item Types page?

Someone can help me with this???  
I am running tests to adopt the tool at our company, but this is a blocker for proceeding with the purchase.

I need to be able to enable this via the API, just as I can through the UI.

Additionally, I noticed that I cannot manipulate or update project pages via the API; that is also a major issue.

---

<div class="post-metadata">

**Author:** ![imHarsha](https://forum.plane.so/letter_avatar_proxy/v4/letter/i/bb73d2/32.png) [@imHarsha](https://forum.plane.so/u/imHarsha)\
**Post date:** [August 5, 2026, 1:50pm UTC](https://forum.plane.so/t/enabling-work-item-types-via-rest-api-silently-and-permanently-prevents-the-project-from-ever-having-the-native-epic-type/291/2 "2026-08-05T13:50:07Z")

</div>

Thanks for the detailed writeup, @cleybson

Yes, enabling Work Item Types through the API should create the Epic type as well. We’ve identified the issue and our team is working on a fix.

As for adding native Epic to projects where Work Item Types was enabled via API, we’re working out how to approach this holistically and will get back to you on this.

[Import Work Item Types](https://docs.plane.so/work-items/workspace-work-item-types#import-types-into-a-project) is an Enterprise Grid plan feature. [Epics](https://docs.plane.so/core-concepts/issues/epics#epics) are now found under Work Item Types, and the toggle can be accessed via Work Item Types \> Epic.
