# Identity: integrations

> The integrations this identity has connected, and whether each is healthy; Connect an MCP server: a catalogue entry in one click, or any server by its URL (SPEC §6.1-§6.4); Start the upstream OAuth ceremony and hand back the URL to send the owner to; What this integration offers, and what it could o

## The integrations this identity has connected, and whether each is healthy

`GET /v1/identities/{slug}/integrations` · operation `listIntegrations`

Requires the `batondeck:identities:read` permission (action `identity:read`).

**Parameters**

| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| `slug` | path | string | yes |  |

**Responses**

| Status | Meaning |
|---|---|
| 200 | The integrations this identity has connected, and whether each is healthy |
| 401 | No portal session, and no live API key. |
| 403 | The policy refused, or the request was cross-site. |
| 404 | No such resource, or none this session may see. |

<details>
<summary>200 response schema</summary>

```json
{
  "type": "object",
  "properties": {
    "integrations": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "transport": {
            "type": "string"
          },
          "endpoint": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "permission": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "slug",
          "transport",
          "endpoint",
          "status",
          "permission"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "integrations"
  ],
  "additionalProperties": false
}
```

</details>

```sh
curl -X GET 'https://api.batondeck.com/v1/identities/:slug/integrations' \
  -H "Authorization: Bearer $BATONDECK_API_KEY"
```


## Connect an MCP server: a catalogue entry in one click, or any server by its URL (SPEC §6.1-§6.4)

`POST /v1/identities/{slug}/integrations` · operation `createIntegration`

Requires the `batondeck:identities:manage` permission (action `integration:write`).

Refused while the workspace is suspended or on deletion hold.

**Parameters**

| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| `slug` | path | string | yes |  |

**Request body** (`application/json`)

| Field | Type | Required | Notes |
|---|---|---|---|
| `catalogue` | string |  | ≤ 64 chars |
| `slug` | string |  | ≥ 2 chars, ≤ 32 chars |
| `endpoint` | string |  |  |
| `transport` | "streamable-http" \\| "sse" |  |  |
| `auth` | object \\| null |  |  |

<details>
<summary>Request schema</summary>

```json
{
  "type": "object",
  "properties": {
    "catalogue": {
      "type": "string",
      "maxLength": 64
    },
    "slug": {
      "type": "string",
      "minLength": 2,
      "maxLength": 32
    },
    "endpoint": {
      "type": "string",
      "format": "uri"
    },
    "transport": {
      "type": "string",
      "enum": [
        "streamable-http",
        "sse"
      ]
    },
    "auth": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "header": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "value": {
              "type": "string",
              "minLength": 1,
              "maxLength": 4096
            }
          },
          "required": [
            "header",
            "value"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}
```

</details>

**Responses**

| Status | Meaning |
|---|---|
| 201 | Connect an MCP server: a catalogue entry in one click, or any server by its URL (SPEC §6.1-§6.4) |
| 400 | The arguments did not validate. |
| 401 | No portal session, and no live API key. |
| 403 | The policy refused, or the request was cross-site. |
| 404 | No such resource, or none this session may see. |

<details>
<summary>201 response schema</summary>

```json
{
  "type": "object",
  "properties": {
    "integration": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "slug": {
          "type": "string"
        },
        "transport": {
          "type": "string"
        },
        "endpoint": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "permission": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "slug",
        "transport",
        "endpoint",
        "status",
        "permission"
      ],
      "additionalProperties": false
    },
    "tools": {
      "type": "number"
    },
    "trouble": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "authorization_url": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "integration",
    "tools",
    "trouble",
    "authorization_url"
  ],
  "additionalProperties": false
}
```

</details>

```sh
curl -X POST 'https://api.batondeck.com/v1/identities/:slug/integrations' \
  -H "Authorization: Bearer $BATONDECK_API_KEY" \
  -H 'content-type: application/json' \
  -d @body.json
```


## Start the upstream OAuth ceremony and hand back the URL to send the owner to

`POST /v1/identities/{slug}/integrations/{name}/authorize` · operation `authorizeIntegration`

Requires the `batondeck:identities:manage` permission (action `integration:write`).

Refused while the workspace is suspended or on deletion hold.

**Parameters**

| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| `slug` | path | string | yes |  |
| `name` | path | string | yes |  |

**Request body** (`application/json`)

| Field | Type | Required | Notes |
|---|---|---|---|
| `scope` | string |  | ≤ 512 chars |

<details>
<summary>Request schema</summary>

```json
{
  "type": "object",
  "properties": {
    "scope": {
      "type": "string",
      "maxLength": 512
    }
  },
  "additionalProperties": false
}
```

</details>

**Responses**

| Status | Meaning |
|---|---|
| 200 | Start the upstream OAuth ceremony and hand back the URL to send the owner to |
| 400 | The arguments did not validate. |
| 401 | No portal session, and no live API key. |
| 403 | The policy refused, or the request was cross-site. |
| 404 | No such resource, or none this session may see. |

<details>
<summary>200 response schema</summary>

```json
{
  "type": "object",
  "properties": {
    "authorization_url": {
      "type": "string"
    }
  },
  "required": [
    "authorization_url"
  ],
  "additionalProperties": false
}
```

</details>

```sh
curl -X POST 'https://api.batondeck.com/v1/identities/:slug/integrations/:name/authorize' \
  -H "Authorization: Bearer $BATONDECK_API_KEY" \
  -H 'content-type: application/json' \
  -d @body.json
```


## What this integration offers, and what it could offer (SPEC §6.5)

`GET /v1/identities/{slug}/integrations/{name}/exposure` · operation `getExposure`

Requires the `batondeck:identities:read` permission (action `identity:read`).

**Parameters**

| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| `slug` | path | string | yes |  |
| `name` | path | string | yes |  |

**Responses**

| Status | Meaning |
|---|---|
| 200 | What this integration offers, and what it could offer (SPEC §6.5) |
| 401 | No portal session, and no live API key. |
| 403 | The policy refused, or the request was cross-site. |
| 404 | No such resource, or none this session may see. |

<details>
<summary>200 response schema</summary>

```json
{
  "type": "object",
  "properties": {
    "catalog": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "entries": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "version": {
      "type": "number"
    },
    "stale": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "catalog",
    "entries",
    "version",
    "stale"
  ],
  "additionalProperties": false
}
```

</details>

```sh
curl -X GET 'https://api.batondeck.com/v1/identities/:slug/integrations/:name/exposure' \
  -H "Authorization: Bearer $BATONDECK_API_KEY"
```


## Replace which of an integration's tools contacts may reach

`POST /v1/identities/{slug}/integrations/{name}/exposure` · operation `setExposure`

Requires the `batondeck:identities:manage` permission (action `integration:write`).

Refused while the workspace is suspended or on deletion hold.

**Parameters**

| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| `slug` | path | string | yes |  |
| `name` | path | string | yes |  |

**Request body** (`application/json`)

| Field | Type | Required | Notes |
|---|---|---|---|
| `entries` | array of object | yes |  |

<details>
<summary>Request schema</summary>

```json
{
  "type": "object",
  "properties": {
    "entries": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "tool": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "passthrough",
              "mapped",
              "agent"
            ]
          }
        },
        "required": [
          "tool",
          "mode"
        ],
        "additionalProperties": {}
      }
    }
  },
  "required": [
    "entries"
  ],
  "additionalProperties": false
}
```

</details>

**Responses**

| Status | Meaning |
|---|---|
| 200 | Replace which of an integration's tools contacts may reach |
| 400 | The arguments did not validate. |
| 401 | No portal session, and no live API key. |
| 403 | The policy refused, or the request was cross-site. |
| 404 | No such resource, or none this session may see. |

<details>
<summary>200 response schema</summary>

```json
{
  "type": "object",
  "properties": {
    "version": {
      "type": "number"
    }
  },
  "required": [
    "version"
  ],
  "additionalProperties": false
}
```

</details>

```sh
curl -X POST 'https://api.batondeck.com/v1/identities/:slug/integrations/:name/exposure' \
  -H "Authorization: Bearer $BATONDECK_API_KEY" \
  -H 'content-type: application/json' \
  -d @body.json
```


## Disconnect an upstream and forget its credential

`DELETE /v1/identities/{slug}/integrations/{name}` · operation `deleteIntegration`

Requires the `batondeck:identities:manage` permission (action `integration:write`).

Refused while the workspace is suspended or on deletion hold.

**Parameters**

| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| `slug` | path | string | yes |  |
| `name` | path | string | yes |  |

**Responses**

| Status | Meaning |
|---|---|
| 200 | Disconnect an upstream and forget its credential |
| 401 | No portal session, and no live API key. |
| 403 | The policy refused, or the request was cross-site. |
| 404 | No such resource, or none this session may see. |

<details>
<summary>200 response schema</summary>

```json
{
  "type": "null"
}
```

</details>

```sh
curl -X DELETE 'https://api.batondeck.com/v1/identities/:slug/integrations/:name' \
  -H "Authorization: Bearer $BATONDECK_API_KEY"
```
