> For the complete documentation index, see [llms.txt](https://docs.acpt.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.acpt.io/integrations/abilities-api/taxonomies.md).

# Taxonomies

acpt/list-taxonomies, acpt/get-taxonomy, acpt/save-taxonomy, acpt/delete-taxonomy, acpt/assoc-taxonomy-post-type, acpt/remove-taxonomy-post-type-assoc

Category: `acpt-content-model` · Default capability: `manage_options`

| Ability                                | What it does                                                 |
| -------------------------------------- | ------------------------------------------------------------ |
| `acpt/list-taxonomies`                 | Returns every custom taxonomy registered via ACPT            |
| `acpt/get-taxonomy`                    | Returns a single taxonomy by slug                            |
| `acpt/save-taxonomy`                   | Creates a taxonomy, or updates it if the slug already exists |
| `acpt/delete-taxonomy`                 | Deletes a taxonomy definition                                |
| `acpt/assoc-taxonomy-post-type`        | Attaches an existing taxonomy to an existing post type       |
| `acpt/remove-taxonomy-post-type-assoc` | Detaches a taxonomy from a post type                         |

{% hint style="warning" %}
**The singular/plural label keys are named differently on input vs. output.** `acpt/get-taxonomy` and `acpt/list-taxonomies` return `singular`/`plural`, but `acpt/save-taxonomy` expects `singular_label`/`plural_label`. This mirrors an existing naming inconsistency between ACPT's stored taxonomy model and its `register_acpt_taxonomy()` PHP function — each ability uses whichever names its underlying operation actually expects, so copy-pasting a `get`/`list` response straight into a `save` call won't work for these two fields.
{% endhint %}

## acpt/list-taxonomies

No input required.

```php
$result = wp_get_ability('acpt/list-taxonomies')->execute();
```

## acpt/get-taxonomy

**Input**

| Property | Type   | Required | Description       |
| -------- | ------ | -------- | ----------------- |
| `slug`   | string | Yes      | The taxonomy slug |

```php
$result = wp_get_ability('acpt/get-taxonomy')->execute([
    'slug' => 'genre',
]);
```

```json
{
  "success": true,
  "message": "Operation completed successfully.",
  "data": {
    "id": "5f1c2e3a-1234-4a1b-9c2d-abcdef123456",
    "slug": "genre",
    "singular": "Genre",
    "plural": "Genres",
    "postCount": 0,
    "isNative": false,
    "labels": { "name": "Genre" },
    "settings": { "public": true, "hierarchical": false },
    "customPostTypes": [],
    "permissions": []
  }
}
```

## acpt/save-taxonomy

**Input**

| Property         | Type           | Required | Notes                                                                                                                                                                                                                                                        |
| ---------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `slug`           | string         | Yes      | Max 32 characters. If a taxonomy with this slug already exists, it's **updated** instead of duplicated                                                                                                                                                       |
| `singular_label` | string         | Yes      |                                                                                                                                                                                                                                                              |
| `plural_label`   | string         | Yes      |                                                                                                                                                                                                                                                              |
| `labels`         | object         | No       | Any subset of WordPress's [taxonomy labels](https://developer.wordpress.org/reference/functions/register_taxonomy/) (`name`, `singular_name`, `search_items`, …). Defaults to a full set derived from `singular_label`/`plural_label` if omitted — see below |
| `settings`       | object         | No       | Any subset of `register_taxonomy()`'s arguments — `public`, `hierarchical`, `show_ui`, `show_admin_column`, `rewrite`, `capabilities`, etc. Defaults to a full, working set if omitted — see below                                                           |
| `post_types`     | array\<string> | No       | Post type slugs to attach this taxonomy to immediately                                                                                                                                                                                                       |
| `permissions`    | array          | No       |                                                                                                                                                                                                                                                              |

```php
$result = wp_get_ability('acpt/save-taxonomy')->execute([
    'slug'           => 'genre',
    'singular_label' => 'Genre',
    'plural_label'   => 'Genres',
    'labels'         => ['name' => 'Genre'],
    'settings'       => ['public' => true, 'hierarchical' => false],
    'post_types'     => ['movie'],
]);
```

### Defaults when labels/settings are omitted

Same behavior as [custom post types](/integrations/abilities-api/custom-post-types.md#defaults-when-fields-are-omitted): omitting `labels`/`settings` entirely fills them in with the same values the admin UI's creation wizard pre-selects; sending an explicit empty value (`"labels": {}`/`"settings": {}`) is respected as a deliberately bare taxonomy instead.

| Field      | Default when omitted                                                                                                                                                                                                                                                                                                                                                          |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `labels`   | Derived from `singular_label`/`plural_label` — `add_new_item: "Add new {singular}"`, `search_items: "Search {plural}"`, `not_found: "No {singular} found"`, etc. (every label WordPress's `register_taxonomy()` accepts)                                                                                                                                                      |
| `settings` | `public: true`, `publicly_queryable: true`, `hierarchical: false`, `show_ui: true`, `show_in_menu: true`, `show_in_nav_menus: true`, `show_in_rest: true`, `show_tagcloud: true`, `show_in_quick_edit: true`, `show_admin_column: false`, `capabilities: ["manage_terms", "edit_terms", "delete_terms", "assign_terms"]`, `rewrite: false`, `query_var: false`, `sort: false` |

Note `rewrite`/`query_var` default to `false` here, unlike custom post types (where they default to `true`) — this matches the taxonomy creation wizard's own defaults, not an assumption of symmetry between the two.

## acpt/delete-taxonomy

**Input**

| Property | Type   | Required | Description                 |
| -------- | ------ | -------- | --------------------------- |
| `slug`   | string | Yes      | The taxonomy slug to delete |

```php
$result = wp_get_ability('acpt/delete-taxonomy')->execute([
    'slug' => 'genre',
]);
```

## acpt/assoc-taxonomy-post-type

Attaches an already-registered taxonomy to an already-registered post type. Neither is created if it doesn't exist — use `acpt/save-taxonomy` / `acpt/save-post-type` first.

**Input**

| Property    | Type   | Required |
| ----------- | ------ | -------- |
| `taxonomy`  | string | Yes      |
| `post_type` | string | Yes      |

```php
$result = wp_get_ability('acpt/assoc-taxonomy-post-type')->execute([
    'taxonomy'  => 'genre',
    'post_type' => 'movie',
]);
```

## acpt/remove-taxonomy-post-type-assoc

The reverse of `acpt/assoc-taxonomy-post-type` — detaches the taxonomy without deleting either the taxonomy or the post type. This ability is flagged as **destructive** in its Abilities API metadata (see [How it works → Read/write/destructive metadata](/integrations/abilities-api/how-it-works.md#readwritedestructive-metadata)).

**Input**

| Property    | Type   | Required |
| ----------- | ------ | -------- |
| `taxonomy`  | string | Yes      |
| `post_type` | string | Yes      |

```php
$result = wp_get_ability('acpt/remove-taxonomy-post-type-assoc')->execute([
    'taxonomy'  => 'genre',
    'post_type' => 'movie',
]);
```
