> For the complete documentation index, see [llms.txt](https://docs.api.intratool.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.api.intratool.de/api-reference/menu/menu-items.md).

# MenuItems

## Introduction

`MenuItems` configure additional navigation entries with translated labels, access restrictions, system-variable links, and iframe behavior.

## Model Definition

**Alias**

`menuItem`

**Capabilities**

* [Entity Permissions](/introduction/resource-capabilities/entity-permissions.md) - Restrict which users receive the item.
* [Translations](/introduction/resource-capabilities/translations.md) - Localizes `title`; examples use `en-US`.

## List

List visible `MenuItems`.

**Definition**

<mark style="color:green;">`GET`</mark> `/api/menu/items`

**Request Keys**

| Key         | Type      | Default           | Description                          |
| ----------- | --------- | ----------------- | ------------------------------------ |
| `selects`   | `string`  | All fields        | Comma-separated fields to return.    |
| `relations` | `string`  | Default relations | Pipe-separated relations to include. |
| `limit`     | `integer` | No limit          | Maximum number of items.             |

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('GET', '/api/menu/items', [
    'headers' => ['Authorization' => "Bearer {accessToken}"]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
[
  {
    "id": 15,
    "lang_id": "en-US",
    "icon_id": 44,
    "menu_identifier": "help-center",
    "type": "default",
    "title": "Help Center",
    "link": "https://help.example.com/users/{{ system.user.id }}",
    "allow_iframe_access": true,
    "iframe_access": true,
    "user_confirmation_required": false,
    "sort_number": 1
  },
  {
    "id": 16,
    "lang_id": "en-US",
    "icon_id": 51,
    "menu_identifier": "expense-tool",
    "type": "integration",
    "title": "Expense Tool",
    "link": "https://expenses.example.com/menu-items/{{ menuItem.id }}/users/{{ system.user.id }}",
    "allow_iframe_access": false,
    "iframe_access": false,
    "user_confirmation_required": true,
    "sort_number": 2
  }
]
```

## Show

Show one visible `MenuItem`.

**Definition**

<mark style="color:green;">`GET`</mark> `/api/menu/items/{menuItem}`

**Route Parameters**

| Parameter  | Type      | Description   |
| ---------- | --------- | ------------- |
| `menuItem` | `integer` | Menu item ID. |

**Request Keys**

| Key         | Type     | Default           | Description                          |
| ----------- | -------- | ----------------- | ------------------------------------ |
| `selects`   | `string` | All fields        | Comma-separated fields to return.    |
| `relations` | `string` | Default relations | Pipe-separated relations to include. |

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('GET', '/api/menu/items/15', [
    'headers' => ['Authorization' => "Bearer {accessToken}"]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
{
  "id": 15,
  "lang_id": "en-US",
  "icon_id": 44,
  "menu_identifier": "help-center",
  "type": "default",
  "title": "Help Center",
  "link": "https://help.example.com/users/{{ system.user.id }}",
  "allow_iframe_access": true,
  "iframe_access": true,
  "user_confirmation_required": false,
  "sort_number": 1
}
```

## Admin: List

List all `MenuItems` in administration scope.

**Definition**

<mark style="color:green;">`GET`</mark> `/api/administration/menu/items`

**Request Keys**

| Key         | Type      | Default           | Description                          |
| ----------- | --------- | ----------------- | ------------------------------------ |
| `selects`   | `string`  | All fields        | Comma-separated fields to return.    |
| `relations` | `string`  | Default relations | Pipe-separated relations to include. |
| `limit`     | `integer` | No limit          | Maximum number of items.             |

**Behavior**

Administration results include soft-deleted items.

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('GET', '/api/administration/menu/items', [
    'headers' => ['Authorization' => "Bearer {accessToken}"]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
[
  {
    "id": 15,
    "lang_id": "en-US",
    "icon_id": 44,
    "menu_identifier": "help-center",
    "type": "default",
    "title": "Help Center",
    "link": "https://help.example.com/users/{{ system.user.id }}",
    "allow_iframe_access": true,
    "iframe_access": true,
    "user_confirmation_required": false,
    "sort_number": 1
  },
  {
    "id": 16,
    "lang_id": "en-US",
    "icon_id": 51,
    "menu_identifier": "expense-tool",
    "type": "integration",
    "title": "Expense Tool",
    "link": "https://expenses.example.com/menu-items/{{ menuItem.id }}/users/{{ system.user.id }}",
    "allow_iframe_access": false,
    "iframe_access": false,
    "user_confirmation_required": true,
    "sort_number": 2,
    "deleted_at": "2026-08-03 09:00:00"
  }
]
```

## Admin: Show

Show one `MenuItem` in administration scope.

**Definition**

<mark style="color:green;">`GET`</mark> `/api/administration/menu/items/{menuItem}`

**Route Parameters**

| Parameter  | Type      | Description   |
| ---------- | --------- | ------------- |
| `menuItem` | `integer` | Menu item ID. |

**Request Keys**

| Key         | Type     | Default           | Description                          |
| ----------- | -------- | ----------------- | ------------------------------------ |
| `selects`   | `string` | All fields        | Comma-separated fields to return.    |
| `relations` | `string` | Default relations | Pipe-separated relations to include. |

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('GET', '/api/administration/menu/items/16', [
    'headers' => ['Authorization' => "Bearer {accessToken}"]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
{
  "id": 16,
  "lang_id": "en-US",
  "icon_id": 51,
  "menu_identifier": "expense-tool",
  "type": "integration",
  "title": "Expense Tool",
  "link": "https://expenses.example.com/menu-items/{{ menuItem.id }}/users/{{ system.user.id }}",
  "allow_iframe_access": false,
  "iframe_access": false,
  "user_confirmation_required": true,
  "sort_number": 2
}
```

## Admin: Create

Create a new `MenuItem`.

**Definition**

<mark style="color:yellow;">`POST`</mark> `/api/administration/menu/items`

**Request Keys**

| Key                          | Type      | Default         | Description                                                                      |
| ---------------------------- | --------- | --------------- | -------------------------------------------------------------------------------- |
| `lang_id`                    | `string`  | System language | Language key. Use `en-US` for this example.                                      |
| `icon_id`\*                  | `integer` | -               | Icon ID.                                                                         |
| `menu_identifier`\*          | `string`  | -               | Stable client identifier.                                                        |
| `type`\*                     | `string`  | -               | Menu item type.                                                                  |
| `title`\*                    | `string`  | -               | Visible label.                                                                   |
| `link`\*                     | `string`  | -               | URL or [system-variable](/introduction/system-variables.md) template.            |
| `allow_iframe_access`        | `boolean` | `true`          | Allow eligible URLs to open inside intratool.                                    |
| `user_confirmation_required` | `boolean` | `false`         | Require confirmation before opening.                                             |
| `sort_number`                | `integer` | Auto            | Display order.                                                                   |
| `entity_permissions`         | `object`  | Unrestricted    | [Entity Permissions](/introduction/resource-capabilities/entity-permissions.md). |

Keys with `*` are required.

**Behavior**

`iframe_access` is calculated by the server from `allow_iframe_access` and whether the resolved URL supports embedding. The example link contains all context used by the resolved navigation URL.

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('POST', '/api/administration/menu/items', [
    'headers' => ['Authorization' => "Bearer {accessToken}"],
    'json' => [
        'lang_id' => 'en-US',
        'icon_id' => 51,
        'menu_identifier' => 'expense-tool',
        'type' => 'integration',
        'title' => 'Expense Tool',
        'link' => 'https://expenses.example.com/menu-items/{{ menuItem.id }}/users/{{ system.user.id }}',
        'allow_iframe_access' => false,
        'user_confirmation_required' => true,
        'sort_number' => 2
    ]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
{
  "status": "success",
  "data": {
    "id": 16,
    "lang_id": "en-US",
    "icon_id": 51,
    "menu_identifier": "expense-tool",
    "type": "integration",
    "title": "Expense Tool",
    "link": "https://expenses.example.com/menu-items/{{ menuItem.id }}/users/{{ system.user.id }}",
    "allow_iframe_access": false,
    "iframe_access": false,
    "user_confirmation_required": true,
    "sort_number": 2
  }
}
```

## Admin: Update

Update an existing `MenuItem`.

**Definition**

<mark style="color:blue;">`PUT`</mark> `/api/administration/menu/items/{menuItem}`

**Route Parameters**

| Parameter  | Type      | Description   |
| ---------- | --------- | ------------- |
| `menuItem` | `integer` | Menu item ID. |

**Request Keys**

| Key                          | Type      | Default       | Description                          |
| ---------------------------- | --------- | ------------- | ------------------------------------ |
| `lang_id`                    | `string`  | Current value | Language key.                        |
| `icon_id`                    | `integer` | Current value | Icon ID.                             |
| `menu_identifier`            | `string`  | Current value | Stable client identifier.            |
| `type`                       | `string`  | Current value | Menu item type.                      |
| `title`                      | `string`  | Current value | Visible label.                       |
| `link`                       | `string`  | Current value | URL or system-variable template.     |
| `allow_iframe_access`        | `boolean` | Current value | Allow eligible URLs in intratool.    |
| `user_confirmation_required` | `boolean` | Current value | Require confirmation before opening. |
| `sort_number`                | `integer` | Current value | Display order.                       |
| `entity_permissions`         | `object`  | Current value | Updated Entity Permissions.          |

**Behavior**

The server recalculates `iframe_access` whenever the link or iframe preference is updated.

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('PUT', '/api/administration/menu/items/16', [
    'headers' => ['Authorization' => "Bearer {accessToken}"],
    'json' => [
        'lang_id' => 'en-US',
        'title' => 'Travel and Expense Tool',
        'link' => 'https://expenses.example.com/users/{{ system.user.id }}',
        'allow_iframe_access' => true,
        'user_confirmation_required' => false
    ]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
{
  "status": "success",
  "data": {
    "id": 16,
    "lang_id": "en-US",
    "icon_id": 51,
    "menu_identifier": "expense-tool",
    "type": "integration",
    "title": "Travel and Expense Tool",
    "link": "https://expenses.example.com/users/{{ system.user.id }}",
    "allow_iframe_access": true,
    "iframe_access": false,
    "user_confirmation_required": false,
    "sort_number": 2
  }
}
```

## Admin: Delete

Delete an existing `MenuItem`.

**Definition**

<mark style="color:red;">`DELETE`</mark> `/api/administration/menu/items/{menuItem}`

**Route Parameters**

| Parameter  | Type      | Description   |
| ---------- | --------- | ------------- |
| `menuItem` | `integer` | Menu item ID. |

**Example Request**

{% tabs %}
{% tab title="PHP" %}

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://{tenant}.intratool.de']);
$response = $client->request('DELETE', '/api/administration/menu/items/16', [
    'headers' => ['Authorization' => "Bearer {accessToken}"]
]);
```

{% endtab %}
{% endtabs %}

**Example Response**

```json
{
  "status": "success",
  "data": null
}
```
