---
canonical_url: "https://docs.composio.dev/reference/api-reference/toolkits/postCustomToolkits"
markdown_url: "https://docs.composio.dev/reference/api-reference/toolkits/postCustomToolkits.md"
product: "platform"
version: "3.1"
last_updated: null
---

# Create a custom toolkit

**Documentation:** /reference/api-reference/toolkits/postCustomToolkits

> **API version:** This page documents Composio REST API v3.1, the current version, at `https://backend.composio.dev/api/v3.1`. `https://backend.composio.dev/api/v3` is the previous version and remains supported.

Experimental: this endpoint may change. Creates a custom MCP toolkit and returns its slug. Set user_id to "all" to share the toolkit with every user in the project, or to a user ID to make it private to that user ("default" and other spellings of "all" are rejected). Access cannot be changed later. For a private toolkit, the response can include a connect_link to send that user to.

---

## POST `/api/v3.1/custom/toolkits`

**Endpoint:** `https://backend.composio.dev/api/v3.1/custom/toolkits`

**Summary:** Create a custom toolkit

Experimental: this endpoint may change. Creates a custom MCP toolkit and returns its slug. Set user_id to "all" to share the toolkit with every user in the project, or to a user ID to make it private to that user ("default" and other spellings of "all" are rejected). Access cannot be changed later. For a private toolkit, the response can include a connect_link to send that user to.

### Authentication

**ApiKeyAuth** - API Key in `header` header `x-api-key` OR **UserApiKeyAuth** - API Key in `header` header `x-user-api-key`

### Request Body

Toolkit to create

**Schema:**

- `name` (string) *(required)*: Display name of the toolkit
- `app_url` (string (uri)) *(required)*: MCP server URL. Must use https.
- `logo_file` (object): Square PNG or JPEG logo, 256-1024px, max 3MB. Defaults to the Model Context Protocol logo.
  - `content` (string) *(required)*: Base64-encoded image, max 3MB decoded
  - `mime_type` (enum: "image/png" | "image/jpeg") *(required)*: Image MIME type
- `auth_schemes` (array<any>) *(required)*: How users authenticate to the MCP server
- `user_id` (any) *(required)*: "all" to share the toolkit with every user in the project, or a user ID to make it private to that user. "default" and other spellings of "all" (such as "ALL" or " all") are rejected. Cannot be changed after create.
- `callback_url` (string (uri)): URL to send the user to after they connect. Used only for connect_link.

**Example:**

```json
{
  "name": "string",
  "app_url": "https://example.com",
  "logo_file": {
    "content": "string",
    "mime_type": "image/png"
  },
  "auth_schemes": [
    {
      "mode": "..."
    }
  ],
  "user_id": "all",
  "callback_url": "https://example.com"
}
```

### Responses

#### 200 - Successfully created toolkit

**Response Schema:**

- `slug` (string) *(required)*: Slug of the created toolkit
- `connect_link` (object,null) *(required)*: Link for a private toolkit's user to connect. Null for shared or no-auth toolkits, or if the link could not be created. To retry, call POST /api/v3.1/connected_accounts/link with an auth config for the toolkit, creating one with POST /api/v3.1/auth_configs if needed.

**Example Response:**

```json
{
  "slug": "string",
  "connect_link": null
}
```

#### 400 - Bad request - Invalid parameters

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

#### 401 - Unauthorized - Invalid or missing credentials

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

#### 403 - Forbidden - Your role cannot create custom toolkits

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

#### 408 - Request timeout

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

#### 409 - Conflict - This user already has a private toolkit for this MCP URL

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

#### 429 - Too many requests - Retry after a short backoff

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

#### 500 - Internal server error - Failed to create toolkit

**Response Schema:**

- `error` (object) *(required)*
  - `message` (string) *(required)*
  - `code` (number) *(required)*
  - `slug` (string) *(required)*
  - `status` (number) *(required)*
  - `request_id` (string)
  - `suggested_fix` (string)
  - `errors` (array<string>)

### Example requests

Python uses `requests`; TypeScript uses Node.js fetch. Replace sample IDs and values before sending these requests.

Set `COMPOSIO_API_KEY` before running these requests.

#### Python

```python
import os
import requests
import json

response = requests.request("POST", "https://backend.composio.dev/api/v3.1/custom/toolkits",
    headers={"Content-Type": "application/json", "x-api-key": os.environ["COMPOSIO_API_KEY"]},
    json=json.loads("{\"name\":\"string\",\"app_url\":\"https://example.com\",\"logo_file\":{\"content\":\"string\",\"mime_type\":\"image/png\"},\"auth_schemes\":[{\"mode\":\"...\"}],\"user_id\":\"all\",\"callback_url\":\"https://example.com\"}"))
response.raise_for_status()
print(response.text)
```

#### TypeScript

```typescript
const response = await fetch("https://backend.composio.dev/api/v3.1/custom/toolkits", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-api-key": process.env["COMPOSIO_API_KEY"]! },
  body: JSON.stringify({
  "name": "string",
  "app_url": "https://example.com",
  "logo_file": {
    "content": "string",
    "mime_type": "image/png"
  },
  "auth_schemes": [
    {
      "mode": "..."
    }
  ],
  "user_id": "all",
  "callback_url": "https://example.com"
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.text());
```

#### API

```bash
curl -X POST "https://backend.composio.dev/api/v3.1/custom/toolkits" \
  -H "x-api-key: $COMPOSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "app_url": "https://example.com",
    "logo_file": {
      "content": "string",
      "mime_type": "image/png"
    },
    "auth_schemes": [
      {
        "mode": "..."
      }
    ],
    "user_id": "all",
    "callback_url": "https://example.com"
  }'
```

---

## REST API version

The current REST API version is **v3.1**, served at `https://backend.composio.dev/api/v3.1`. Prefer it for new code and new examples.

`https://backend.composio.dev/api/v3` is the previous version. It is frozen with pinned tool-version defaults and remains supported — existing v3 integrations keep working and do not need to migrate.