---
title: Plugins API
url: https://platform.claude.com/docs/ko/manage-claude/plugins-api
description: Claude Enterprise 조직의 플러그인 인벤토리를 파악하고 관리합니다. 플러그인과 버전을 업로드하고, 멤버에게 제공할 버전을 선택하고, 각 플러그인을 사용할 수 있는 사람을 제어하고, 검토를 위해 플러그인 파일을 다운로드하고, 마켓플레이스를 연결하기 전에 검증할 수 있습니다.
---

Plugins API를 사용하면 Claude Enterprise 조직의 모든 "plugin"(플러그인) 인벤토리를 파악하고, 자체 파이프라인에서 플러그인과 새 버전을 게시하고, 멤버에게 제공할 버전을 선택하고, 각 플러그인을 사용할 수 있는 사람을 제어하고, 검토를 위해 플러그인 파일을 다운로드하고, Git "marketplace"(마켓플레이스)를 연결하기 전에 확인할 수 있습니다.

플러그인 *사용량* 보고(멤버가 어떤 플러그인과 스킬을 얼마나 자주 사용하는지)에 대해서는 [Analytics API](https://platform.claude.com/docs/ko/manage-claude/analytics-api)를 참조하세요.

<Check>
  **범위가 지정된 Admin API 키 필요**

  이 엔드포인트를 사용하려면 `read:plugins` "scope"(범위)(아카이브 다운로드를 포함한 `GET` 엔드포인트의 경우) 또는 `write:plugins` 범위(`POST` 및 `DELETE` 엔드포인트의 경우. 단, 마켓플레이스 검증은 두 범위 모두 허용)를 가진 Admin API 키가 필요합니다. 함께 사용할 수 있는 다른 두 가지 읽기 범위를 포함한 자세한 내용은 [범위](https://platform.claude.com/docs/ko/manage-claude/plugins-api#scopes)를 참조하세요. 기본 소유자가 키를 생성하는 위치는 [Admin API 키 생성](https://platform.claude.com/docs/ko/manage-claude/admin-api-keys#create-a-key-for-a-claude-enterprise-organization)을 참조하세요. 모든 요청에서 `x-api-key` 헤더에 키를 전달하고, [`anthropic-version`](https://platform.claude.com/docs/ko/api/versioning) 헤더와 다음 참고에 표시된 베타 헤더를 함께 전달하세요.
</Check>

<Note>
  Plugins API는 **베타** 상태이며 Claude Enterprise 조직에서만 사용할 수 있습니다. Claude Platform(Claude Console) 조직이나 HIPAA 준비가 활성화된 조직에서는 사용할 수 없습니다.

  모든 요청에는 [베타 헤더](https://platform.claude.com/docs/ko/api/beta-headers) `anthropic-beta: ce-plugins-2026-09-01`이 포함되어야 합니다(SDK와 `ant` CLI는 이 헤더를 자동으로 전송합니다). 이 헤더가 없는 요청은 엔드포인트가 존재하지 않는 것과 똑같이 `404`를 반환합니다.
</Note>

## 엔드포인트

이 API는 5개 리소스에 걸쳐 18개의 엔드포인트를 제공합니다:

| 리소스                                                                                       | 엔드포인트                                                                                                                                                                                                                                                                                                                     |
| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **플러그인**: 조직의 모든 플러그인 나열, 새 플러그인 업로드, 플러그인 조회, 멤버에게 제공할 버전 선택(롤백 또는 승격), 플러그인 삭제          | `GET /v1/organizations/plugins`<br />`POST /v1/organizations/plugins`<br />`GET /v1/organizations/plugins/{plugin_id}`<br />`POST /v1/organizations/plugins/{plugin_id}`<br />`DELETE /v1/organizations/plugins/{plugin_id}`                                                                                              |
| **플러그인 버전**: 플러그인의 버전 기록 나열, 새 버전 업로드, 버전 조회, 버전 파일 다운로드                                  | `GET /v1/organizations/plugins/{plugin_id}/versions`<br />`POST /v1/organizations/plugins/{plugin_id}/versions`<br />`GET /v1/organizations/plugins/{plugin_id}/versions/{version}`<br />`GET /v1/organizations/plugins/{plugin_id}/versions/{version}/content`                                                           |
| **설치 설정**: 조직 소유 플러그인을 사용할 수 있는 사람 읽기, 조직 전체 또는 하나의 그룹에 대해 설정, 두 설정 중 하나 제거               | `GET /v1/organizations/plugins/{plugin_id}/installation_settings`<br />`POST /v1/organizations/plugins/{plugin_id}/installation_settings/{target}`<br />`DELETE /v1/organizations/plugins/{plugin_id}/installation_settings/{target}`                                                                                     |
| **공유**: 멤버가 자신의 플러그인을 누구와 공유했는지 읽기(읽기 전용)                                                 | `GET /v1/organizations/plugins/{plugin_id}/shares`                                                                                                                                                                                                                                                                        |
| **플러그인 마켓플레이스**: 마켓플레이스 ID 찾기, 마켓플레이스 조회, 해당 마켓플레이스 플러그인의 기본 설치 설정 지정, 연결 전 마켓플레이스 콘텐츠 확인 | `GET /v1/organizations/plugin_marketplaces`<br />`GET /v1/organizations/plugin_marketplaces/{marketplace_id}`<br />`POST /v1/organizations/plugin_marketplaces/{marketplace_id}`<br />`POST /v1/organizations/plugin_marketplaces/validate_repository`<br />`POST /v1/organizations/plugin_marketplaces/validate_archive` |

이번 릴리스에는 독립형 스킬(멤버가 claude.ai의 스킬 편집기에서 작성하거나 단일 스킬로 업로드한 스킬)이 포함되지 않습니다. 독립형 스킬은 인벤토리에 나타나지 않으며 여기서 생성할 수 없습니다. Anthropic이 게시하는 플러그인도 인벤토리에 포함되지 않으며, 그 사용량은 [Analytics API](https://platform.claude.com/docs/ko/manage-claude/analytics-api)에서 보고됩니다. 마켓플레이스의 생성, 저장소 연결, 삭제는 이 API가 아니라 claude.ai에서 이루어집니다.

## 사전 요구 사항

* 조직이 Claude Enterprise 플랜을 사용해야 합니다.
* 기본 소유자가 [claude.ai > 조직 설정 > API](https://claude.ai/admin-settings/api-access)에서 `read:plugins` 범위, `write:plugins` 범위 또는 둘 다를 가진 Admin API 키를 생성합니다. [Admin API 키 생성](https://platform.claude.com/docs/ko/manage-claude/admin-api-keys#create-a-key-for-a-claude-enterprise-organization)을 참조하세요.
* 모든 요청에는 `x-api-key`, `anthropic-version: 2023-06-01`, `anthropic-beta: ce-plugins-2026-09-01`의 세 가지 헤더가 포함됩니다.

Python, TypeScript, C#, Go, Java, PHP, Ruby SDK는 이러한 엔드포인트를 `client.beta.organization` (csharp, go: `client.Beta.Organization`; java: `client.beta().organization()`; php: `$client->beta->organization`) 아래에, [`ant` CLI](https://platform.claude.com/docs/ko/cli-sdks-libraries/cli/quickstart)는 `ant beta:organization` 아래에 제공하며, `anthropic-version` 및 `anthropic-beta` 헤더를 자동으로 전송합니다. 이 페이지의 예제는 각 SDK의 기본 클라이언트를 사용하며, 이 클라이언트는 CLI와 마찬가지로 `ANTHROPIC_API_KEY` 환경 변수에서 Admin API 키를 읽습니다. curl 예제는 같은 변수에서 키를 읽어 `x-api-key` 헤더로 전달합니다. SDK나 CLI가 추가 페이지를 자동으로 가져오는 경우, `limit`은 전체 개수가 아니라 페이지 크기를 설정합니다([페이지네이션](https://platform.claude.com/docs/ko/manage-claude/plugins-api#pagination) 참조).

API 키는 조직에 속하며, 키를 생성한 사람이 조직을 떠난 후에도 계속 작동합니다. 키를 공유하거나 소스 제어에 체크인하지 마세요.

## 빠른 시작

조직 자체 마켓플레이스에 있는 플러그인을 최신순으로 나열합니다:

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins?owner_type=organization&limit=20" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins list --owner-type organization --limit 20
  ```

  ```python Python
  client = anthropic.Anthropic()

  plugins = client.beta.organization.plugins.list(owner_type="organization", limit=20)

  # 필요에 따라 추가 페이지를 자동으로 가져옵니다.
  for plugin in plugins:
      print(f"{plugin.id}: {plugin.name}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const plugins = await client.beta.organization.plugins.list({
    owner_type: "organization",
    limit: 20
  });

  for await (const plugin of plugins) {
    console.log(`${plugin.id}: ${plugin.name}`);
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta.Organization.Plugins;

  AnthropicClient client = new();

  var page = await client.Beta.Organization.Plugins.List(
      new() { OwnerType = OwnerType.Organization, Limit = 20 }
  );

  await foreach (var plugin in page.Paginate())
  {
      Console.WriteLine($"{plugin.ID}: {plugin.Name}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  plugins := client.Beta.Organization.Plugins.ListAutoPaging(context.Background(), anthropic.BetaOrganizationPluginListParams{
  	OwnerType: anthropic.BetaOrganizationPluginListParamsOwnerTypeOrganization,
  	Limit:     anthropic.Int(20),
  })

  for plugins.Next() {
  	plugin := plugins.Current()
  	fmt.Printf("%s: %s\n", plugin.ID, plugin.Name)
  }
  if err := plugins.Err(); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.PluginListParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = PluginListParams.builder()
          .ownerType(PluginListParams.OwnerType.ORGANIZATION)
          .limit(20)
          .build();
      var plugins = client.beta().organization().plugins().list(params);

      for (var plugin : plugins.autoPager()) {
          IO.println(plugin.id() + ": " + plugin.name());
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\Organization\Plugins\PluginListParams\OwnerType;
  // ...

  $client = new Client();

  $plugins = $client->beta->organization->plugins->list(
      limit: 20,
      ownerType: OwnerType::ORGANIZATION,
  );

  // 이 페이지만 해당합니다. 다음 페이지는 page: $plugins->nextPage로 list()를 다시 호출하세요.
  foreach ($plugins->getItems() as $plugin) {
      echo "{$plugin->id}: {$plugin->name}\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  page = client.beta.organization.plugins.list(owner_type: :organization, limit: 20)

  page.auto_paging_each do |plugin|
    puts "#{plugin.id}: #{plugin.name}"
  end
  ```
</CodeGroup>

```json
{
  "data": [
    {
      "type": "plugin",
      "id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      "name": "sales-toolkit",
      "display_name": "Sales Toolkit",
      "description": "Account research and call prep for the sales team.",
      "served_version_id": "pluginver_01Km7tL4pR9xF5sU2zV3jP6q",
      "served_version_pinned": true,
      "latest_version_id": "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p",
      "manifest_version": "1.4.0",
      "owner": { "type": "organization" },
      "marketplace_id": "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
      "created_by": { "type": "api_actor", "api_key_id": "apikey_01Nq9vN6rT2zH7uW4bX5mR8s" },
      "organization_installation_preference": "available",
      "organization_installation_preference_inherited": true,
      "content_scan": { "status": "completed", "assessment": "pass", "reason": null },
      "components": [
        {
          "type": "skill",
          "name": "account-research",
          "description": "Researches a customer account before a call."
        },
        { "type": "mcp_server", "name": "crm", "description": null }
      ],
      "reach": "remote",
      "created_at": "2026-09-01T17:04:11Z",
      "updated_at": "2026-09-15T14:12:30Z"
    }
  ],
  "next_page": "page_xK9f2LqT7vNw3pRzBd8sHy"
}
```

이 예제에서 플러그인은 이전 버전에 고정되어 있습니다. 더 새로운 버전(`latest_version_id`)이 저장되어 있지만 아직 제공되지 않습니다.

## 범위

| 범위                         | 부여 권한                                                                                                                                                                                                                                                                |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `read:plugins`             | 이 페이지의 모든 `GET` 엔드포인트(아카이브 다운로드 포함) 및 마켓플레이스 검증.                                                                                                                                                                                                                     |
| `write:plugins`            | 이 페이지의 모든 `POST` 및 `DELETE` 엔드포인트: 플러그인 생성, 버전 생성, 제공 버전 변경, 플러그인 삭제, 설치 설정 지정 및 제거, 마켓플레이스 기본값 설정, 그리고 마켓플레이스 검증. 읽기 권한은 부여하지 않습니다.                                                                                                                                 |
| `read:org_audit`           | 보안 감사 통합을 위한 읽기 전용 범위: 이 페이지의 모든 `GET` 엔드포인트(아카이브 다운로드 포함)와 [사용자 관리](https://platform.claude.com/docs/ko/manage-claude/user-management) 및 [Compliance API](https://platform.claude.com/docs/ko/manage-claude/compliance-api) 읽기 엔드포인트. 마켓플레이스 검증이나 쓰기 권한은 부여하지 않습니다. |
| `read:compliance_org_data` | 조직 메타데이터(이름, 유형, 역할, 그룹) 및 유효 설정을 위한 Compliance API의 범위. `read:org_audit`과 똑같이 이 페이지의 모든 `GET` 엔드포인트에 대한 권한을 부여하므로, Compliance Access Key로 두 번째 키 없이 플러그인을 읽을 수 있습니다. 마켓플레이스 검증이나 쓰기 권한은 부여하지 않습니다.                                                                  |

하나의 키에 여러 범위를 지정할 수 있습니다. 플러그인을 업로드한 후 다시 읽는 통합에는 `read:plugins`와 `write:plugins`가 모두 필요합니다. 이 페이지에서 엔드포인트에 `read:plugins` 범위가 필요하다고 명시된 곳에서는 `read:org_audit` 또는 `read:compliance_org_data`를 가진 키도 사용할 수 있습니다.

### 멤버의 플러그인 파일에 대한 액세스

이러한 각 읽기 범위(`read:plugins`, `read:org_audit`, `read:compliance_org_data`)로는 claude.ai의 관리자 설정에 표시되지 않는 파일을 포함하여 멤버의 개인 마켓플레이스에 있는 플러그인의 파일을 다운로드할 수 있습니다. 또한 상위 조직에 바인딩된 `read:org_audit` 또는 `read:compliance_org_data` 키는 `organization_id`를 전달하여, 그 아래에 있으며 이 API에 액세스할 수 있는 모든 조직에서 이 작업을 수행할 수 있습니다([같은 상위 조직 아래의 다른 조직 읽기](https://platform.claude.com/docs/ko/manage-claude/plugins-api#reading-another-organization-under-the-same-parent) 참조). 이러한 각 다운로드는 [Compliance API Activity Feed](https://platform.claude.com/docs/ko/manage-claude/compliance-activity-feed)에 키, 플러그인, 버전, 멤버를 식별하는 `claude_plugin_archive_accessed` 이벤트를 기록합니다([Activity Feed 이벤트](https://platform.claude.com/docs/ko/manage-claude/plugins-api#activity-feed-events) 참조). 조직 소유 플러그인의 다운로드는 기록되지 않습니다.

### 같은 상위 조직 아래의 다른 조직 읽기

`read:plugins` 및 `write:plugins` 키는 해당 키가 생성된 조직만 읽고 씁니다. 회사에 하나의 상위 조직 아래에 연결된 여러 Claude 조직이 있는 경우, 상위 조직의 기본 소유자가 연결된 모든 조직에 대해 생성한 `read:org_audit` 또는 `read:compliance_org_data` 키([Admin API 키 생성](https://platform.claude.com/docs/ko/manage-claude/admin-api-keys#create-a-key-for-a-claude-enterprise-organization) 참조)는 이 API에 액세스할 수 있는 해당 조직 중 어느 것이든 읽을 수 있습니다. 이 페이지의 모든 `GET` 엔드포인트에서 `organization_id` 쿼리 매개변수에 해당 조직의 ID를 전달하세요. ID는 claude.ai 설정에 표시되는 조직 UUID입니다(`org_` 접두사가 붙은 형식도 허용됩니다). 매개변수가 없으면 키는 자신이 생성된 조직을 읽습니다. `404`는 지정된 조직이 키의 상위 조직 아래에 없거나 해당 조직에서 이 API를 사용할 수 없음을 의미합니다. UUID나 `org_` ID가 아닌 값은 `400`을 반환합니다. 그 외의 키가 자신의 조직이 아닌 다른 조직을 지정하면 `404`를 받습니다. 쓰기 작업은 `organization_id`를 허용하지 않습니다.

## 주요 개념

### 플러그인과 구성 요소

**플러그인**은 조직 멤버를 위해 Claude를 확장하는 패키지입니다. 플러그인은 다음 구성 요소를 임의로 조합하여 포함합니다:

| 구성 요소              | 설명                                                     |
| ------------------ | ------------------------------------------------------ |
| 스킬(Skill)          | 작업에 필요할 때 Claude가 로드하는 지침과 파일.                         |
| 명령(Command)        | 멤버가 `/` 다음에 명령 이름을 입력하여 실행하는 저장된 프롬프트.                 |
| 에이전트(Agent)        | Claude가 작업의 일부를 넘길 수 있는, 자체 지침을 가진 도우미 어시스턴트.          |
| 훅(Hook)            | Claude가 도구를 사용하기 전과 같이 세션에서 이벤트가 발생할 때 자동으로 실행되는 명령.   |
| MCP 서버(MCP server) | Claude에서 다른 시스템의 도구와 데이터로의 연결(Model Context Protocol). |
| CLI                | 플러그인을 통해 Claude가 실행할 수 있는 명령줄 프로그램.                    |

모든 플러그인에는 `.claude-plugin/plugin.json`에 매니페스트가 있습니다. 매니페스트의 `name`은 플러그인의 `name`이 되며, 이는 마켓플레이스 내에서 고유한 소문자 식별자입니다.

### 마켓플레이스

**마켓플레이스**는 플러그인의 컨테이너입니다. 각 마켓플레이스에는 소유자와 소스가 있습니다.

* **소유자.** 조직은 자체 마켓플레이스를 소유합니다. 각 멤버도 개인 마켓플레이스를 가질 수 있습니다.
* **소스.** `manual`은 플러그인이 claude.ai에서, 또는 조직 마켓플레이스의 경우 이 API를 통해 업로드됨을 의미합니다. `github`, `gitlab`, `public_git`은 소유자가 연결한 Git 저장소에서 플러그인이 동기화됨을 의미합니다. 동기화된 마켓플레이스에는 아무것도 업로드할 수 없으며, 다음 동기화가 어느 변경이든 되돌리기 때문에 이 API로 해당 플러그인을 삭제할 수도 없습니다. 대신 저장소를 변경하세요.

조직의 "**library marketplace**"(라이브러리 마켓플레이스)는 마켓플레이스를 지정하지 않을 때 업로드가 들어가는 조직 소유 `manual` 마켓플레이스입니다. 이 마켓플레이스는 처음으로 무언가가 업로드될 때 생성됩니다.

### 조직 소유 플러그인과 멤버 소유 플러그인

플러그인의 `owner.type`은 플러그인이 누구의 마켓플레이스에 있는지를 나타냅니다:

* `organization`: 이 API를 통해 관리할 수 있습니다. 단, Git에서 동기화되는 마켓플레이스의 플러그인은 여기서 업로드를 받거나 삭제할 수 없습니다.
* `user`: 한 멤버의 개인 마켓플레이스에 있습니다. 세부 정보를 읽고 파일을 다운로드할 수 있으며, 마켓플레이스가 `manual`이면 삭제할 수 있습니다. 버전 업로드와 제공 버전 선택은 `403`을 반환합니다. 공유는 claude.ai에서 멤버만 관리할 수 있습니다.

조직에서 멤버를 제거해도 해당 멤버의 플러그인은 제거되지 않습니다. 플러그인은 멤버의 `user_id` 아래 인벤토리에 남아 있으며 `owner_user_id` 필터로 여전히 찾을 수 있으므로, 떠난 멤버의 콘텐츠를 검토하고 제거할 수 있습니다. 멤버의 계정이 삭제되면 인벤토리에서 제거됩니다.

### 버전과 제공 버전

이 API, claude.ai, Git 동기화 중 어디에서 오든 모든 업로드는 변경할 수 없는 새 "**version**"(버전)을 생성합니다. 플러그인에는 버전을 가리키는 두 개의 포인터가 있습니다:

* `latest_version_id`: 최신 버전.
* `served_version_id`: 멤버에게 제공되는 버전.

기본적으로 `served_version_pinned`는 `false`이며, 제공 버전은 일반적으로 최신 버전을 따릅니다. 콘텐츠 스캔이 켜져 있으면 claude.ai에서 저장된 버전은 콘텐츠 스캔을 **대기**할 수 있습니다. 즉, 저장되지만 즉시 제공되지는 않습니다. 이 페이지에서 "대기"는 claude.ai에서 저장된 버전에만 사용하며, 멤버나 관리자가 플러그인에 게시하는 버전에는 사용하지 않습니다. 스캔이 켜져 있는 동안 대기 중인 버전은 스캔이 `pass` 또는 `warn`으로 완료된 후에만 제공됩니다. 버전이 대기하는 동안 `served_version_id`는 `latest_version_id`보다 이전 버전을 가리킵니다. 두 ID가 일치할 때까지 폴링하지 마세요. 예를 들어 스캔이 실패하면 두 ID가 계속 다를 수 있습니다.

`POST /v1/organizations/plugins/{plugin_id}`로 버전을 선택하면 플러그인이 "**pin**"(고정)됩니다(`served_version_pinned: true`). 관리자가 claude.ai에서 버전을 선택하거나, 플러그인에 게시하려는 멤버의 요청을 수락하는 경우에도 마찬가지입니다. 그 이후로 새 업로드는 저장되고 `latest_version_id`를 갱신하지만, `served_version_id`를 다른 버전으로 지정할 때까지 멤버는 고정된 버전을 계속 사용합니다. 두 포인터가 서로 다른 플러그인에는 제공되지 않는 저장된 버전이 있습니다.

이를 통해 릴리스 파이프라인은 각 빌드를 업로드하고, 테스트한 다음, 승격할 수 있습니다. 각 빌드가 제공되는 시점을 파이프라인이 결정하도록 하려면 `served_version_id`를 현재 버전으로 설정하여 플러그인을 한 번 고정하세요. 그 이후로는 제공하려는 각 빌드를 승격하세요. "content scanning"(콘텐츠 스캔)이 켜져 있으면, 첫 번째 고정은 현재 버전의 스캔이 완료될 때까지 `409 scan_pending`을 반환하고, 스캔이 `fail` 또는 `unknown`으로 완료되었거나 오류가 발생한 경우 `400 scan_failed`를 반환합니다(`warn`은 허용됩니다). 고정된 플러그인은 현재 여기서든 claude.ai에서든 고정을 해제할 수 없습니다.

롤백하려면 `served_version_id`를 이전 버전으로 설정하세요. 롤포워드도 같은 방식으로 합니다.

이 규칙은 조직 소유 플러그인에 대한 설명입니다. 멤버 소유 플러그인의 제공 버전은 claude.ai에서 소유자가 제어합니다.

### 설치 설정

"**Installation settings**"(설치 설정)는 조직 소유 플러그인을 사용할 수 있는 사람을 결정합니다. 각 설정은 `installation_preference`라는 필드(그리고 플러그인 및 마켓플레이스 객체에서는 `organization_installation_preference` 및 `default_installation_preference`)에 담긴 네 가지 값 중 하나를 가집니다:

| 값               | 멤버에게 표시되는 내용           |
| --------------- | ---------------------- |
| `required`      | 플러그인이 설치되며 제거할 수 없습니다. |
| `auto_install`  | 플러그인이 설치되며 제거할 수 있습니다. |
| `available`     | 요청 시 플러그인을 설치할 수 있습니다. |
| `not_available` | 플러그인이 숨겨집니다.           |

플러그인은 조직 전체 설정 하나와 그룹별 설정 하나씩([사용자 관리](https://platform.claude.com/docs/ko/manage-claude/user-management#groups)에서 관리되는 역할 기반 액세스 제어 그룹)을 가질 수 있습니다. 멤버는 다음 규칙에 따라 값을 받습니다:

1. 조직 전체 값은 플러그인 자체의 조직 전체 설정이 있으면 그 값이고, 없으면 마켓플레이스의 기본값이며, 그것도 없으면 `not_available`입니다. 플러그인은 이 값을 `organization_installation_preference`에 보고하며, 값이 마켓플레이스 기본값에서 오는 동안에는 `organization_installation_preference_inherited: true`를 함께 보고합니다.
2. 플러그인에 대한 설정을 가진 그룹에 속하지 않은 멤버는 조직 전체 값을 받습니다.
3. 설정을 가진 그룹에 하나 이상 속한 멤버는 대신 해당 그룹 설정 중 가장 허용적인 값을 받으며, 순위는 `required`, `auto_install`, `available`, `not_available` 순입니다.

그룹의 설정은 해당 멤버에 대해 조직 전체 값을 대체하며, 추가되지 않습니다. 예를 들어 조직 전체 값이 `required`이고 Pilot 그룹이 `available`을 가지고 있으면 Pilot 멤버는 `available`을 받습니다. 플러그인을 파일럿 그룹에서 조직 전체로 옮길 때는 조직 전체 값을 설정한 다음 그룹의 설정을 제거하세요. 조직 전체 값을 설정하면 플러그인이 마켓플레이스 기본값을 상속하지 않게 됩니다. [조직 전체 설정을 제거](https://platform.claude.com/docs/ko/manage-claude/plugins-api#remove-an-installation-setting)하면 플러그인이 해당 기본값으로 돌아갑니다.

이 API를 통해 생성된 플러그인은 자체 설정 없이 시작하므로 마켓플레이스의 기본값을 상속합니다. 누군가 기본값을 설정하지 않았다면 이 값은 `not_available`입니다. 그룹을 삭제하면 모든 플러그인에서 해당 그룹의 설정이 제거됩니다.

### 공유

"**Shares**"(공유)는 멤버 소유 플러그인을 사용할 수 있는 사람을 결정합니다. 소유자는 claude.ai에서 모든 멤버, 그룹 또는 지정된 멤버와 플러그인을 공유합니다. 이 API는 공유를 나열할 수 있지만 변경할 수는 없습니다.

조직이 claude.ai 설정에서 특정 종류의 공유를 꺼 둔 경우, 해당 종류의 공유는 목록에 계속 나타나지만 그 설정이 꺼져 있는 동안에는 누구에게도 액세스 권한을 부여하지 않습니다. 목록 자체에는 해당 설정이 꺼져 있는지 여부가 표시되지 않습니다.

### 콘텐츠 스캔

콘텐츠 스캔은 claude.ai의 조직 설정입니다. 이 설정이 켜져 있으면 새로 저장된 버전이 스캔되고(claude.ai는 일부를 예외로 둡니다) 결과가 `content_scan`에 보고됩니다. 스캔되지 않은 버전(예: 스캔이 켜지기 전에 저장된 버전)은 `content_scan: null`을 가집니다. 고객 관리형 암호화 키 또는 "zero data retention"(데이터 무보존)을 사용하는 조직에는 스캔이 제공되지 않습니다.

스캔이 켜져 있는 동안 멤버는 제공 버전의 스캔이 `pass` 또는 `warn`으로 `completed`된 경우에만 플러그인을 제공받습니다. 스캔이 실행되는 동안, 또는 스캔이 실패하거나 오류가 발생하거나 판정에 도달하지 못한 후에는 플러그인이 멤버에게 제공되지 않으며, 그 대신 이전 버전이 제공되지도 않습니다. 스캔된 적이 없는 버전(`content_scan: null`)은 정상적으로 제공됩니다.

이 API를 통해 업로드한 버전은 콘텐츠 스캔을 대기하지 않습니다. 해당 버전이 제공 버전이 되면 멤버는 스캔이 통과할 때까지 플러그인을 사용할 수 없으며, 스캔이 실패하면 계속 사용할 수 없습니다. 새 버전이 스캔되는 동안 멤버가 현재 버전을 유지해야 한다면 먼저 플러그인을 고정하세요([버전과 제공 버전](https://platform.claude.com/docs/ko/manage-claude/plugins-api#versions-and-the-served-version) 참조).

claude.ai에서 저장된 버전이 스캔을 대기하는 동안 제공 버전은 변경되지 않습니다. API 업로드가 제공 버전이 되면 모든 대기가 종료되며, 대기 중이던 버전은 누군가 선택하는 경우에만 제공됩니다. 대기 중인 버전의 스캔을 보려면 해당 버전을 읽으세요([플러그인 버전 목록 조회](https://platform.claude.com/docs/ko/manage-claude/plugins-api#list-a-plugins-versions) 참조).

업로드 후 `content_scan.status`는 `processing`이며 판정은 비동기적으로 도착합니다. 판정을 확인하려면 버전을 읽으세요. 플러그인 객체는 제공 버전의 스캔만 표시합니다. 스캔이 아직 실행 중인 버전으로 제공 버전을 변경하면 `409 scan_pending`을 반환하고, 스캔이 실패한 버전으로 변경하면 `400 scan_failed`를 반환합니다.

### 도달 범위

`reach`는 버전이 멤버의 컴퓨터와 그 너머에 얼마나 멀리 도달하는지를 하나의 값으로 요약합니다:

| 값            | 의미                                                                                                                                                                                                                               |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `remote`     | 다른 무엇을 선언하든 관계없이 MCP 서버 또는 CLI를 선언합니다.                                                                                                                                                                                           |
| `privileged` | MCP 서버나 CLI는 선언하지 않지만, 훅, 모니터(세션 동안 계속 실행되는 백그라운드 명령), LSP(Language Server Protocol) 서버, 또는 플러그인이 멤버의 앱에 적용하는 설정을 선언하거나, 프런트매터에서 도구를 사전 승인하는(`allowed-tools`) 스킬, 명령 또는 기타 Markdown 파일을 포함합니다. 이러한 항목은 멤버 자신의 컴퓨터에서 실행되거나 적용됩니다. |
| `contained`  | MCP 서버, CLI, 훅, 모니터, LSP 서버 또는 앱 설정을 선언하지 않으며, Markdown 파일 중 어느 것도 도구를 사전 승인하지 않습니다(예: `allowed-tools`가 없는 스킬, 명령, 에이전트만 포함하는 플러그인).                                                                                             |

`reach`는 `components`에 나열되지 않는 모니터, LSP 서버, 앱 설정을 포함하여 버전이 선언하는 모든 것을 고려하므로, `components` 목록이 비어 있는 버전도 `privileged`일 수 있습니다. 구성 요소가 기록되기 전에 저장된 버전, 그리고 스킬 중 하나의 `SKILL.md`나 명령 파일 중 하나를 읽을 수 없어 도달 범위를 판단할 수 없는 버전의 경우 `null`입니다. `null`은 미분류로 취급하세요.

### 업로드 요구 사항

업로드는 claude.ai의 플러그인 업로드와 동일한 규칙을 따르므로, 두 곳에서 동일한 아카이브가 허용됩니다.

* 업로드는 하나의 `.zip` 또는 `.plugin` 아카이브이거나 개별 파일 집합입니다. 아카이브는 모든 내용을 하나의 최상위 폴더로 감쌀 수 있습니다.
* 정확히 하나의 매니페스트가 `.claude-plugin/plugin.json`에 있어야 하며, 매니페스트는 `name`을 선언해야 합니다. 매니페스트 없이 `SKILL.md`만 있으면 거부됩니다.
* 프런트매터에서 플러그인 구성 요소를 선언하는 최상위 `SKILL.md`는 매니페스트에 병합됩니다. 둘 다 값을 설정하는 경우 `plugin.json`이 우선합니다.
* `name`에는 소문자(모든 문자 체계), 숫자, 하이픈을 최대 64자까지 사용할 수 있습니다. 대문자, 공백, 밑줄 및 기타 구두점은 거부됩니다.
* `displayName`은 최대 64자, `description`은 최대 500자입니다.
* 모든 `SKILL.md`에는 `name`과 `description`이 있는 유효한 YAML 프런트매터가 필요하며, 둘 다 `<example>`과 같은 XML 태그를 포함할 수 없습니다. 두 스킬 또는 두 명령은 같은 이름을 가질 수 없습니다.
* 최상위 `bin/` 디렉터리 아래에는 파일이 있을 수 없습니다.
* 중첩된 `.zip` 파일은 허용되지 않습니다. 패키징된 MCP 서버(`.mcpb`, `.dxt`)는 허용됩니다.
* 파일 경로는 상대 경로여야 하고, `..`를 포함하지 않아야 하며, 문자, 숫자, 공백 및 `_ . - / ( ) ,`만 사용해야 합니다.
* 요청 본문과 압축 해제된 아카이브는 각각 최대 200MB입니다. 한도를 초과하는 요청 본문은 `400`이 아닌 `413`(`request_too_large`)을 반환합니다. 업로드는 최대 5,000개 파일, 경로 깊이 12, 경로 길이 472자, 파일 또는 폴더 이름 255자로 제한됩니다.
* ZIP 아카이브는 DEFLATE 또는 STORE 압축을 사용해야 하며, 암호화되거나 심볼릭 링크를 포함할 수 없습니다.
* 마켓플레이스는 플러그인과 멤버가 보관하는 독립형 스킬을 합쳐 최대 500개 항목을 보유할 수 있습니다. 이 한도와 5,000개 파일 한도는 현재 값이며 상향될 수 있습니다.

## 예제 워크플로

### 릴리스 파이프라인에서 각 빌드 게시

CI에서 태그가 지정된 모든 빌드를 업로드하고, 빌드가 제공되는 시점을 파이프라인이 결정하도록 합니다.

1. `GET /v1/organizations/plugin_marketplaces?owner_type=organization`으로 업로드할 마켓플레이스를 찾거나, `marketplace_id`를 생략하여 라이브러리 마켓플레이스를 사용하세요.
2. 첫 번째 릴리스에서는 `POST /v1/organizations/plugins`로 [플러그인을 생성](https://platform.claude.com/docs/ko/manage-claude/plugins-api#create-a-plugin)하세요. 이후 모든 릴리스에서는 플러그인의 `latest_version_id`를 기록한 다음 `POST /v1/organizations/plugins/{plugin_id}/versions`로 [버전을 업로드](https://platform.claude.com/docs/ko/manage-claude/plugins-api#create-a-version)하세요. 업로드 응답이 유실되면 플러그인을 읽고 `latest_version_id`가 변경되지 않은 경우에만 재시도하세요([업로드 재시도](https://platform.claude.com/docs/ko/manage-claude/plugins-api#retrying-uploads) 참조).
3. 각 새 빌드를 확인하는 동안 멤버가 현재 버전을 계속 사용하도록 하려면 `served_version_id`를 현재 버전으로 설정하여 플러그인을 한 번 고정하세요. 그 이후로 각 업로드는 제공되지 않은 채 저장되며, 고정은 취소할 수 없습니다. 제공하려는 모든 빌드에는 5단계가 필요합니다.
4. 콘텐츠 스캔이 켜져 있으면 `content_scan.status`가 더 이상 `processing`이 아닐 때까지 `GET /v1/organizations/plugins/{plugin_id}/versions/{version}`을 폴링하고, `pass` 또는 `warn`으로 `completed`된 경우에만 승격하세요.
5. `POST /v1/organizations/plugins/{plugin_id}`와 `{"served_version_id": "<the new version's ID>"}`로 [빌드를 승격](https://platform.claude.com/docs/ko/manage-claude/plugins-api#change-the-served-version)하세요. 롤백하려면 같은 방식으로 이전 버전의 ID를 보내세요.

### 파일럿 그룹에 플러그인을 배포한 다음 모든 사람에게 배포

1. `GET /v1/organizations/rbac_groups`로 파일럿 그룹의 ID를 조회하세요. 이 호출에는 `read:rbac_groups` 범위가 필요하며, 이 범위를 사용하려면 연결된 모든 조직에 대해 생성된 키가 필요합니다([사용자 관리](https://platform.claude.com/docs/ko/manage-claude/user-management#groups) 참조). 다음 단계에는 키가 생성된 조직에서만 작동하는 `write:plugins`가 필요하므로, 연결된 조직이 여러 개인 엔터프라이즈에서는 플러그인을 보유한 조직에서 이 키를 생성하고 두 범위를 모두 부여하거나, 해당 단계에는 그 조직에서 생성한 두 번째 키를 사용하세요.

2. `POST /v1/organizations/plugins/{plugin_id}/installation_settings/{target}`으로 [그룹에 자체 설정을 부여](https://platform.claude.com/docs/ko/manage-claude/plugins-api#set-an-installation-setting)하세요(예: `auto_install`). 여기서 `{target}`은 그룹의 `rbac_group_` ID이며, 조직 전체 값은 `not_available`로 유지됩니다. 그룹 멤버만 플러그인을 받습니다.

3. 파일럿이 끝나면 다음 호출로 조직 전체 값을 설정한 다음, 그룹이 다시 조직을 따르도록 그룹의 설정을 제거하세요. 조직 전체 값을 설정하면 플러그인이 마켓플레이스 기본값을 상속하지 않게 됩니다. 나중에 [조직 전체 설정을 제거](https://platform.claude.com/docs/ko/manage-claude/plugins-api#remove-an-installation-setting)하면 플러그인이 해당 기본값으로 돌아갑니다.

   <CodeGroup>
     ```bash cURL
     curl -X POST "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/installation_settings/organization" \
       -H "content-type: application/json" \
       -H "x-api-key: $ANTHROPIC_API_KEY" \
       -H "anthropic-version: 2023-06-01" \
       -H "anthropic-beta: ce-plugins-2026-09-01" \
       -d '{"installation_preference": "required"}'
     ```

     ```bash CLI
     ant beta:organization:plugins:installation-settings set \
       --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
       --target organization \
       --installation-preference required
     ```

     ```python Python
     client = anthropic.Anthropic()

     setting = client.beta.organization.plugins.installation_settings.set(
         "organization",
         plugin_id="plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
         installation_preference="required",
     )

     print(f"plugin_id: {setting.plugin_id}")
     print(f"installation_preference: {setting.installation_preference}")
     ```

     ```typescript TypeScript
     const client = new Anthropic();

     const setting = await client.beta.organization.plugins.installationSettings.set(
       "organization",
       {
         plugin_id: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
         installation_preference: "required"
       }
     );

     console.log(`plugin_id: ${setting.plugin_id}`);
     console.log(`installation_preference: ${setting.installation_preference}`);
     ```

     ```csharp C#
     using Anthropic.Models.Beta.Organization.Plugins.InstallationSettings;

     AnthropicClient client = new();

     var setting = await client.Beta.Organization.Plugins.InstallationSettings.Set(
         "organization",
         new()
         {
             PluginID = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
             InstallationPreference = InstallationPreference.Required,
         }
     );

     Console.WriteLine($"plugin_id: {setting.PluginID}");
     Console.WriteLine($"installation_preference: {setting.InstallationPreference.Raw()}");
     ```

     ```go Go
     client := anthropic.NewClient()

     setting, err := client.Beta.Organization.Plugins.InstallationSettings.Set(
     	context.Background(),
     	"organization",
     	anthropic.BetaOrganizationPluginInstallationSettingSetParams{
     		PluginID:               "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
     		InstallationPreference: anthropic.BetaOrganizationPluginInstallationSettingSetParamsInstallationPreferenceRequired,
     	},
     )
     if err != nil {
     	log.Fatal(err)
     }

     fmt.Printf("plugin_id: %s\n", setting.PluginID)
     fmt.Printf("installation_preference: %s\n", setting.InstallationPreference)
     ```

     ```java Java
     import com.anthropic.models.beta.organization.plugins.installationsettings.InstallationSettingSetParams;

     void main() {
         AnthropicClient client = AnthropicOkHttpClient.fromEnv();

         var params = InstallationSettingSetParams.builder()
             .pluginId("plugin_01Hq3vX8kZcN2mB7pR4tY9wL")
             .installationPreference(InstallationSettingSetParams.InstallationPreference.REQUIRED)
             .build();
         var setting = client.beta().organization().plugins().installationSettings()
             .set("organization", params);

         IO.println("plugin_id: " + setting.pluginId());
         IO.println("installation_preference: " + setting.installationPreference().asString());
     }
     ```

     ```php PHP
     use Anthropic\Beta\Organization\Plugins\InstallationSettings\InstallationSettingSetParams\InstallationPreference;
     // ...

     $client = new Client();

     $setting = $client->beta->organization->plugins->installationSettings->set(
         target: 'organization',
         pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
         installationPreference: InstallationPreference::REQUIRED,
     );

     echo "plugin_id: {$setting->pluginID}\n";
     echo "installation_preference: {$setting->installationPreference}\n";
     ```

     ```ruby Ruby
     client = Anthropic::Client.new

     plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
     setting = client.beta.organization.plugins.installation_settings.set(
       "organization",
       plugin_id: plugin_id,
       installation_preference: :required
     )

     puts "plugin_id: #{setting.plugin_id}"
     puts "installation_preference: #{setting.installation_preference}"
     ```
   </CodeGroup>

   그런 다음 `DELETE /v1/organizations/plugins/{plugin_id}/installation_settings/{target}`으로 그룹의 설정을 제거하세요. 여기서 `{target}`은 그룹의 ID입니다. 그룹의 설정은 해당 멤버에 대해 조직 전체 값에 추가되는 것이 아니라 조직 전체 값을 대체하므로, `available`인 그룹 설정이 남아 있으면 해당 멤버는 계속 `available`을 받게 됩니다.

### 보안 인벤토리 동기화 유지

멤버의 세션 외부로 도달하거나 콘텐츠 스캔에 실패한 플러그인을 표시하는 야간 작업을 실행하세요.

1. `next_page`가 `null`이 될 때까지 [`GET /v1/organizations/plugins?limit=100`](https://platform.claude.com/docs/ko/manage-claude/plugins-api#list-plugins)을 페이지별로 조회하세요([페이지네이션](https://platform.claude.com/docs/ko/manage-claude/plugins-api#pagination) 참조). 매 실행마다 해당 목록에서 각 플러그인의 `reach`와 `content_scan`을 읽으세요. 나중에 도착하는 스캔 판정은 `updated_at`을 변경하지 않습니다. `updated_at`은 일반적으로 마지막 실행 이후 새 콘텐츠나 새 제공 버전이 있는 플러그인을 알려줍니다(새로 아카이브를 다운로드할 가치가 있음). 대기 중인 버전([버전과 제공 버전](https://platform.claude.com/docs/ko/manage-claude/plugins-api#versions-and-the-served-version) 참조)은 저장될 때가 아니라 제공 버전이 될 때 `updated_at`을 변경합니다. 이를 알아차리려면 `latest_version_id`를 마지막 실행의 값과 비교하세요. Git 동기화나 계정 삭제로 제거된 플러그인은 이벤트 없이 사라지므로, 전체 재나열은 제거를 포착하는 방법이기도 합니다.
2. `reach`가 `remote`(MCP 서버나 CLI를 선언함)이거나 `content_scan.assessment`가 `fail` 또는 `unknown`인 각 플러그인을 표시하세요. 이 필드는 제공 버전을 설명합니다. 제공되지 않는 더 새로운 버전도 확인하려면 `latest_version_id`가 `served_version_id`와 다를 때 플러그인의 버전을 나열하세요([플러그인 버전 목록 조회](https://platform.claude.com/docs/ko/manage-claude/plugins-api#list-a-plugins-versions) 참조).
3. 표시된 각 플러그인에 대해 `GET /v1/organizations/plugins/{plugin_id}/versions/{served_version_id}/content`로 검토를 위해 제공 버전의 아카이브를 다운로드하세요([버전 파일 다운로드](https://platform.claude.com/docs/ko/manage-claude/plugins-api#download-a-versions-files) 참조). 2단계의 기준을 충족하는 제공되지 않는 버전도 ID로 다운로드하세요.
4. 검토하는 동안 멤버가 플러그인을 사용하지 못하게 하려면, 되돌릴 수 있는 옵션(조직 소유)과 영구적인 옵션에 대해 [플러그인 삭제](https://platform.claude.com/docs/ko/manage-claude/plugins-api#delete-a-plugin)를 참조하세요.

## 플러그인

플러그인 객체는 조직의 마켓플레이스 중 하나 또는 멤버의 개인 마켓플레이스에 있는 플러그인을 설명합니다([빠른 시작](https://platform.claude.com/docs/ko/manage-claude/plugins-api#quick-start) 응답에 전체 객체가 나와 있습니다). 객체의 `display_name`, `description`, `manifest_version`, `content_scan`, `components`, `reach`는 **제공** 버전을 설명하므로, 한 번의 목록 호출로 멤버에게 무엇이 제공되고 있는지 확인할 수 있습니다.

| 필드                                                                                       | 설명                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                                                                     | `plugin_` 접두사가 붙습니다.                                                                                                                                                                                                                                                                                                                                                          |
| `name`                                                                                   | 매니페스트에서 가져옵니다. 조직 전체가 아니라 마켓플레이스 내에서 고유합니다. 조직 소유 플러그인의 경우 고정되며, 멤버가 claude.ai에서 자신의 플러그인 이름을 변경하면 바뀝니다.                                                                                                                                                                                                                                                                      |
| `display_name`, `description`, `manifest_version`                                        | 제공 버전의 매니페스트 `displayName`, `description`, `version`입니다. 매니페스트에 선언되지 않은 경우 각각 `null`입니다. `manifest_version`은 표시용으로 정규화됩니다. 앞에 붙은 `v` 또는 `V` 하나가 제거되므로, 매니페스트 `version`이 `"v1.4.0"`이면 `"1.4.0"`으로 반환됩니다. 또한 `"latest"`처럼 버전 번호로 보이지 않는 값, 그리고 claude.ai가 2026년 8월에 이 필드를 기록하기 시작하기 전에 생성된 플러그인 버전의 경우에도 `null`입니다. 업로드는 `version` 때문에 거부되지 않으며, `manifest_version`은 고유하지 않습니다. |
| `served_version_id`, `latest_version_id`                                                 | `pluginver_` 접두사가 붙습니다. 각각 멤버에게 제공되는 버전과 최신 버전입니다. [버전과 제공 버전](https://platform.claude.com/docs/ko/manage-claude/plugins-api#versions-and-the-served-version)을 참조하세요.                                                                                                                                                                                                         |
| `served_version_pinned`                                                                  | 플러그인이 고정될 때까지 `false`이며([버전과 제공 버전](https://platform.claude.com/docs/ko/manage-claude/plugins-api#versions-and-the-served-version) 참조), 그 이후로는 `true`입니다.                                                                                                                                                                                                                     |
| `owner`                                                                                  | `{"type": "organization"}`, 또는 멤버의 개인 마켓플레이스의 경우 `{"type": "user", "user_id": "user_..."}`입니다.                                                                                                                                                                                                                                                                                |
| `marketplace_id`                                                                         | `marketplace_` 접두사가 붙습니다.                                                                                                                                                                                                                                                                                                                                                     |
| `created_by`                                                                             | 플러그인을 생성한 주체입니다. claude.ai의 사람인 경우 `{"type": "user_actor", "user_id": "user_...", "email_address": "..."}`(`email_address`는 `null`일 수 있음), API 키인 경우 `{"type": "api_actor", "api_key_id": "apikey_..."}`입니다. 다른 행위자 유형이 나타날 수도 있습니다. Git에서 동기화된 플러그인처럼 생성자가 기록되지 않은 경우 `null`입니다.                                                                                             |
| `organization_installation_preference`, `organization_installation_preference_inherited` | 조직 소유: 조직 전체 값과, 그 값이 마켓플레이스의 기본값에서 오는지 여부입니다([설치 설정](https://platform.claude.com/docs/ko/manage-claude/plugins-api#installation-settings) 참조). 멤버 소유: 둘 다 `null`입니다.                                                                                                                                                                                                         |
| `content_scan`                                                                           | 제공 버전의 스캔 결과로, `status`, `assessment`, `reason`을 가진 객체입니다(이 표 다음에 설명). 스캔된 적이 없으면 `null`입니다.                                                                                                                                                                                                                                                                                  |
| `components`                                                                             | 제공 버전의 구성 요소로, 각각 `{"type", "name", "description"}` 형식이며 `type`은 `skill`, `mcp_server`, `command`, `agent`, `hook`, `cli` 중 하나입니다. 이 유형 순서대로 나열된 다음 이름순으로 나열됩니다. MCP 서버의 경우 `name`은 매니페스트의 키이고, 훅의 경우 훅이 실행되는 이벤트이며, CLI의 경우 실행 파일의 이름입니다. MCP 서버, 훅, CLI의 `description`은 항상 `null`입니다. 기록되지 않은 경우 `null`입니다.                                                                 |
| `reach`                                                                                  | `contained`, `privileged`, `remote` 중 하나입니다. [도달 범위](https://platform.claude.com/docs/ko/manage-claude/plugins-api#reach)를 참조하세요.                                                                                                                                                                                                                                             |
| `updated_at`                                                                             | 제공 버전이 변경될 때, 플러그인이 고정될 때, 그리고 일반적으로 새 버전이 저장될 때 변경됩니다. 대기 중인 버전([버전과 제공 버전](https://platform.claude.com/docs/ko/manage-claude/plugins-api#versions-and-the-served-version) 참조)은 저장될 때가 아니라 제공 버전이 될 때 이 값을 변경합니다. 설치 설정, 공유 또는 새 스캔 결과에 대해서는 변경되지 않습니다.                                                                                                                      |

`content_scan` 객체:

| 필드           | 설명                                                                                                                                                                                                                               |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`     | 스캔이 실행되는 동안에는 `processing`, 완료되면 `completed`, 완료할 수 없으면 `errored`입니다(또는 드물게 이 응답에서 결과를 읽을 수 없는 경우에도 `errored`이며, 이 경우 나중에 읽으면 결과가 보고될 수 있습니다). 스캔이 `processing` 또는 `errored`인 버전은 멤버에게 제공되지 않습니다. 콘텐츠를 새 버전으로 다시 업로드하면 새로 스캔됩니다. |
| `assessment` | `status`가 `completed`일 때 설정됩니다: `pass`(발견된 항목 없음), `warn`(사용을 차단하지 않는 항목 발견), `fail`(사용을 차단하는 항목 발견), `unknown`(판정 없음). 그 외에는 `null`입니다.                                                                                         |
| `reason`     | `warn` 및 `fail`의 경우 다음 목록에 있는 주요 우려 사항입니다. 그 외에는 `null`이며, 사유 기록 기능 이전의 오래된 스캔에서도 `null`입니다.                                                                                                                                     |

<Accordion title="콘텐츠 스캔 reason 값">
  | `reason`                          | 의미                                                                |
  | --------------------------------- | ----------------------------------------------------------------- |
  | `covert-usage-telemetry`          | 멤버에게 알리지 않고 멤버 또는 멤버의 사용에 관한 정보를 외부 주소로 보내도록 Claude에 지시합니다.       |
  | `undisclosed-data-destination`    | 파일, 이메일, 문서 또는 기타 콘텐츠를 멤버에게 표시되지 않고 멤버가 제어하지 않는 고정된 외부 대상으로 보냅니다. |
  | `remote-code-instruction-loader`  | 플러그인 설치 후 변경될 수 있는 외부 콘텐츠를 다운로드하여 실행하거나 그 지침을 따르도록 Claude에 지시합니다. |
  | `credential-exposure`             | 실제 자격 증명을 포함하거나, 멤버의 환경에서 자격 증명 또는 토큰을 수집합니다.                     |
  | `guardrail-tampering`             | 예를 들어 모든 권한 프롬프트를 사전 승인하는 방식으로 멤버의 보호 장치를 약화시킵니다.                 |
  | `system-prompt-spoofing`          | Claude의 시스템 지침을 모방하거나 대체하려고 시도합니다.                                |
  | `covert-record-tampering`         | 멤버가 원래 보게 될 정보를 몰래 변경하거나, 숨기거나, 삭제합니다.                            |
  | `covert-behavior-override`        | 플러그인의 목적을 넘어 Claude의 동작을 변경하고 그 변경을 멤버에게 숨깁니다.                    |
  | `hidden-code-execution`           | 번들된 코드를 실행하면서 그 코드가 하는 일을 밝히지 말라고 Claude에 지시합니다.                  |
  | `undisclosed-promotion-injection` | 공개되지 않은 홍보 콘텐츠를 Claude의 출력에 삽입합니다.                                |
  | `hidden-identity-gate`            | 이유를 밝히지 않고 어떤 계정이 실행하는지에 따라 동작을 변경하거나 중단합니다.                      |
  | `destructive-persistence`         | 멤버의 파일을 삭제하거나 손상시킬 수 있으며, 플러그인이 제거된 후에도 남는 프로그램을 설치할 수 있습니다.      |
  | `unanalyzable-binary`             | 컴파일되었거나 읽을 수 없는 프로그램을 포함하고 있어 스캔이 그 동작을 확인할 수 없습니다.               |
  | `other`                           | 이 목록보다 새로운 우려 사항을 포함한 기타 모든 우려 사항입니다.                             |
</Accordion>

`plugin_` 접두사가 없는 `plugin_id`는 `400`을 반환합니다. 접두사가 있지만 확인되지 않거나, 다른 조직에 속하거나, 독립형 스킬을 가리키는 `plugin_id`는 `404`를 반환합니다.

### 플러그인 나열

`GET /v1/organizations/plugins`는 조직의 마켓플레이스와 멤버의 개인 마켓플레이스에 있는 조직의 모든 플러그인을 `created_at` 내림차순으로 나열합니다. `owner_type`(`organization` 또는 `user`), `owner_user_id`(`user_` 접두사가 붙으며, 멤버가 조직을 떠난 후를 포함한 해당 멤버의 플러그인), `marketplace_id`, 그리고 `created_at[gte]`, `created_at[gt]`, `created_at[lte]`, `created_at[lt]`(RFC 3339 타임스탬프)로 필터링할 수 있습니다. 필터는 AND로 결합됩니다. 조직에서 일치하는 항목이 없는 `marketplace_id` 또는 `owner_user_id`는 오류가 아닌 빈 페이지를 반환합니다. 응답은 [빠른 시작](https://platform.claude.com/docs/ko/manage-claude/plugins-api#quick-start)에 표시된 형식입니다. `read:plugins` 범위가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins?owner_type=organization&limit=20" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins list --owner-type organization --limit 20
  ```

  ```python Python
  client = anthropic.Anthropic()

  plugins = client.beta.organization.plugins.list(owner_type="organization", limit=20)

  # 필요에 따라 추가 페이지를 자동으로 가져옵니다.
  for plugin in plugins:
      print(f"{plugin.id}: {plugin.name}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const plugins = await client.beta.organization.plugins.list({
    owner_type: "organization",
    limit: 20
  });

  for await (const plugin of plugins) {
    console.log(`${plugin.id}: ${plugin.name}`);
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta.Organization.Plugins;

  AnthropicClient client = new();

  var page = await client.Beta.Organization.Plugins.List(
      new() { OwnerType = OwnerType.Organization, Limit = 20 }
  );

  await foreach (var plugin in page.Paginate())
  {
      Console.WriteLine($"{plugin.ID}: {plugin.Name}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  plugins := client.Beta.Organization.Plugins.ListAutoPaging(context.Background(), anthropic.BetaOrganizationPluginListParams{
  	OwnerType: anthropic.BetaOrganizationPluginListParamsOwnerTypeOrganization,
  	Limit:     anthropic.Int(20),
  })

  for plugins.Next() {
  	plugin := plugins.Current()
  	fmt.Printf("%s: %s\n", plugin.ID, plugin.Name)
  }
  if err := plugins.Err(); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.PluginListParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = PluginListParams.builder()
          .ownerType(PluginListParams.OwnerType.ORGANIZATION)
          .limit(20)
          .build();
      var plugins = client.beta().organization().plugins().list(params);

      for (var plugin : plugins.autoPager()) {
          IO.println(plugin.id() + ": " + plugin.name());
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\Organization\Plugins\PluginListParams\OwnerType;
  // ...

  $client = new Client();

  $plugins = $client->beta->organization->plugins->list(
      limit: 20,
      ownerType: OwnerType::ORGANIZATION,
  );

  // 이 페이지만 해당합니다. 다음 페이지는 page: $plugins->nextPage로 list()를 다시 호출하세요.
  foreach ($plugins->getItems() as $plugin) {
      echo "{$plugin->id}: {$plugin->name}\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  page = client.beta.organization.plugins.list(owner_type: :organization, limit: 20)

  page.auto_paging_each do |plugin|
    puts "#{plugin.id}: #{plugin.name}"
  end
  ```
</CodeGroup>

### 플러그인 생성

`POST /v1/organizations/plugins`는 조직 소유 플러그인과 그 첫 번째 버전을 한 번의 호출로 생성하며, 이 버전이 "served version"(제공 버전)이 됩니다. 본문은 `multipart/form-data`입니다. `files[]`는 하나의 `.zip` 또는 `.plugin` 아카이브이거나, 파일당 하나의 파트로 구성됩니다. 후자의 경우 각 파트의 파일 이름은 플러그인 내 해당 파일의 경로입니다(예: `.claude-plugin/plugin.json`). 선택적 필드는 `marketplace_id`(조직 소유의 `manual` 마켓플레이스이며, 기본값은 처음 사용할 때 생성되는 라이브러리 마켓플레이스입니다)와 `release_notes`(최대 5,000자이며, claude.ai의 버전 기록에 표시되고 버전에 반환됩니다)입니다. 플러그인의 `name`, `display_name`, `description`, `manifest_version`은 업로드된 매니페스트에서 가져오며, 업로드는 [업로드 요구 사항](https://platform.claude.com/docs/ko/manage-claude/plugins-api#upload-requirements)을 충족해야 합니다. 콘텐츠 스캔이 켜져 있으면 응답의 `content_scan.status`는 `processing`이며, 판정 결과는 비동기적으로 도착합니다. 플러그인을 반환합니다. `write:plugins` 스코프가 필요합니다.

아카이브 업로드:

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugins" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -F "files[]=@dist/sales-toolkit.zip" \
    -F "release_notes=First release"
  ```

  ```bash CLI
  ant beta:organization:plugins create \
    --file dist/sales-toolkit.zip \
    --release-notes "First release"
  ```

  ```python Python
  client = anthropic.Anthropic()

  with open("dist/sales-toolkit.zip", "rb") as archive:
      plugin = client.beta.organization.plugins.create(
          files=[archive],
          release_notes="First release",
      )

  print(f"id: {plugin.id}")
  print(f"served_version_id: {plugin.served_version_id}")
  ```

  ```typescript TypeScript
  import fs from "node:fs";

  const client = new Anthropic();

  const plugin = await client.beta.organization.plugins.create({
    files: [fs.createReadStream("dist/sales-toolkit.zip")],
    release_notes: "First release"
  });

  console.log(`id: ${plugin.id}`);
  console.log(`served_version_id: ${plugin.served_version_id}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var plugin = await client.Beta.Organization.Plugins.Create(
      new()
      {
          Files = [File.OpenRead("dist/sales-toolkit.zip")],
          ReleaseNotes = "First release",
      }
  );

  Console.WriteLine($"id: {plugin.ID}");
  Console.WriteLine($"served_version_id: {plugin.ServedVersionID}");
  ```

  ```go Go
  client := anthropic.NewClient()

  archive, err := os.Open("dist/sales-toolkit.zip")
  if err != nil {
  	log.Fatal(err)
  }
  defer archive.Close()

  plugin, err := client.Beta.Organization.Plugins.New(context.Background(), anthropic.BetaOrganizationPluginNewParams{
  	Files:        []io.Reader{archive},
  	ReleaseNotes: anthropic.String("First release"),
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", plugin.ID)
  fmt.Printf("served_version_id: %s\n", plugin.ServedVersionID)
  ```

  ```java Java
  import com.anthropic.core.MultipartField;
  import com.anthropic.models.beta.organization.plugins.PluginCreateParams;

  void main() throws Exception {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // `files[]` 파트를 직접 구성하여 아카이브가 파일 이름과 함께 전송되도록 합니다.
      // 업로드에는 파일 이름이 필요하기 때문입니다.
      var archive = MultipartField.<List<InputStream>>builder()
          .value(List.of(Files.newInputStream(Path.of("dist/sales-toolkit.zip"))))
          .filename("sales-toolkit.zip")
          .contentType("application/octet-stream")
          .build();
      var params = PluginCreateParams.builder()
          .files(archive)
          .releaseNotes("First release")
          .build();
      var plugin = client.beta().organization().plugins().create(params);

      IO.println("id: " + plugin.id());
      IO.println("served_version_id: " + plugin.servedVersionId());
  }
  ```

  ```php PHP
  use Anthropic\Core\FileParam;

  $client = new Client();

  $plugin = $client->beta->organization->plugins->create(
      files: [
          FileParam::fromResource(fopen('dist/sales-toolkit.zip', 'r')),
      ],
      releaseNotes: 'First release',
  );

  echo "id: {$plugin->id}\n";
  echo "served_version_id: {$plugin->servedVersionID}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin = client.beta.organization.plugins.create(
    files: [Pathname("dist/sales-toolkit.zip")],
    release_notes: "First release"
  )

  puts "id: #{plugin.id}"
  puts "served_version_id: #{plugin.served_version_id}"
  ```
</CodeGroup>

```json
{
  "type": "plugin",
  "id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  "name": "sales-toolkit",
  "display_name": "Sales Toolkit",
  "description": "Account research and call prep for the sales team.",
  "served_version_id": "pluginver_01Km7tL4pR9xF5sU2zV3jP6q",
  "served_version_pinned": false,
  "latest_version_id": "pluginver_01Km7tL4pR9xF5sU2zV3jP6q",
  "manifest_version": "1.4.0",
  "owner": { "type": "organization" },
  "marketplace_id": "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
  "created_by": { "type": "api_actor", "api_key_id": "apikey_01Nq9vN6rT2zH7uW4bX5mR8s" },
  "organization_installation_preference": "available",
  "organization_installation_preference_inherited": true,
  "content_scan": { "status": "processing", "assessment": null, "reason": null },
  "components": [
    {
      "type": "skill",
      "name": "account-research",
      "description": "Researches a customer account before a call."
    },
    { "type": "mcp_server", "name": "crm", "description": null }
  ],
  "reach": "remote",
  "created_at": "2026-09-01T17:04:11Z",
  "updated_at": "2026-09-01T17:04:11Z"
}
```

개별 파일을 지정한 마켓플레이스에 업로드합니다. 각 파일은 플러그인 내 경로로 첨부하세요(cURL 예제의 `;filename=` 접미사, SDK 예제의 파일 이름 인수). 기본 이름만으로 전송된 파일이 있으면 매니페스트를 찾을 수 없게 됩니다. TypeScript 및 Java SDK와 `ant` CLI는 아직 경로를 지정하여 파일을 첨부할 수 없으므로, 해당 예제에서는 대신 플러그인을 하나의 아카이브로 마켓플레이스에 업로드합니다:

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugins" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -F "files[]=@.claude-plugin/plugin.json;filename=.claude-plugin/plugin.json" \
    -F "files[]=@skills/account-research/SKILL.md;filename=skills/account-research/SKILL.md" \
    -F "marketplace_id=marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  ```

  ```bash CLI
  # CLI는 각 파일을 기본 이름(base name)만으로 전송하므로,
  # 플러그인을 하나의 아카이브로 묶어 업로드하세요.
  ant beta:organization:plugins create \
    --file dist/sales-toolkit.zip \
    --marketplace-id marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r
  ```

  ```python Python
  client = anthropic.Anthropic()

  # (filename, file) 튜플을 사용하면 플러그인 내 각 파일의 경로가 유지됩니다.
  # 파일 객체만 전달하면 기본 이름(base name)으로만 전송됩니다.
  with (
      open(".claude-plugin/plugin.json", "rb") as manifest,
      open("skills/account-research/SKILL.md", "rb") as skill_md,
  ):
      plugin = client.beta.organization.plugins.create(
          files=[
              (".claude-plugin/plugin.json", manifest),
              ("skills/account-research/SKILL.md", skill_md),
          ],
          marketplace_id="marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
      )

  print(f"id: {plugin.id}")
  print(f"served_version_id: {plugin.served_version_id}")
  ```

  ```typescript TypeScript
  import fs from "node:fs";

  const client = new Anthropic();

  // TypeScript SDK는 각 파일을 기본 이름(base name)으로 전송하므로,
  // 플러그인을 하나의 아카이브로 업로드하세요.
  const plugin = await client.beta.organization.plugins.create({
    files: [fs.createReadStream("dist/sales-toolkit.zip")],
    marketplace_id: "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  });

  console.log(`id: ${plugin.id}`);
  console.log(`served_version_id: ${plugin.served_version_id}`);
  ```

  ```csharp C#
  using Anthropic.Core;

  AnthropicClient client = new();

  // FileName은 플러그인 내 각 파일의 경로를 유지합니다. 이것이 없으면 FileStream은
  // 기본 이름(base name)만으로 전송됩니다.
  var plugin = await client.Beta.Organization.Plugins.Create(
      new()
      {
          Files =
          [
              new BinaryContent
              {
                  Stream = File.OpenRead(".claude-plugin/plugin.json"),
                  FileName = ".claude-plugin/plugin.json",
              },
              new BinaryContent
              {
                  Stream = File.OpenRead("skills/account-research/SKILL.md"),
                  FileName = "skills/account-research/SKILL.md",
              },
          ],
          MarketplaceID = "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
      }
  );

  Console.WriteLine($"id: {plugin.ID}");
  Console.WriteLine($"served_version_id: {plugin.ServedVersionID}");
  ```

  ```go Go
  client := anthropic.NewClient()

  manifest, err := os.Open(".claude-plugin/plugin.json")
  if err != nil {
  	log.Fatal(err)
  }
  defer manifest.Close()

  skillMd, err := os.Open("skills/account-research/SKILL.md")
  if err != nil {
  	log.Fatal(err)
  }
  defer skillMd.Close()

  // anthropic.File은 플러그인 내 각 파일의 경로를 파트의 filename으로 유지합니다.
  // *os.File을 그대로 사용하면 기본 이름으로 전송되어 매니페스트를 찾을 수 없습니다.
  plugin, err := client.Beta.Organization.Plugins.New(context.Background(), anthropic.BetaOrganizationPluginNewParams{
  	Files: []io.Reader{
  		anthropic.File(manifest, ".claude-plugin/plugin.json", "application/json"),
  		anthropic.File(skillMd, "skills/account-research/SKILL.md", "text/markdown"),
  	},
  	MarketplaceID: anthropic.String("marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"),
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", plugin.ID)
  fmt.Printf("served_version_id: %s\n", plugin.ServedVersionID)
  ```

  ```java Java
  import com.anthropic.core.MultipartField;
  import com.anthropic.models.beta.organization.plugins.PluginCreateParams;

  void main() throws Exception {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // PluginCreateParams의 `files` setter는 목록 전체에 대해 파일 이름을 하나만 받으므로,
      // 대신 플러그인을 하나의 아카이브로 업로드합니다. 즉, 업로드에 필요한
      // 아카이브 파일 이름을 담아 직접 구성한 단일 파트를 사용합니다.
      var archive = MultipartField.<List<InputStream>>builder()
          .value(List.of(Files.newInputStream(Path.of("dist/sales-toolkit.zip"))))
          .filename("sales-toolkit.zip")
          .contentType("application/octet-stream")
          .build();
      var params = PluginCreateParams.builder()
          .files(archive)
          .marketplaceId("marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r")
          .build();
      var plugin = client.beta().organization().plugins().create(params);

      IO.println("id: " + plugin.id());
      IO.println("served_version_id: " + plugin.servedVersionId());
  }
  ```

  ```php PHP
  use Anthropic\Core\FileParam;

  $client = new Client();

  $plugin = $client->beta->organization->plugins->create(
      files: [
          FileParam::fromResource(
              fopen('.claude-plugin/plugin.json', 'r'),
              filename: '.claude-plugin/plugin.json',
          ),
          FileParam::fromResource(
              fopen('skills/account-research/SKILL.md', 'r'),
              filename: 'skills/account-research/SKILL.md',
          ),
      ],
      marketplaceID: 'marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r',
  );

  echo "id: {$plugin->id}\n";
  echo "served_version_id: {$plugin->servedVersionID}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  # `filename:`을 지정한 FilePart는 플러그인 내 각 파일의 경로를 유지합니다.
  # Pathname만 단독으로 전달하면 파일의 기본 이름(base name)으로만 전송됩니다.
  plugin = client.beta.organization.plugins.create(
    files: [
      Anthropic::FilePart.new(
        Pathname(".claude-plugin/plugin.json"),
        filename: ".claude-plugin/plugin.json"
      ),
      Anthropic::FilePart.new(
        Pathname("skills/account-research/SKILL.md"),
        filename: "skills/account-research/SKILL.md"
      )
    ],
    marketplace_id: "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  )

  puts "id: #{plugin.id}"
  puts "served_version_id: #{plugin.served_version_id}"
  ```
</CodeGroup>

[업로드 요구 사항](https://platform.claude.com/docs/ko/manage-claude/plugins-api#upload-requirements)을 위반하는 업로드에 대한 `400`(요청 본문이 200 MB를 초과하는 경우 `413`)과 공통 응답(`marketplace_id`가 멤버의 개인 마켓플레이스인 경우 `403`. [오류 응답](https://platform.claude.com/docs/ko/manage-claude/plugins-api#error-responses) 참조) 외에도, 생성 요청은 다음과 같은 이유로 실패할 수 있습니다:

| 상태                         | 원인                                                            | 조치 방법                                                                                                                                              |
| -------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| 404                        | `marketplace_id`가 조직의 마켓플레이스가 아닙니다.                           | [마켓플레이스 목록 조회](https://platform.claude.com/docs/ko/manage-claude/plugins-api#list-marketplaces)에서 ID를 가져오세요.                                       |
| 400                        | 마켓플레이스가 Git에서 동기화되거나, 이미 500개의 플러그인과 스킬을 보유하고 있습니다.           | `manual` 마켓플레이스에 업로드하거나, 대신 리포지토리를 변경하세요.                                                                                                          |
| 409 `plugin_name_taken`    | 해당 마켓플레이스에서 이미 사용 중인 이름입니다.                                   | `details.plugin_id`로 계속 진행하거나(해당 플러그인에 버전 업로드), 매니페스트의 `name`을 변경하세요.                                                                              |
| 409 `skill_name_taken`     | 플러그인이 라이브러리 마켓플레이스에 추가되는데, 그 스킬 중 하나가 조직 스킬과 같은 이름을 가지고 있습니다. | 스킬 이름을 변경하거나, claude.ai에서 조직 스킬을 제거하세요.                                                                                                            |
| 409 (`error_code` 없음)      | 같은 마켓플레이스에 같은 이름으로 진행 중인 다른 업로드가 있습니다.                        | 잠시 후 다시 시도하세요.                                                                                                                                     |
| 503 `registration_pending` | 플러그인은 생성되었지만 등록이 완료되지 않았습니다.                                  | 다시 전송하지 말고, 같은 파일을 `details.plugin_id`의 버전으로 업로드하세요([업로드 재시도](https://platform.claude.com/docs/ko/manage-claude/plugins-api#retrying-uploads) 참조). |

### 플러그인 조회

`GET /v1/organizations/plugins/{plugin_id}`는 하나의 플러그인을 반환합니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins retrieve \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL
  ```

  ```python Python
  client = anthropic.Anthropic()

  plugin = client.beta.organization.plugins.retrieve("plugin_01Hq3vX8kZcN2mB7pR4tY9wL")

  print(f"id: {plugin.id}")
  print(f"name: {plugin.name}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const plugin = await client.beta.organization.plugins.retrieve(
    "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  );

  console.log(`id: ${plugin.id}`);
  console.log(`name: ${plugin.name}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var plugin = await client.Beta.Organization.Plugins.Retrieve("plugin_01Hq3vX8kZcN2mB7pR4tY9wL");

  Console.WriteLine($"id: {plugin.ID}");
  Console.WriteLine($"name: {plugin.Name}");
  ```

  ```go Go
  client := anthropic.NewClient()

  plugin, err := client.Beta.Organization.Plugins.Get(
  	context.Background(),
  	"plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	anthropic.BetaOrganizationPluginGetParams{},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", plugin.ID)
  fmt.Printf("name: %s\n", plugin.Name)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  var plugin = client.beta().organization().plugins()
      .retrieve("plugin_01Hq3vX8kZcN2mB7pR4tY9wL");

  IO.println("id: " + plugin.id());
  IO.println("name: " + plugin.name());
  ```

  ```php PHP
  $client = new Client();

  $plugin = $client->beta->organization->plugins->retrieve(
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
  );

  echo "id: {$plugin->id}\n";
  echo "name: {$plugin->name}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  plugin = client.beta.organization.plugins.retrieve(plugin_id)

  puts "id: #{plugin.id}"
  puts "name: #{plugin.name}"
  ```
</CodeGroup>

### 제공 버전 변경

`POST /v1/organizations/plugins/{plugin_id}`는 조직 소유 플러그인의 어떤 버전을 멤버에게 제공할지 변경합니다. 롤백하려면 이전 버전을 전달하고, 제공되지 않은 채 저장된 빌드를 승격하려면 더 새로운 버전을 전달하세요. 이렇게 하면 플러그인이 고정되며, 고정된 플러그인은 현재 여기서든 claude.ai에서든 고정을 해제할 수 없습니다([버전과 제공 버전](https://platform.claude.com/docs/ko/manage-claude/plugins-api#versions-and-the-served-version) 참조). 업데이트 가능한 유일한 필드는 `served_version_id`이며 필수입니다. 변경 사항은 응답이 반환되기 전에 멤버에게 적용되며 버전을 생성하지 않습니다. 콘텐츠 스캔이 켜져 있으면 해당 버전은 멤버에게 제공될 수 있는 버전이어야 합니다([콘텐츠 스캔](https://platform.claude.com/docs/ko/manage-claude/plugins-api#content-scanning) 참조). 고정된 플러그인에 이미 제공 중인 버전을 전달하면 아무것도 변경되지 않습니다. 고정되지 않은 플러그인에 이를 전달하면 해당 버전으로 고정되므로, 이후 업로드는 더 이상 자동으로 제공되지 않습니다. 고정은 대기도 종료합니다. 콘텐츠 스캔을 기다리던 버전은 저장된 상태로 유지되며, 누군가 선택하는 경우에만 제공됩니다. 플러그인을 반환합니다. `write:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL" \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -d '{"served_version_id": "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p"}'
  ```

  ```bash CLI
  ant beta:organization:plugins update \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --served-version-id pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p
  ```

  ```python Python
  client = anthropic.Anthropic()

  plugin = client.beta.organization.plugins.update(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      served_version_id="pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p",
  )

  print(f"id: {plugin.id}")
  print(f"served_version_id: {plugin.served_version_id}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const plugin = await client.beta.organization.plugins.update(
    "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
    { served_version_id: "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p" }
  );

  console.log(`id: ${plugin.id}`);
  console.log(`served_version_id: ${plugin.served_version_id}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var plugin = await client.Beta.Organization.Plugins.Update(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      new() { ServedVersionID = "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p" }
  );

  Console.WriteLine($"id: {plugin.ID}");
  Console.WriteLine($"served_version_id: {plugin.ServedVersionID}");
  ```

  ```go Go
  client := anthropic.NewClient()

  plugin, err := client.Beta.Organization.Plugins.Update(
  	context.Background(),
  	"plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	anthropic.BetaOrganizationPluginUpdateParams{
  		ServedVersionID: "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p",
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", plugin.ID)
  fmt.Printf("served_version_id: %s\n", plugin.ServedVersionID)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.PluginUpdateParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = PluginUpdateParams.builder()
          .servedVersionId("pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p")
          .build();
      var plugin = client.beta().organization().plugins()
          .update("plugin_01Hq3vX8kZcN2mB7pR4tY9wL", params);

      IO.println("id: " + plugin.id());
      IO.println("served_version_id: " + plugin.servedVersionId());
  }
  ```

  ```php PHP
  $client = new Client();

  $plugin = $client->beta->organization->plugins->update(
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
      servedVersionID: 'pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p',
  );

  echo "id: {$plugin->id}\n";
  echo "served_version_id: {$plugin->servedVersionID}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  plugin = client.beta.organization.plugins.update(
    plugin_id,
    served_version_id: "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p"
  )

  puts "id: #{plugin.id}"
  puts "served_version_id: #{plugin.served_version_id}"
  ```
</CodeGroup>

```json
{
  "type": "plugin",
  "id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  "name": "sales-toolkit",
  "display_name": "Sales Toolkit",
  "description": "Account research and call prep for the sales team.",
  "served_version_id": "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p",
  "served_version_pinned": true,
  "latest_version_id": "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p",
  "manifest_version": "1.5.0",
  "owner": { "type": "organization" },
  "marketplace_id": "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
  "created_by": { "type": "api_actor", "api_key_id": "apikey_01Nq9vN6rT2zH7uW4bX5mR8s" },
  "organization_installation_preference": "available",
  "organization_installation_preference_inherited": true,
  "content_scan": { "status": "completed", "assessment": "pass", "reason": null },
  "components": [
    {
      "type": "skill",
      "name": "account-research",
      "description": "Researches a customer account before a call."
    },
    { "type": "mcp_server", "name": "crm", "description": null },
    {
      "type": "command",
      "name": "call-prep",
      "description": "Builds a one-page brief for an upcoming call."
    }
  ],
  "reach": "remote",
  "created_at": "2026-09-01T17:04:11Z",
  "updated_at": "2026-09-16T10:02:45Z"
}
```

공통 응답(멤버 소유 플러그인에 대한 `403`, 멤버에게 제공될 수 없는 버전에 대한 `409 scan_pending` 또는 `400 scan_failed`. [오류 응답](https://platform.claude.com/docs/ko/manage-claude/plugins-api#error-responses) 참조) 외에도, 요청은 다음과 같은 이유로 실패할 수 있습니다:

| 상태                     | 원인                                                                                                          | 조치 방법                                                                                                               |
| ---------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| 400                    | 본문에 `served_version_id`가 없거나, `null`로 설정되었거나, 다른 필드가 포함되어 있습니다. 또는 값에 `pluginver_` 접두사가 없거나 값이 `latest`입니다. | 정확히 `{"served_version_id": "pluginver_…"}`를 전송하세요.                                                                  |
| 404                    | `served_version_id`가 이 플러그인의 버전이 아닙니다.                                                                      | [플러그인 버전 목록 조회](https://platform.claude.com/docs/ko/manage-claude/plugins-api#list-a-plugins-versions)에서 ID를 가져오세요. |
| 409 (`error_code` 없음)  | 이 플러그인에 대한 업로드 또는 다른 제공 버전 변경이 아직 진행 중입니다.                                                                  | 잠시 후 다시 시도하세요.                                                                                                      |
| 409 `skill_name_taken` | 플러그인이 라이브러리 마켓플레이스에 있고, 해당 버전에 현재 조직 스킬이 사용 중인 이름의 스킬이 있습니다.                                                | 다른 버전을 선택하거나, 스킬 중 하나의 이름을 변경하세요.                                                                                   |

### 플러그인 삭제

`DELETE /v1/organizations/plugins/{plugin_id}`는 claude.ai에서 관리자가 삭제하는 것과 마찬가지로 플러그인과 그 플러그인이 보유한 모든 버전을 영구적으로 삭제합니다. 이 작업은 `manual` 마켓플레이스에 있는 모든 플러그인에 적용되며, 멤버의 플러그인도 포함됩니다. 해당 멤버가 이후 조직을 떠났더라도 마찬가지입니다. 삭제가 반환되면 플러그인, 그 버전 및 파일은 모든 읽기 작업에서 사라지며, 더 이상 멤버에게 제공되지 않습니다. 조직 소유 플러그인의 설치 설정은 플러그인과 함께 제거됩니다. 멤버 소유 플러그인의 공유는 철회되며, 소유자에게서도 사라집니다. Git에서 동기화되는 마켓플레이스에 있는 플러그인은 `400`을 반환합니다. 리포지토리에서 제거하거나, claude.ai에서 마켓플레이스를 제거하세요. `write:plugins` 스코프가 필요합니다.

삭제는 되돌릴 수 없으며, 버전별 삭제는 없습니다. 대신 조직 소유 플러그인을 되돌릴 수 있는 방식으로 보류하려면, 조직 전체 설치 설정을 `not_available`로 설정하고(마켓플레이스의 기본값을 상속하던 플러그인은 자체 설정을 갖게 되며, 나중에 [해당 조직 전체 설정을 제거](https://platform.claude.com/docs/ko/manage-claude/plugins-api#remove-an-installation-setting)하면 플러그인이 기본값으로 돌아갑니다), `GET /v1/organizations/plugins/{plugin_id}/installation_settings`가 나열하는 모든 그룹 설정을 제거(또는 `not_available`로 설정)하세요. 그룹의 설정은 해당 그룹 멤버에 대해 조직 전체 값을 재정의하기 때문입니다. 이러한 쓰기는 병렬이 아닌 하나씩 차례로 전송하세요([설치 설정 지정](https://platform.claude.com/docs/ko/manage-claude/plugins-api#set-an-installation-setting) 참조). 멤버 소유 플러그인은 삭제하는 것 외에는 이 API를 통해 보류할 수 없으며, 삭제도 마켓플레이스가 `manual`인 경우에만 가능합니다.

<CodeGroup>
  ```bash cURL
  curl -X DELETE "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins delete --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL
  ```

  ```python Python
  client = anthropic.Anthropic()

  deleted_plugin = client.beta.organization.plugins.delete(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  )

  print(f"id: {deleted_plugin.id}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const deletedPlugin = await client.beta.organization.plugins.delete(
    "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  );

  console.log(`id: ${deletedPlugin.id}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var deletedPlugin = await client.Beta.Organization.Plugins.Delete(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  );

  Console.WriteLine($"id: {deletedPlugin.ID}");
  ```

  ```go Go
  client := anthropic.NewClient()

  deletedPlugin, err := client.Beta.Organization.Plugins.Delete(
  	context.Background(),
  	"plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	anthropic.BetaOrganizationPluginDeleteParams{},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", deletedPlugin.ID)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  var deletedPlugin = client.beta().organization().plugins()
      .delete("plugin_01Hq3vX8kZcN2mB7pR4tY9wL");

  IO.println("id: " + deletedPlugin.id());
  ```

  ```php PHP
  $client = new Client();

  $deletedPlugin = $client->beta->organization->plugins->delete(
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
  );

  echo "id: {$deletedPlugin->id}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  deleted_plugin = client.beta.organization.plugins.delete(plugin_id)

  puts "id: #{deleted_plugin.id}"
  ```
</CodeGroup>

```json
{ "type": "plugin_deleted", "id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL" }
```

## 플러그인 버전

플러그인 버전은 한 번의 업로드로 생성된 플러그인 파일의 변경 불가능한 스냅샷입니다([버전 생성](https://platform.claude.com/docs/ko/manage-claude/plugins-api#create-a-version) 응답에서 전체 객체를 확인할 수 있습니다). 버전의 필드는 이 버전에 대한 플러그인의 제공 버전 필드(`display_name`, `description`, `manifest_version`, `content_scan`, `components`, `reach`)를 그대로 반영하며, 여기에 `release_notes`(업로드 시 제공된 내용이며, claude.ai의 버전 기록에 표시됨)와 `created_by`(업로드한 사람)가 추가됩니다.

`pluginver_` 접두사가 없는 `{version}`은 `400`을 반환합니다(명시된 경우의 리터럴 `latest`는 예외). 접두사가 있지만 해당 플러그인의 버전을 식별하지 못하는 값은 `404`를 반환합니다.

### 플러그인 버전 목록 조회

`GET /v1/organizations/plugins/{plugin_id}/versions`는 플러그인의 버전을 `created_at` 내림차순으로 나열합니다. 첫 번째 항목은 `latest_version_id`가 식별하는 버전입니다. `limit`은 1에서 1,000 사이입니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/versions?limit=50" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins:versions list \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --limit 50
  ```

  ```python Python
  client = anthropic.Anthropic()

  versions = client.beta.organization.plugins.versions.list(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL", limit=50
  )

  # 필요에 따라 추가 페이지를 자동으로 가져옵니다.
  for version in versions:
      print(f"{version.id}: {version.manifest_version}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const versions = await client.beta.organization.plugins.versions.list(
    "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
    { limit: 50 }
  );

  for await (const version of versions) {
    console.log(`${version.id}: ${version.manifest_version}`);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  var page = await client.Beta.Organization.Plugins.Versions.List(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      new() { Limit = 50 }
  );

  await foreach (var version in page.Paginate())
  {
      Console.WriteLine($"{version.ID}: {version.ManifestVersion}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  versions := client.Beta.Organization.Plugins.Versions.ListAutoPaging(
  	context.Background(),
  	"plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	anthropic.BetaOrganizationPluginVersionListParams{
  		Limit: anthropic.Int(50),
  	},
  )

  for versions.Next() {
  	version := versions.Current()
  	fmt.Printf("%s: %s\n", version.ID, version.ManifestVersion)
  }
  if err := versions.Err(); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.versions.VersionListParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = VersionListParams.builder()
          .limit(50)
          .build();
      var versions = client.beta().organization().plugins().versions()
          .list("plugin_01Hq3vX8kZcN2mB7pR4tY9wL", params);

      for (var version : versions.autoPager()) {
          IO.println(version.id() + ": " + version.manifestVersion().orElse(null));
      }
  }
  ```

  ```php PHP
  $client = new Client();

  $versions = $client->beta->organization->plugins->versions->list(
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
      limit: 50,
  );

  // 이 페이지만 해당합니다. 다음 페이지는 page: $versions->nextPage로 list()를 다시 호출하세요.
  foreach ($versions->getItems() as $version) {
      echo "{$version->id}: {$version->manifestVersion}\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  page = client.beta.organization.plugins.versions.list(plugin_id, limit: 50)

  page.auto_paging_each do |version|
    puts "#{version.id}: #{version.manifest_version}"
  end
  ```
</CodeGroup>

### 버전 생성

`POST /v1/organizations/plugins/{plugin_id}/versions`는 `manual` 마켓플레이스에 있는 조직 소유 플러그인에 버전을 추가합니다. 본문은 `multipart/form-data`이며, [플러그인 생성](https://platform.claude.com/docs/ko/manage-claude/plugins-api#create-a-plugin)과 동일한 `files[]` 및 `release_notes` 필드, [업로드 요구 사항](https://platform.claude.com/docs/ko/manage-claude/plugins-api#upload-requirements), 그리고 파일, 매니페스트, 아카이브, 크기 오류를 가집니다. 업로드된 이름(매니페스트의 `name`)은 플러그인의 `name`과 같아야 합니다. 플러그인이 고정되지 않은 경우 새 버전은 일반적으로 저장되는 즉시 제공됩니다. 고정된 경우 버전은 저장되지만 제공 버전을 해당 버전으로 변경할 때까지 제공되지 않습니다. 확인하려면 응답의 `id`를 플러그인의 `served_version_id`와 비교하세요. 버전을 반환합니다. `write:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/versions" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -F "files[]=@dist/sales-toolkit.zip" \
    -F "release_notes=Adds the call-prep command."
  ```

  ```bash CLI
  ant beta:organization:plugins:versions create \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --file dist/sales-toolkit.zip \
    --release-notes "Adds the call-prep command."
  ```

  ```python Python
  client = anthropic.Anthropic()

  with open("dist/sales-toolkit.zip", "rb") as archive:
      version = client.beta.organization.plugins.versions.create(
          "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
          files=[archive],
          release_notes="Adds the call-prep command.",
      )

  print(f"id: {version.id}")
  print(f"manifest_version: {version.manifest_version}")
  ```

  ```typescript TypeScript
  import fs from "node:fs";

  const client = new Anthropic();

  const version = await client.beta.organization.plugins.versions.create(
    "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
    {
      files: [fs.createReadStream("dist/sales-toolkit.zip")],
      release_notes: "Adds the call-prep command."
    }
  );

  console.log(`id: ${version.id}`);
  console.log(`manifest_version: ${version.manifest_version}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var version = await client.Beta.Organization.Plugins.Versions.Create(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      new()
      {
          Files = [File.OpenRead("dist/sales-toolkit.zip")],
          ReleaseNotes = "Adds the call-prep command.",
      }
  );

  Console.WriteLine($"id: {version.ID}");
  Console.WriteLine($"manifest_version: {version.ManifestVersion}");
  ```

  ```go Go
  client := anthropic.NewClient()

  archive, err := os.Open("dist/sales-toolkit.zip")
  if err != nil {
  	log.Fatal(err)
  }
  defer archive.Close()

  version, err := client.Beta.Organization.Plugins.Versions.New(
  	context.Background(),
  	"plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	anthropic.BetaOrganizationPluginVersionNewParams{
  		Files:        []io.Reader{archive},
  		ReleaseNotes: anthropic.String("Adds the call-prep command."),
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", version.ID)
  fmt.Printf("manifest_version: %s\n", version.ManifestVersion)
  ```

  ```java Java
  import com.anthropic.core.MultipartField;
  import com.anthropic.models.beta.organization.plugins.versions.VersionCreateParams;

  void main() throws Exception {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // `files[]` 파트를 직접 구성하여 아카이브가 파일 이름과 함께 전송되도록 합니다.
      // 업로드에는 파일 이름이 필요하기 때문입니다.
      var archive = MultipartField.<List<InputStream>>builder()
          .value(List.of(Files.newInputStream(Path.of("dist/sales-toolkit.zip"))))
          .filename("sales-toolkit.zip")
          .contentType("application/octet-stream")
          .build();
      var params = VersionCreateParams.builder()
          .files(archive)
          .releaseNotes("Adds the call-prep command.")
          .build();
      var version = client.beta().organization().plugins().versions()
          .create("plugin_01Hq3vX8kZcN2mB7pR4tY9wL", params);

      IO.println("id: " + version.id());
      IO.println("manifest_version: " + version.manifestVersion().orElse(null));
  }
  ```

  ```php PHP
  use Anthropic\Core\FileParam;

  $client = new Client();

  $version = $client->beta->organization->plugins->versions->create(
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
      files: [
          FileParam::fromResource(fopen('dist/sales-toolkit.zip', 'r')),
      ],
      releaseNotes: 'Adds the call-prep command.',
  );

  echo "id: {$version->id}\n";
  echo "manifest_version: {$version->manifestVersion}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  version = client.beta.organization.plugins.versions.create(
    plugin_id,
    files: [Pathname("dist/sales-toolkit.zip")],
    release_notes: "Adds the call-prep command."
  )

  puts "id: #{version.id}"
  puts "manifest_version: #{version.manifest_version}"
  ```
</CodeGroup>

```json
{
  "type": "plugin_version",
  "id": "pluginver_01Jd5sK2nQ8wE4rT6yU1iO3p",
  "plugin_id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  "display_name": "Sales Toolkit",
  "description": "Account research and call prep for the sales team.",
  "manifest_version": "1.5.0",
  "release_notes": "Adds the call-prep command.",
  "created_by": { "type": "api_actor", "api_key_id": "apikey_01Nq9vN6rT2zH7uW4bX5mR8s" },
  "content_scan": { "status": "processing", "assessment": null, "reason": null },
  "components": [
    {
      "type": "skill",
      "name": "account-research",
      "description": "Researches a customer account before a call."
    },
    { "type": "mcp_server", "name": "crm", "description": null },
    {
      "type": "command",
      "name": "call-prep",
      "description": "Builds a one-page brief for an upcoming call."
    }
  ],
  "reach": "remote",
  "created_at": "2026-09-15T14:12:30Z"
}
```

[업로드 요구 사항](https://platform.claude.com/docs/ko/manage-claude/plugins-api#upload-requirements)을 위반하는 업로드에 대한 `400`(요청 본문이 200 MB를 초과하는 경우 `413`)과 공통 응답(멤버 소유 플러그인에 대한 `403`. [오류 응답](https://platform.claude.com/docs/ko/manage-claude/plugins-api#error-responses) 참조) 외에도, 요청은 다음과 같은 이유로 실패할 수 있습니다:

| 상태                         | 원인                                                      | 조치 방법                                                                                                                                               |
| -------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400                        | 플러그인이 Git에서 동기화되는 마켓플레이스에 있거나, 업로드된 이름이 플러그인의 이름과 다릅니다. | 대신 리포지토리를 변경하거나, 매니페스트의 `name`을 수정하세요.                                                                                                              |
| 409 (`error_code` 없음)      | 이 플러그인에 대한 다른 업로드 또는 제공 버전 변경이 아직 진행 중입니다.              | 잠시 후 다시 시도하세요.                                                                                                                                      |
| 409 `skill_name_taken`     | 플러그인이 라이브러리 마켓플레이스에 있고, 해당 버전이 조직 스킬과 같은 이름의 스킬을 추가합니다. | 스킬 이름을 변경하거나, claude.ai에서 조직 스킬을 제거하세요.                                                                                                             |
| 503 `registration_pending` | 버전은 저장되었지만 등록이 완료되지 않았습니다.                              | 응답에 `x-should-retry: true`가 포함되어 있으면 같은 요청을 다시 전송하세요([업로드 재시도](https://platform.claude.com/docs/ko/manage-claude/plugins-api#retrying-uploads) 참조). |

### 버전 조회

`GET /v1/organizations/plugins/{plugin_id}/versions/{version}`은 하나의 버전을 반환합니다. `{version}`은 버전 ID이거나, 요청 시점에 `latest_version_id`가 식별하는 버전을 나타내는 `latest`입니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/versions/latest" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins:versions retrieve \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --version latest
  ```

  ```python Python
  client = anthropic.Anthropic()

  version = client.beta.organization.plugins.versions.retrieve(
      "latest",
      plugin_id="plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  )

  print(f"id: {version.id}")
  print(f"manifest_version: {version.manifest_version}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const version = await client.beta.organization.plugins.versions.retrieve("latest", {
    plugin_id: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  });

  console.log(`id: ${version.id}`);
  console.log(`manifest_version: ${version.manifest_version}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var version = await client.Beta.Organization.Plugins.Versions.Retrieve(
      "latest",
      new() { PluginID = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL" }
  );

  Console.WriteLine($"id: {version.ID}");
  Console.WriteLine($"manifest_version: {version.ManifestVersion}");
  ```

  ```go Go
  client := anthropic.NewClient()

  version, err := client.Beta.Organization.Plugins.Versions.Get(
  	context.Background(),
  	"latest",
  	anthropic.BetaOrganizationPluginVersionGetParams{
  		PluginID: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", version.ID)
  fmt.Printf("manifest_version: %s\n", version.ManifestVersion)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.versions.VersionRetrieveParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = VersionRetrieveParams.builder()
          .pluginId("plugin_01Hq3vX8kZcN2mB7pR4tY9wL")
          .build();
      var version = client.beta().organization().plugins().versions()
          .retrieve("latest", params);

      IO.println("id: " + version.id());
      IO.println("manifest_version: " + version.manifestVersion().orElse(null));
  }
  ```

  ```php PHP
  $client = new Client();

  $version = $client->beta->organization->plugins->versions->retrieve(
      version: 'latest',
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
  );

  echo "id: {$version->id}\n";
  echo "manifest_version: {$version->manifestVersion}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  version = client.beta.organization.plugins.versions.retrieve("latest", plugin_id: plugin_id)

  puts "id: #{version.id}"
  puts "manifest_version: #{version.manifest_version}"
  ```
</CodeGroup>

### 버전 파일 다운로드

`GET /v1/organizations/plugins/{plugin_id}/versions/{version}/content`는 버전의 파일을 저장된 `.zip` 아카이브(`Content-Type: application/zip`)로 다운로드합니다. 아카이브는 콘텐츠 스캔 결과와 관계없이 반환되므로, 멤버에게 보류된 버전도 검사할 수 있습니다. 아카이브는 저장된 그대로 제공되므로, `manual` 마켓플레이스에 있는 조직 소유 플러그인의 경우 현재 업로드 요구 사항을 충족한다면 변경 없이 새 버전으로 다시 업로드할 수 있습니다. `{version}`은 `latest`가 아닌 버전 ID여야 합니다. 먼저 플러그인의 `served_version_id` 또는 `latest_version_id`를 읽거나, `GET /v1/organizations/plugins/{plugin_id}/versions/latest`로 `latest`를 확인하세요. `Content-Disposition` 파일 이름은 플러그인 이름에서 파생되며 고유하지 않으므로, 저장하는 파일의 이름은 플러그인 ID와 버전 ID를 기준으로 지정하세요. `read:plugins` 스코프가 필요합니다.

**멤버 소유** 플러그인의 아카이브를 다운로드하면 Compliance API Activity Feed에 `claude_plugin_archive_accessed` 이벤트가 기록되며, 이 이벤트는 키(`api_actor`로), 플러그인과 그 마켓플레이스, 버전, 소유 멤버를 ID로 식별합니다. 이름은 포함되지 않습니다. 조직 소유 플러그인의 아카이브를 다운로드하면 아무것도 기록되지 않습니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/versions/pluginver_01Km7tL4pR9xF5sU2zV3jP6q/content" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -o plugin_01Hq3vX8kZcN2mB7pR4tY9wL_pluginver_01Km7tL4pR9xF5sU2zV3jP6q.zip
  ```

  ```bash CLI
  ant beta:organization:plugins:versions download \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --version pluginver_01Km7tL4pR9xF5sU2zV3jP6q \
    --output plugin_01Hq3vX8kZcN2mB7pR4tY9wL_pluginver_01Km7tL4pR9xF5sU2zV3jP6q.zip
  ```

  ```python Python
  client = anthropic.Anthropic()

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  version_id = "pluginver_01Km7tL4pR9xF5sU2zV3jP6q"

  with client.beta.organization.plugins.versions.with_streaming_response.download(
      version_id,
      plugin_id=plugin_id,
  ) as response:
      response.stream_to_file(f"{plugin_id}_{version_id}.zip")
  ```

  ```typescript TypeScript
  import { writeFile } from "node:fs/promises";

  const client = new Anthropic();

  const pluginId = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL";
  const versionId = "pluginver_01Km7tL4pR9xF5sU2zV3jP6q";

  const response = await client.beta.organization.plugins.versions.download(versionId, {
    plugin_id: pluginId
  });
  if (!response.body) {
    throw new Error("The download returned no body");
  }

  await writeFile(`${pluginId}_${versionId}.zip`, response.body);
  ```

  ```csharp C#
  AnthropicClient client = new();

  using var response = await client.Beta.Organization.Plugins.Versions.Download(
      "pluginver_01Km7tL4pR9xF5sU2zV3jP6q",
      new() { PluginID = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL" }
  );

  using var content = await response.ReadAsStream();
  using var file = File.Create(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL_pluginver_01Km7tL4pR9xF5sU2zV3jP6q.zip"
  );
  await content.CopyToAsync(file);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Organization.Plugins.Versions.Download(
  	context.Background(),
  	"pluginver_01Km7tL4pR9xF5sU2zV3jP6q",
  	anthropic.BetaOrganizationPluginVersionDownloadParams{
  		PluginID: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }
  defer response.Body.Close()

  out, err := os.Create("plugin_01Hq3vX8kZcN2mB7pR4tY9wL_pluginver_01Km7tL4pR9xF5sU2zV3jP6q.zip")
  if err != nil {
  	log.Fatal(err)
  }
  defer out.Close()

  if _, err := io.Copy(out, response.Body); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  import com.anthropic.core.http.HttpResponse;
  import com.anthropic.models.beta.organization.plugins.versions.VersionDownloadParams;

  void main() throws Exception {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = VersionDownloadParams.builder()
          .pluginId("plugin_01Hq3vX8kZcN2mB7pR4tY9wL")
          .build();
      try (HttpResponse response = client.beta().organization().plugins().versions()
              .download("pluginver_01Km7tL4pR9xF5sU2zV3jP6q", params)) {
          Files.copy(
              response.body(),
              Path.of("plugin_01Hq3vX8kZcN2mB7pR4tY9wL_pluginver_01Km7tL4pR9xF5sU2zV3jP6q.zip"),
              StandardCopyOption.REPLACE_EXISTING);
      }
  }
  ```

  ```php PHP
  $client = new Client();

  // download()는 전체 아카이브를 하나의 문자열로 반환하므로, 원시(raw)
  // 응답을 받아 본문을 청크 단위로 디스크에 복사합니다.
  $response = $client->beta->organization->plugins->versions->raw->download(
      version: 'pluginver_01Km7tL4pR9xF5sU2zV3jP6q',
      params: ['pluginID' => 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL'],
  );

  $archive = $response->getBody();
  $file = fopen('plugin_01Hq3vX8kZcN2mB7pR4tY9wL_pluginver_01Km7tL4pR9xF5sU2zV3jP6q.zip', 'wb');
  while (!$archive->eof()) {
      fwrite($file, $archive->read(1024 * 1024));
  }
  fclose($file);
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  version_id = "pluginver_01Km7tL4pR9xF5sU2zV3jP6q"
  archive = client.beta.organization.plugins.versions.download(version_id, plugin_id: plugin_id)

  # SDK는 아카이브를 이미 메모리로 읽어 들인 StringIO 형태로 반환합니다.
  File.binwrite("#{plugin_id}_#{version_id}.zip", archive.string)
  ```
</CodeGroup>

## 플러그인 설치 설정

이 엔드포인트는 조직 소유 플러그인에 적용됩니다. 멤버 소유 플러그인에 대해서는 `404`를 반환하며, 멤버 소유 플러그인에는 대신 [공유](https://platform.claude.com/docs/ko/manage-claude/plugins-api#plugin-shares)가 있습니다. `{target}`은 플러그인의 조직 전체 설정을 나타내는 리터럴 `organization`이거나, 해당 그룹의 설정을 나타내는 그룹의 `rbac_group_` ID입니다. 그 외의 값은 `400`을 반환합니다. 그룹 ID는 `GET /v1/organizations/rbac_groups`(스코프 `read:rbac_groups`. [사용자 관리](https://platform.claude.com/docs/ko/manage-claude/user-management#groups) 참조)에서 가져옵니다. 설정에는 자체 `id`가 없습니다. 설정은 `(plugin_id, target)`으로 지정되며, 설정에는 행위자가 기록되지 않습니다(행위자는 `plugin_installation_preference_updated` 활동 이벤트에 기록됩니다).

### 플러그인 설치 설정 목록 조회

`GET /v1/organizations/plugins/{plugin_id}/installation_settings`는 조직 소유 플러그인이 보유한 설정을 `created_at` 내림차순으로 나열합니다. 여기에는 플러그인 자체의 조직 전체 설정(마켓플레이스의 기본값을 상속하는 동안에는 없음)과 각 그룹의 설정이 포함됩니다. `target_type`(`organization` 또는 `rbac_group`)으로 필터링할 수 있습니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/installation_settings" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins:installation-settings list \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL
  ```

  ```python Python
  client = anthropic.Anthropic()

  settings = client.beta.organization.plugins.installation_settings.list(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  )

  # 필요에 따라 추가 페이지를 자동으로 가져옵니다.
  for setting in settings:
      print(f"{setting.plugin_id}: {setting.installation_preference}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const settings = await client.beta.organization.plugins.installationSettings.list(
    "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  );

  for await (const setting of settings) {
    console.log(`${setting.plugin_id}: ${setting.installation_preference}`);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  var page = await client.Beta.Organization.Plugins.InstallationSettings.List(
      "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  );

  await foreach (var setting in page.Paginate())
  {
      Console.WriteLine($"{setting.PluginID}: {setting.InstallationPreference.Raw()}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  settings := client.Beta.Organization.Plugins.InstallationSettings.ListAutoPaging(
  	context.Background(),
  	"plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	anthropic.BetaOrganizationPluginInstallationSettingListParams{},
  )

  for settings.Next() {
  	setting := settings.Current()
  	fmt.Printf("%s: %s\n", setting.PluginID, setting.InstallationPreference)
  }
  if err := settings.Err(); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  var settings = client.beta().organization().plugins().installationSettings()
      .list("plugin_01Hq3vX8kZcN2mB7pR4tY9wL");

  for (var setting : settings.autoPager()) {
      IO.println(setting.pluginId() + ": " + setting.installationPreference().asString());
  }
  ```

  ```php PHP
  $client = new Client();

  $settings = $client->beta->organization->plugins->installationSettings->list(
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
  );

  // 이 페이지만 해당합니다. 다음 페이지는 page: $settings->nextPage로 list()를 다시 호출하세요.
  foreach ($settings->getItems() as $setting) {
      echo "{$setting->pluginID}: {$setting->installationPreference}\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  page = client.beta.organization.plugins.installation_settings.list(plugin_id)

  page.auto_paging_each do |setting|
    puts "#{setting.plugin_id}: #{setting.installation_preference}"
  end
  ```
</CodeGroup>

### 설치 설정 지정

`POST /v1/organizations/plugins/{plugin_id}/installation_settings/{target}`은 조직 소유 플러그인에 대해 하나의 대상의 설치 설정을 지정하며, 설정을 생성하거나 이미 보유한 값을 변경합니다. 본문의 유일한 필드는 `installation_preference`(`required`, `auto_install`, `available` 또는 `not_available`)이며 필수입니다. 대상이 이미 보유한 값을 설정하면 아무것도 변경되지 않습니다. `organization` 대상을 설정하면 값이 기본값과 같더라도 플러그인이 마켓플레이스의 기본값을 상속하지 않게 되므로(`organization_installation_preference_inherited`가 `false`가 됨), 플러그인은 더 이상 마켓플레이스 기본값의 이후 변경을 따르지 않습니다. 플러그인을 마켓플레이스의 기본값으로 되돌리려면 [조직 전체 설정을 제거](https://platform.claude.com/docs/ko/manage-claude/plugins-api#remove-an-installation-setting)하세요. 그룹 설정은 영향을 받지 않습니다. 그룹 대상은 조직이 `GET /v1/organizations/rbac_groups`에서 볼 수 있는 그룹이어야 하며, 그렇지 않으면 요청은 `404`를 반환합니다. 변경은 플러그인의 `updated_at`을 바꾸지 않으며, Activity Feed에 기록됩니다. 설정을 반환합니다. `write:plugins` 스코프가 필요합니다.

플러그인의 설치 설정 쓰기 요청은 한 번에 하나씩 전송하세요. 같은 플러그인에 대한 여러 쓰기 요청이 동시에 도착하면, 서버는 이를 하나씩 순서대로 처리하며 일부 요청에는 적용하는 대신 `503`으로 응답할 수 있습니다. 이 `503`에는 `x-should-retry: true`가 포함되며, 해당 쓰기 요청은 반복해도 안전합니다. 1\~2초 기다린 후 다시 전송하세요.

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/installation_settings/rbac_group_01F3xQqQzXyWvUtSrQpOnMlK" \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -d '{"installation_preference": "available"}'
  ```

  ```bash CLI
  ant beta:organization:plugins:installation-settings set \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --target rbac_group_01F3xQqQzXyWvUtSrQpOnMlK \
    --installation-preference available
  ```

  ```python Python
  client = anthropic.Anthropic()

  setting = client.beta.organization.plugins.installation_settings.set(
      "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
      plugin_id="plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      installation_preference="available",
  )

  print(f"plugin_id: {setting.plugin_id}")
  print(f"installation_preference: {setting.installation_preference}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const setting = await client.beta.organization.plugins.installationSettings.set(
    "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
    {
      plugin_id: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
      installation_preference: "available"
    }
  );

  console.log(`plugin_id: ${setting.plugin_id}`);
  console.log(`installation_preference: ${setting.installation_preference}`);
  ```

  ```csharp C#
  using Anthropic.Models.Beta.Organization.Plugins.InstallationSettings;

  AnthropicClient client = new();

  var setting = await client.Beta.Organization.Plugins.InstallationSettings.Set(
      "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
      new()
      {
          PluginID = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
          InstallationPreference = InstallationPreference.Available,
      }
  );

  Console.WriteLine($"plugin_id: {setting.PluginID}");
  Console.WriteLine($"installation_preference: {setting.InstallationPreference.Raw()}");
  ```

  ```go Go
  client := anthropic.NewClient()

  setting, err := client.Beta.Organization.Plugins.InstallationSettings.Set(
  	context.Background(),
  	"rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
  	anthropic.BetaOrganizationPluginInstallationSettingSetParams{
  		PluginID:               "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  		InstallationPreference: anthropic.BetaOrganizationPluginInstallationSettingSetParamsInstallationPreferenceAvailable,
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("plugin_id: %s\n", setting.PluginID)
  fmt.Printf("installation_preference: %s\n", setting.InstallationPreference)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.installationsettings.InstallationSettingSetParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = InstallationSettingSetParams.builder()
          .pluginId("plugin_01Hq3vX8kZcN2mB7pR4tY9wL")
          .installationPreference(InstallationSettingSetParams.InstallationPreference.AVAILABLE)
          .build();
      var setting = client.beta().organization().plugins().installationSettings()
          .set("rbac_group_01F3xQqQzXyWvUtSrQpOnMlK", params);

      IO.println("plugin_id: " + setting.pluginId());
      IO.println("installation_preference: " + setting.installationPreference().asString());
  }
  ```

  ```php PHP
  use Anthropic\Beta\Organization\Plugins\InstallationSettings\InstallationSettingSetParams\InstallationPreference;
  // ...

  $client = new Client();

  $setting = $client->beta->organization->plugins->installationSettings->set(
      target: 'rbac_group_01F3xQqQzXyWvUtSrQpOnMlK',
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
      installationPreference: InstallationPreference::AVAILABLE,
  );

  echo "plugin_id: {$setting->pluginID}\n";
  echo "installation_preference: {$setting->installationPreference}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  group_id = "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK"
  setting = client.beta.organization.plugins.installation_settings.set(
    group_id,
    plugin_id: plugin_id,
    installation_preference: :available
  )

  puts "plugin_id: #{setting.plugin_id}"
  puts "installation_preference: #{setting.installation_preference}"
  ```
</CodeGroup>

```json
{
  "type": "plugin_installation_setting",
  "plugin_id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  "target": { "type": "rbac_group", "rbac_group_id": "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK" },
  "installation_preference": "available",
  "created_at": "2026-09-02T10:00:00Z",
  "updated_at": "2026-09-02T10:00:00Z"
}
```

### 설치 설정 제거

`DELETE /v1/organizations/plugins/{plugin_id}/installation_settings/{target}`은 조직 소유 플러그인에 대해 하나의 대상의 설치 설정을 제거합니다. `{target}`이 `organization`이면 플러그인 자체의 조직 전체 설정을 제거합니다. 그러면 플러그인은 다시 마켓플레이스의 기본값을 상속하며(`organization_installation_preference_inherited`가 `true`가 됨) 해당 기본값의 이후 변경을 따릅니다. 그룹 설정은 영향을 받지 않습니다. 그룹의 `rbac_group_` ID를 사용하면 해당 그룹의 설정을 제거합니다. 그룹의 멤버는 조직 전체 값 또는 자신이 속한 다른 그룹의 설정으로 돌아갑니다. 자체 설정을 보유하지 않은 대상은 `404`를 반환하며, 여기에는 이미 마켓플레이스의 기본값을 상속하는 플러그인의 `organization` 대상도 포함됩니다. 변경은 플러그인의 `updated_at`을 바꾸지 않으며, Activity Feed에 기록됩니다. 응답에는 `id` 대신 복합 키가 포함되며, `organization` 대상의 경우 `target`은 `{"type": "organization"}`입니다. `write:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl -X DELETE "https://api.anthropic.com/v1/organizations/plugins/plugin_01Hq3vX8kZcN2mB7pR4tY9wL/installation_settings/rbac_group_01F3xQqQzXyWvUtSrQpOnMlK" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins:installation-settings remove \
    --plugin-id plugin_01Hq3vX8kZcN2mB7pR4tY9wL \
    --target rbac_group_01F3xQqQzXyWvUtSrQpOnMlK
  ```

  ```python Python
  client = anthropic.Anthropic()

  removed_setting = client.beta.organization.plugins.installation_settings.remove(
      "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
      plugin_id="plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  )

  print(f"plugin_id: {removed_setting.plugin_id}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const removedSetting = await client.beta.organization.plugins.installationSettings.remove(
    "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
    { plugin_id: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL" }
  );

  console.log(`plugin_id: ${removedSetting.plugin_id}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var removedSetting = await client.Beta.Organization.Plugins.InstallationSettings.Remove(
      "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
      new() { PluginID = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL" }
  );

  Console.WriteLine($"plugin_id: {removedSetting.PluginID}");
  ```

  ```go Go
  client := anthropic.NewClient()

  removedSetting, err := client.Beta.Organization.Plugins.InstallationSettings.Remove(
  	context.Background(),
  	"rbac_group_01F3xQqQzXyWvUtSrQpOnMlK",
  	anthropic.BetaOrganizationPluginInstallationSettingRemoveParams{
  		PluginID: "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("plugin_id: %s\n", removedSetting.PluginID)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.plugins.installationsettings.InstallationSettingRemoveParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = InstallationSettingRemoveParams.builder()
          .pluginId("plugin_01Hq3vX8kZcN2mB7pR4tY9wL")
          .build();
      var removedSetting = client.beta().organization().plugins().installationSettings()
          .remove("rbac_group_01F3xQqQzXyWvUtSrQpOnMlK", params);

      IO.println("plugin_id: " + removedSetting.pluginId());
  }
  ```

  ```php PHP
  $client = new Client();

  $removedSetting = $client->beta->organization->plugins->installationSettings->remove(
      target: 'rbac_group_01F3xQqQzXyWvUtSrQpOnMlK',
      pluginID: 'plugin_01Hq3vX8kZcN2mB7pR4tY9wL',
  );

  echo "plugin_id: {$removedSetting->pluginID}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
  group_id = "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK"
  removed_setting = client.beta.organization.plugins.installation_settings.remove(
    group_id,
    plugin_id: plugin_id
  )

  puts "plugin_id: #{removed_setting.plugin_id}"
  ```
</CodeGroup>

```json
{
  "type": "plugin_installation_setting_deleted",
  "plugin_id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL",
  "target": { "type": "rbac_group", "rbac_group_id": "rbac_group_01F3xQqQzXyWvUtSrQpOnMlK" }
}
```

## 플러그인 공유

공유는 멤버 소유 플러그인에만 존재하며, 이 API에서는 읽기 전용입니다([공유](https://platform.claude.com/docs/ko/manage-claude/plugins-api#shares) 참조).

### 플러그인 공유 목록 조회

`GET /v1/organizations/plugins/{plugin_id}/shares`는 멤버 소유 플러그인의 소유자가 플러그인을 공유한 대상을 `granted_at` 내림차순으로 나열합니다. 대상은 모든 멤버(`organization`), 그룹(`rbac_group`) 또는 지정된 멤버(`organization_member`)입니다. `target_type`으로 필터링할 수 있습니다. 소유자가 공유하지 않은 플러그인은 빈 목록을 반환하며, 조직 소유 플러그인은 `404`를 반환합니다. 공유는 이 API에서 읽기 전용이며, 나열된 공유는 claude.ai에서 조직에 해당 유형의 공유가 켜져 있는 동안에만 액세스 권한을 부여합니다([공유](https://platform.claude.com/docs/ko/manage-claude/plugins-api#shares) 참조). `granted_at`은 공유가 부여된 시점이며, 소유자가 이후 claude.ai에서 공유를 변경한 경우에는 그 변경 시점입니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugins/plugin_01Mr2wP7sU3aJ8vX5cY6nS9t/shares" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugins:shares list \
    --plugin-id plugin_01Mr2wP7sU3aJ8vX5cY6nS9t
  ```

  ```python Python
  client = anthropic.Anthropic()

  shares = client.beta.organization.plugins.shares.list("plugin_01Mr2wP7sU3aJ8vX5cY6nS9t")

  # 필요에 따라 추가 페이지를 자동으로 가져옵니다.
  for share in shares:
      print(f"plugin_id: {share.plugin_id}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const shares = await client.beta.organization.plugins.shares.list(
    "plugin_01Mr2wP7sU3aJ8vX5cY6nS9t"
  );

  for await (const share of shares) {
    console.log(`plugin_id: ${share.plugin_id}`);
  }
  ```

  ```csharp C#
  AnthropicClient client = new();

  var page = await client.Beta.Organization.Plugins.Shares.List("plugin_01Mr2wP7sU3aJ8vX5cY6nS9t");

  await foreach (var share in page.Paginate())
  {
      Console.WriteLine($"plugin_id: {share.PluginID}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  shares := client.Beta.Organization.Plugins.Shares.ListAutoPaging(
  	context.Background(),
  	"plugin_01Mr2wP7sU3aJ8vX5cY6nS9t",
  	anthropic.BetaOrganizationPluginShareListParams{},
  )

  for shares.Next() {
  	share := shares.Current()
  	fmt.Printf("plugin_id: %s\n", share.PluginID)
  }
  if err := shares.Err(); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  var shares = client.beta().organization().plugins().shares()
      .list("plugin_01Mr2wP7sU3aJ8vX5cY6nS9t");

  for (var share : shares.autoPager()) {
      IO.println("plugin_id: " + share.pluginId());
  }
  ```

  ```php PHP
  $client = new Client();

  $shares = $client->beta->organization->plugins->shares->list(
      pluginID: 'plugin_01Mr2wP7sU3aJ8vX5cY6nS9t',
  );

  // 이 페이지만 해당합니다. 다음 페이지는 page: $shares->nextPage로 list()를 다시 호출하세요.
  foreach ($shares->getItems() as $share) {
      echo "plugin_id: {$share->pluginID}\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  plugin_id = "plugin_01Mr2wP7sU3aJ8vX5cY6nS9t"
  page = client.beta.organization.plugins.shares.list(plugin_id)

  page.auto_paging_each do |share|
    puts "plugin_id: #{share.plugin_id}"
  end
  ```
</CodeGroup>

```json
{
  "data": [
    {
      "type": "plugin_share",
      "plugin_id": "plugin_01Mr2wP7sU3aJ8vX5cY6nS9t",
      "target": { "type": "organization_member", "user_id": "user_01WCz9BvGLdMYRUMmcAxMWvW" },
      "granted_at": "2026-08-20T15:12:00Z"
    }
  ],
  "next_page": null
}
```

## 플러그인 마켓플레이스

이 API는 [마켓플레이스](https://platform.claude.com/docs/ko/manage-claude/plugins-api#marketplaces)를 읽고 조직 마켓플레이스의 기본 설치 설정을 지정합니다. 마켓플레이스 자체의 생성, 리포지토리 연결, 삭제는 claude.ai에서 이루어집니다.

```json
{
  "type": "plugin_marketplace",
  "id": "marketplace_01VbNcMxZaSdFgHjKlQwErTy",
  "name": "engineering-tools",
  "owner": { "type": "organization" },
  "source": "github",
  "sync_status": "success",
  "last_sync_ended_at": "2026-09-10T22:15:03Z",
  "last_sync_read_sha": "9fceb02d0ae598e95dc970b74767f19372d61af8",
  "default_installation_preference": "available",
  "created_at": "2026-06-12T08:45:00Z"
}
```

| 필드                                | 설명                                                                                                                                                                                      |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                            | 마켓플레이스의 이름입니다. 마켓플레이스가 존재하는 동안 고정됩니다.                                                                                                                                                   |
| `owner`                           | 플러그인의 경우와 같은 형태입니다.                                                                                                                                                                     |
| `source`                          | `manual`, `github`, `gitlab` 또는 `public_git`입니다. [마켓플레이스](https://platform.claude.com/docs/ko/manage-claude/plugins-api#marketplaces)를 참조하세요.                                           |
| `sync_status`                     | 가장 최근 동기화의 결과입니다: `success`, `in_progress`, `failed_content`, `failed_transient`, `failed_auth` 또는 `failed_limits`. 동기화가 처음 시도되기 전까지는 `null`이며, 소스가 `manual`인 마켓플레이스에서는 동기화가 시도되지 않습니다. |
| `last_sync_ended_at`              | 결과와 관계없이 가장 최근 동기화 시도가 완료된 시점입니다. 아직 동기화되지 않은 연결된 리포지토리의 경우 마켓플레이스가 생성된 시점입니다. 동기화되지 않는 마켓플레이스의 경우 `null`입니다.                                                                           |
| `last_sync_read_sha`              | 마지막 동기화가 리포지토리에서 읽은 커밋입니다. 제공 버전이 생성된 커밋과 반드시 같지는 않습니다. 동기화되지 않는 마켓플레이스의 경우 `null`입니다.                                                                                                  |
| `default_installation_preference` | 조직 마켓플레이스: 자체 설정이 없는 마켓플레이스 내 모든 플러그인에 대한 조직 전체 값입니다(설정된 적이 없으면 `not_available`). 개인 마켓플레이스: `null`.                                                                                    |

`marketplace_` 접두사가 없는 `marketplace_id`는 `400`을 반환합니다. 접두사가 있지만 확인되지 않거나 다른 조직에 속한 값은 `404`를 반환합니다.

### 마켓플레이스 목록 조회

`GET /v1/organizations/plugin_marketplaces`는 조직의 마켓플레이스와 멤버의 개인 마켓플레이스를 `created_at` 내림차순으로 나열합니다. 마켓플레이스가 플러그인을 보유하기 전에 그 ID를 찾아 플러그인 목록을 필터링하거나 해당 마켓플레이스에 업로드할 때 사용하세요. 라이브러리 마켓플레이스는 claude.ai에서든 이 API를 통해서든 그 안에 무언가가 처음 생성된 후에 나타납니다. `owner_type`(`organization` 또는 `user`)과 `source`로 필터링할 수 있습니다. `limit`은 1에서 1,000 사이입니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugin_marketplaces?owner_type=organization" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugin-marketplaces list --owner-type organization
  ```

  ```python Python
  client = anthropic.Anthropic()

  marketplaces = client.beta.organization.plugin_marketplaces.list(
      owner_type="organization"
  )

  # 필요에 따라 추가 페이지를 자동으로 가져옵니다.
  for marketplace in marketplaces:
      print(f"{marketplace.id}: {marketplace.name}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const marketplaces = await client.beta.organization.pluginMarketplaces.list({
    owner_type: "organization"
  });

  for await (const marketplace of marketplaces) {
    console.log(`${marketplace.id}: ${marketplace.name}`);
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta.Organization.PluginMarketplaces;

  AnthropicClient client = new();

  var page = await client.Beta.Organization.PluginMarketplaces.List(
      new() { OwnerType = OwnerType.Organization }
  );

  await foreach (var marketplace in page.Paginate())
  {
      Console.WriteLine($"{marketplace.ID}: {marketplace.Name}");
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  marketplaces := client.Beta.Organization.PluginMarketplaces.ListAutoPaging(
  	context.Background(),
  	anthropic.BetaOrganizationPluginMarketplaceListParams{
  		OwnerType: anthropic.BetaOrganizationPluginMarketplaceListParamsOwnerTypeOrganization,
  	},
  )

  for marketplaces.Next() {
  	marketplace := marketplaces.Current()
  	fmt.Printf("%s: %s\n", marketplace.ID, marketplace.Name)
  }
  if err := marketplaces.Err(); err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java
  import com.anthropic.models.beta.organization.pluginmarketplaces.PluginMarketplaceListParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = PluginMarketplaceListParams.builder()
          .ownerType(PluginMarketplaceListParams.OwnerType.ORGANIZATION)
          .build();
      var marketplaces = client.beta().organization().pluginMarketplaces().list(params);

      for (var marketplace : marketplaces.autoPager()) {
          IO.println(marketplace.id() + ": " + marketplace.name());
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\Organization\PluginMarketplaces\PluginMarketplaceListParams\OwnerType;
  // ...

  $client = new Client();

  $marketplaces = $client->beta->organization->pluginMarketplaces->list(
      ownerType: OwnerType::ORGANIZATION,
  );

  // 이 페이지만 해당합니다. 다음 페이지는 page: $marketplaces->nextPage 로 list() 를 다시 호출하세요.
  foreach ($marketplaces->getItems() as $marketplace) {
      echo "{$marketplace->id}: {$marketplace->name}\n";
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  page = client.beta.organization.plugin_marketplaces.list(owner_type: :organization)

  page.auto_paging_each do |marketplace|
    puts "#{marketplace.id}: #{marketplace.name}"
  end
  ```
</CodeGroup>

### 마켓플레이스 조회

`GET /v1/organizations/plugin_marketplaces/{marketplace_id}`는 하나의 마켓플레이스를 반환합니다. `read:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl "https://api.anthropic.com/v1/organizations/plugin_marketplaces/marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01"
  ```

  ```bash CLI
  ant beta:organization:plugin-marketplaces retrieve \
    --marketplace-id marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r
  ```

  ```python Python
  client = anthropic.Anthropic()

  marketplace = client.beta.organization.plugin_marketplaces.retrieve(
      "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  )

  print(f"id: {marketplace.id}")
  print(f"name: {marketplace.name}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const marketplace = await client.beta.organization.pluginMarketplaces.retrieve(
    "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  );

  console.log(`id: ${marketplace.id}`);
  console.log(`name: ${marketplace.name}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var marketplace = await client.Beta.Organization.PluginMarketplaces.Retrieve(
      "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  );

  Console.WriteLine($"id: {marketplace.ID}");
  Console.WriteLine($"name: {marketplace.Name}");
  ```

  ```go Go
  client := anthropic.NewClient()

  marketplace, err := client.Beta.Organization.PluginMarketplaces.Get(
  	context.Background(),
  	"marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
  	anthropic.BetaOrganizationPluginMarketplaceGetParams{},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", marketplace.ID)
  fmt.Printf("name: %s\n", marketplace.Name)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  var marketplace = client.beta().organization().pluginMarketplaces()
      .retrieve("marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r");

  IO.println("id: " + marketplace.id());
  IO.println("name: " + marketplace.name());
  ```

  ```php PHP
  $client = new Client();

  $marketplace = $client->beta->organization->pluginMarketplaces->retrieve(
      marketplaceID: 'marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r',
  );

  echo "id: {$marketplace->id}\n";
  echo "name: {$marketplace->name}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  marketplace_id = "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  marketplace = client.beta.organization.plugin_marketplaces.retrieve(marketplace_id)

  puts "id: #{marketplace.id}"
  puts "name: #{marketplace.name}"
  ```
</CodeGroup>

### 마켓플레이스 기본 설치 설정 지정

`POST /v1/organizations/plugin_marketplaces/{marketplace_id}`는 조직 소유 마켓플레이스의 기본 설치 설정을 지정합니다. 자체 조직 전체 설정이 없는 마켓플레이스 내 모든 플러그인은 나중에 추가되는 플러그인을 포함하여 이 기본값을 `organization_installation_preference`로 보고합니다. 이 작업은 `manual` 마켓플레이스와 동기화되는 마켓플레이스 모두에 적용되며, 멤버의 개인 마켓플레이스는 `403`을 반환합니다. 업데이트할 수 있는 유일한 필드는 `default_installation_preference`이며, 필수입니다. 이 값은 다시 `null`로 설정할 수 없습니다. claude.ai에서와 마찬가지로 마켓플레이스에 기본값이 한 번 지정되면 계속 유지됩니다. 변경 사항은 플러그인별 이벤트 없이 하나의 `marketplace_updated` 이벤트로 기록되며, 어떤 플러그인의 `updated_at`도 변경하지 않습니다. 이미 설정된 값으로 설정하면 아무것도 변경되지 않지만, 한 가지 예외가 있습니다. 기본값이 설정된 적이 없는 마켓플레이스는 `not_available`을 보고하지만 실제로는 설정을 보유하지 않으므로, 첫 번째 쓰기(`not_available`이라도)는 변경으로 간주됩니다. 마켓플레이스를 반환합니다. `write:plugins` 스코프가 필요합니다.

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugin_marketplaces/marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r" \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -d '{"default_installation_preference": "available"}'
  ```

  ```bash CLI
  ant beta:organization:plugin-marketplaces update \
    --marketplace-id marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r \
    --default-installation-preference available
  ```

  ```python Python
  client = anthropic.Anthropic()

  marketplace = client.beta.organization.plugin_marketplaces.update(
      "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
      default_installation_preference="available",
  )

  print(f"id: {marketplace.id}")
  print(f"default_installation_preference: {marketplace.default_installation_preference}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const marketplace = await client.beta.organization.pluginMarketplaces.update(
    "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
    { default_installation_preference: "available" }
  );

  console.log(`id: ${marketplace.id}`);
  console.log(`default_installation_preference: ${marketplace.default_installation_preference}`);
  ```

  ```csharp C#
  using Anthropic.Models.Beta.Organization.PluginMarketplaces;

  AnthropicClient client = new();

  var marketplace = await client.Beta.Organization.PluginMarketplaces.Update(
      "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
      new() { DefaultInstallationPreference = DefaultInstallationPreference.Available }
  );

  Console.WriteLine($"id: {marketplace.ID}");
  Console.WriteLine(
      $"default_installation_preference: {marketplace.DefaultInstallationPreference?.Raw()}"
  );
  ```

  ```go Go
  client := anthropic.NewClient()

  marketplace, err := client.Beta.Organization.PluginMarketplaces.Update(
  	context.Background(),
  	"marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r",
  	anthropic.BetaOrganizationPluginMarketplaceUpdateParams{
  		DefaultInstallationPreference: anthropic.BetaOrganizationPluginMarketplaceUpdateParamsDefaultInstallationPreferenceAvailable,
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("id: %s\n", marketplace.ID)
  fmt.Printf("default_installation_preference: %s\n", marketplace.DefaultInstallationPreference)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.pluginmarketplaces.PluginMarketplaceUpdateParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = PluginMarketplaceUpdateParams.builder()
          .defaultInstallationPreference(PluginMarketplaceUpdateParams.DefaultInstallationPreference.AVAILABLE)
          .build();
      var marketplace = client.beta().organization().pluginMarketplaces()
          .update("marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r", params);

      IO.println("id: " + marketplace.id());
      IO.println("default_installation_preference: "
          + marketplace.defaultInstallationPreference().map(preference -> preference.asString()).orElse(null));
  }
  ```

  ```php PHP
  use Anthropic\Beta\Organization\PluginMarketplaces\PluginMarketplaceUpdateParams\DefaultInstallationPreference;
  // ...

  $client = new Client();

  $marketplace = $client->beta->organization->pluginMarketplaces->update(
      marketplaceID: 'marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r',
      defaultInstallationPreference: DefaultInstallationPreference::AVAILABLE,
  );

  echo "id: {$marketplace->id}\n";
  echo "default_installation_preference: {$marketplace->defaultInstallationPreference}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  marketplace_id = "marketplace_01Lp8uM5qS1yG6tV3aW4kQ7r"
  marketplace = client.beta.organization.plugin_marketplaces.update(
    marketplace_id,
    default_installation_preference: :available
  )

  puts "id: #{marketplace.id}"
  puts "default_installation_preference: #{marketplace.default_installation_preference}"
  ```
</CodeGroup>

### 마켓플레이스 콘텐츠 검증

두 엔드포인트는 아무것도 연결하거나 저장하지 않고, 주어진 마켓플레이스 콘텐츠를 동기화하면 어떤 결과가 나올지 보고합니다. `POST /v1/organizations/plugin_marketplaces/validate_repository`는 공개 GitHub 리포지토리를 읽고, `POST /v1/organizations/plugin_marketplaces/validate_archive`는 업로드한 마켓플레이스 디렉터리의 `.zip`을 읽습니다. 두 엔드포인트 모두 같은 보고서를 반환합니다. 보고서에는 `marketplace.json`의 형식이 올바른지, 어떤 플러그인이 어떤 이유로 건너뛰어지는지, 어떤 플러그인이 일부 콘텐츠가 제외된 채 동기화되는지가 포함됩니다. 검사 항목은 실제 동기화에서 실행되는 것과 같습니다. 콘텐츠 관련 문제는 HTTP 오류가 아니라 보고서로 반환됩니다. 리포지토리나 아카이브를 전혀 읽을 수 없는 경우에도 요청은 `valid: false`와 함께 성공합니다. 검증은 읽기 요청으로 계산되며, 두 엔드포인트를 합쳐 조직당 분당 10회의 검증으로 추가 제한됩니다([속도 제한](https://platform.claude.com/docs/ko/manage-claude/plugins-api#rate-limiting) 참조). 검증은 Activity Feed에 아무것도 기록하지 않습니다. 검증은 반환되기까지 최대 120초가 걸릴 수 있으므로, 클라이언트의 타임아웃을 그보다 길게 설정하세요. 두 엔드포인트 모두 `read:plugins` 또는 `write:plugins` 스코프가 필요합니다(`read:org_audit` 및 `read:compliance_org_data`로는 권한이 부여되지 않습니다).

리포지토리와 그 외부에 있는 GitHub의 플러그인 소스는 익명으로 읽히므로, 비공개 리포지토리나 비공개 플러그인 소스는 찾을 수 없는 것으로 보고됩니다. GitHub 이외의 호스트에 있는 플러그인 소스는 가져오지 않습니다. 이러한 플러그인은 일반적으로 `marketplace_validate_source_not_checked` 경고를 받으며, 마켓플레이스가 실제로 동기화될 때 검사됩니다. 리포지토리가 Anthropic이 모든 조직에 동기화하는 마켓플레이스이거나 아카이브가 그러한 마켓플레이스를 지정하는 경우, 더 엄격한 규칙이 적용됩니다. 마켓플레이스 외부의 모든 플러그인 소스는 전체 커밋 SHA로 고정되어야 하고, 고정되지 않았거나 지원되지 않는 호스트의 소스는 플러그인 오류로 보고되며, 읽는 브랜치의 기본값은 해당 마켓플레이스가 동기화하는 브랜치입니다.

`validate_repository`는 두 개의 필드가 있는 JSON 본문을 받습니다. `repository_url`은 github.com에 있는 공개 리포지토리의 `https://` URL이며(필수), `ref`는 브랜치 이름 또는 40자 전체 커밋 SHA입니다(선택 사항. 생략하거나 `null`이면 동기화가 읽을 브랜치이며, 일반적으로 리포지토리의 기본 브랜치입니다). `validate_archive`는 정확히 하나의 파트 `archive`가 있는 `multipart/form-data`를 받으며, 이 파트는 파일 이름이 있는 파일 파트로 전송되어야 합니다. 이 파트는 마켓플레이스 디렉터리의 `.zip`으로, 최대 32 MB이고, 콘텐츠가 루트에 있거나 하나의 폴더로 감싸져 있어야 하며(Git 호스트의 다운로드가 생성하는 형태), DEFLATE 또는 STORE 압축만 허용됩니다. 다른 폼 필드는 허용되지 않습니다.

특정 브랜치의 공개 리포지토리 검증:

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugin_marketplaces/validate_repository" \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -d '{"repository_url": "https://github.com/example-org/claude-plugins", "ref": "release-candidate"}'
  ```

  ```bash CLI
  ant beta:organization:plugin-marketplaces validate-repository \
    --repository-url https://github.com/example-org/claude-plugins \
    --ref release-candidate
  ```

  ```python Python
  client = anthropic.Anthropic()

  report = client.beta.organization.plugin_marketplaces.validate_repository(
      repository_url="https://github.com/example-org/claude-plugins",
      ref="release-candidate",
  )

  print(f"valid: {str(report.valid).lower()}")
  print(f"total_plugin_count: {report.total_plugin_count}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const report = await client.beta.organization.pluginMarketplaces.validateRepository({
    repository_url: "https://github.com/example-org/claude-plugins",
    ref: "release-candidate"
  });

  console.log(`valid: ${report.valid}`);
  console.log(`total_plugin_count: ${report.total_plugin_count}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var report = await client.Beta.Organization.PluginMarketplaces.ValidateRepository(
      new()
      {
          RepositoryUrl = "https://github.com/example-org/claude-plugins",
          Ref = "release-candidate",
      }
  );

  Console.WriteLine($"valid: {report.Valid.ToString().ToLowerInvariant()}");
  Console.WriteLine($"total_plugin_count: {report.TotalPluginCount}");
  ```

  ```go Go
  client := anthropic.NewClient()

  report, err := client.Beta.Organization.PluginMarketplaces.ValidateRepository(
  	context.Background(),
  	anthropic.BetaOrganizationPluginMarketplaceValidateRepositoryParams{
  		RepositoryURL: "https://github.com/example-org/claude-plugins",
  		Ref:           anthropic.String("release-candidate"),
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("valid: %t\n", report.Valid)
  fmt.Printf("total_plugin_count: %d\n", report.TotalPluginCount)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.pluginmarketplaces.PluginMarketplaceValidateRepositoryParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var params = PluginMarketplaceValidateRepositoryParams.builder()
          .repositoryUrl("https://github.com/example-org/claude-plugins")
          .ref("release-candidate")
          .build();
      var report = client.beta().organization().pluginMarketplaces().validateRepository(params);

      IO.println("valid: " + report.valid());
      IO.println("total_plugin_count: " + report.totalPluginCount());
  }
  ```

  ```php PHP
  $client = new Client();

  $report = $client->beta->organization->pluginMarketplaces->validateRepository(
      repositoryURL: 'https://github.com/example-org/claude-plugins',
      ref: 'release-candidate',
  );

  echo 'valid: ' . ($report->valid ? 'true' : 'false') . "\n";
  echo "total_plugin_count: {$report->totalPluginCount}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  report = client.beta.organization.plugin_marketplaces.validate_repository(
    repository_url: "https://github.com/example-org/claude-plugins",
    ref: "release-candidate"
  )

  puts "valid: #{report.valid}"
  puts "total_plugin_count: #{report.total_plugin_count}"
  ```
</CodeGroup>

```json
{
  "type": "plugin_marketplace_validation_report",
  "valid": false,
  "ref": "release-candidate",
  "commit_sha": "9fceb02d0ae598e95dc970b74767f19372d61af8",
  "total_plugin_count": 3,
  "manifest_error": null,
  "manifest_error_code": null,
  "plugin_errors": [
    {
      "name": "deploy-helper",
      "error": "The plugin has a top-level bin/ directory.",
      "error_code": "marketplace_sync_bin_directory_not_allowed"
    }
  ],
  "plugin_warnings": [
    {
      "name": "release-notes",
      "warnings": [
        {
          "message": "plugin.json has unrecognized top-level keys: owners",
          "error_code": "marketplace_sync_plugin_unrecognized_keys"
        }
      ]
    }
  ]
}
```

| 필드                                      | 설명                                                                                                                                                                                    |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `valid`                                 | `marketplace.json`의 형식이 올바르고 건너뛰어지는 플러그인이 없으면 `true`입니다. 경고가 있어도 `false`가 되지 않습니다.                                                                                                    |
| `ref`                                   | 읽은 브랜치의 이름입니다. 브랜치를 지정하지 않아 기본 브랜치를 읽은 경우, 커밋 SHA인 경우, 아카이브인 경우에는 `null`입니다.                                                                                                          |
| `commit_sha`                            | 검증된 커밋입니다. Git 호스트에서 다운로드한 아카이브의 경우, 호스트가 ZIP 파일의 주석 필드에 기록한 커밋이 있으면 그 커밋입니다(검증되지 않음).                                                                                                |
| `total_plugin_count`                    | `marketplace.json`이 선언한 플러그인 수입니다. 읽을 수 없는 경우 `0`입니다.                                                                                                                                 |
| `manifest_error`, `manifest_error_code` | 아무것도 검증할 수 없을 때 설정됩니다. 소스를 읽을 수 없거나, `marketplace.json`이 없거나, 형식이 잘못되었거나, 제한을 초과한 경우입니다. 120초 이내에 완료되지 않은 검증은 `manifest_error_code: "marketplace_validate_deadline_exceeded"`를 보고합니다. |
| `plugin_errors`                         | 동기화 시 건너뛰어지는 플러그인마다 하나의 `{name, error, error_code}`입니다.                                                                                                                               |
| `plugin_warnings`                       | 일부 콘텐츠가 제외된 채 동기화되는 플러그인마다 하나의 `{name, warnings: [{message, error_code}]}`입니다.                                                                                                        |

대신 마켓플레이스 디렉터리의 로컬 사본을 `.zip`으로 검증할 수도 있으며, 응답은 같은 보고서입니다:

<CodeGroup>
  ```bash cURL
  curl -X POST "https://api.anthropic.com/v1/organizations/plugin_marketplaces/validate_archive" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: ce-plugins-2026-09-01" \
    -F "archive=@marketplace.zip"
  ```

  ```bash CLI
  ant beta:organization:plugin-marketplaces validate-archive \
    --archive marketplace.zip
  ```

  ```python Python
  client = anthropic.Anthropic()

  with open("marketplace.zip", "rb") as archive:
      report = client.beta.organization.plugin_marketplaces.validate_archive(
          archive=archive
      )

  print(f"valid: {str(report.valid).lower()}")
  print(f"total_plugin_count: {report.total_plugin_count}")
  ```

  ```typescript TypeScript
  import fs from "node:fs";

  const client = new Anthropic();

  const report = await client.beta.organization.pluginMarketplaces.validateArchive({
    archive: fs.createReadStream("marketplace.zip")
  });

  console.log(`valid: ${report.valid}`);
  console.log(`total_plugin_count: ${report.total_plugin_count}`);
  ```

  ```csharp C#
  AnthropicClient client = new();

  var report = await client.Beta.Organization.PluginMarketplaces.ValidateArchive(
      new() { Archive = File.OpenRead("marketplace.zip") }
  );

  Console.WriteLine($"valid: {report.Valid.ToString().ToLowerInvariant()}");
  Console.WriteLine($"total_plugin_count: {report.TotalPluginCount}");
  ```

  ```go Go
  client := anthropic.NewClient()

  archive, err := os.Open("marketplace.zip")
  if err != nil {
  	log.Fatal(err)
  }
  defer archive.Close()

  report, err := client.Beta.Organization.PluginMarketplaces.ValidateArchive(
  	context.Background(),
  	anthropic.BetaOrganizationPluginMarketplaceValidateArchiveParams{
  		Archive: archive,
  	},
  )
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Printf("valid: %t\n", report.Valid)
  fmt.Printf("total_plugin_count: %d\n", report.TotalPluginCount)
  ```

  ```java Java
  import com.anthropic.models.beta.organization.pluginmarketplaces.PluginMarketplaceValidateArchiveParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      // 이 엔드포인트는 파일 이름이 필요하므로, `archive` 파트가 파일 이름과 함께 전송되도록 Path를 전달하세요.
      var params = PluginMarketplaceValidateArchiveParams.builder()
          .archive(Path.of("marketplace.zip"))
          .build();
      var report = client.beta().organization().pluginMarketplaces().validateArchive(params);

      IO.println("valid: " + report.valid());
      IO.println("total_plugin_count: " + report.totalPluginCount());
  }
  ```

  ```php PHP
  use Anthropic\Core\FileParam;

  $client = new Client();

  $report = $client->beta->organization->pluginMarketplaces->validateArchive(
      archive: FileParam::fromResource(fopen('marketplace.zip', 'r')),
  );

  echo 'valid: ' . ($report->valid ? 'true' : 'false') . "\n";
  echo "total_plugin_count: {$report->totalPluginCount}\n";
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  report = client.beta.organization.plugin_marketplaces.validate_archive(
    archive: Pathname("marketplace.zip")
  )

  puts "valid: #{report.valid}"
  puts "total_plugin_count: #{report.total_plugin_count}"
  ```
</CodeGroup>

콘텐츠 관련 문제로 요청이 실패하는 경우는 없습니다. 모든 엔드포인트에 공통인 응답(`read:org_audit` 또는 `read:compliance_org_data`만 있는 키에 대한 `403`. [오류 응답](https://platform.claude.com/docs/ko/manage-claude/plugins-api#error-responses) 및 [속도 제한](https://platform.claude.com/docs/ko/manage-claude/plugins-api#rate-limiting) 참조) 외에, 요청 자체는 다음과 같은 이유로 실패할 수 있습니다:

| 상태  | 원인                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 조치 방법                                |
| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| 400 | `validate_repository`의 경우: 본문이 JSON 객체가 아니거나, `repository_url`이 없거나, 2,048자를 초과하거나, 자격 증명을 포함하거나, `https://github.com/{owner}/{repo}` 형식이 아닙니다(`.git` 접미사는 허용되지만, 다른 호스트, 브랜치 페이지의 `/tree/main`과 같은 더 긴 경로, 443 또는 80 이외의 포트는 허용되지 않습니다). 또는 `ref`가 비어 있거나, 255자를 초과하거나, `..`를 포함하거나, ASCII 문자, 숫자, `.`, `_`, `-`, `+`, `/` 이외의 문자를 포함합니다. 또는 다른 필드가 있습니다. 이러한 검사를 통과했지만 리포지토리에 없는 브랜치를 지정한 `ref`는 거부되지 않습니다. 요청은 `valid: false`와 함께 성공하며, `manifest_error`에 브랜치를 찾을 수 없다고 표시됩니다. `validate_archive`의 경우: 본문이 `multipart/form-data`가 아니거나, `archive` 파트가 없거나, 반복되거나, 파일 이름이 있는 파일 파트로 전송되지 않았거나, 다른 폼 필드가 있습니다. | 요청을 수정하여 다시 전송하세요.                   |
| 413 | `validate_archive`의 경우: `archive` 파트 또는 요청에 선언된 본문 길이가 32 MB를 초과합니다.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 대신 URL로 리포지토리를 검증하거나, 아카이브 크기를 줄이세요. |

#### 보고서 코드

보고서의 각 결과에는 안정적인 코드가 있습니다. 아무것도 검증할 수 없을 때는 `manifest_error_code`, 각 `plugin_errors` 항목에는 `error_code`, 각 경고에는 `error_code`가 있습니다. 플러그인에 여러 문제가 있는 경우 `error_code`는 첫 번째 문제의 코드이며, `error`는 모든 메시지를 결합한 것입니다. 새 코드가 추가될 수 있습니다. 인식할 수 없는 `manifest_error_code`도 여전히 콘텐츠를 검증할 수 없었음을 의미하고, `plugin_errors` 항목의 인식할 수 없는 코드도 여전히 플러그인이 건너뛰어짐을 의미하며, 경고의 인식할 수 없는 코드도 여전히 플러그인이 동기화됨을 의미합니다. 다음 코드는 일시적인 상태를 나타내므로, 같은 요청이 나중에 성공할 수 있습니다: `marketplace_host_rate_limited`, `marketplace_host_server_error`, `marketplace_host_timeout`, `marketplace_host_unreachable`, `marketplace_repo_access_denied`, `marketplace_sync_transient_fetch_budget_exhausted`, `marketplace_validate_network_error`, 그리고 대개 `marketplace_validate_deadline_exceeded`.

## 인식할 수 없는 값

이 페이지의 모든 문자열 값(컴포넌트 유형, `reach`, 스캔 필드, 마켓플레이스 `source`, 오류 코드)에는 언제든지 새로운 값이 추가될 수 있습니다. 인식할 수 없는 값은 실패로 처리하지 말고, 다른 알 수 없는 문자열과 마찬가지로 처리하세요.

## 속도 제한

읽기 요청(이 페이지의 모든 `GET` 엔드포인트)은 조직당 **분당 300회 요청**의 "rate limit"(속도 제한)을 공유하며, 쓰기 요청(플러그인 또는 버전 생성, 제공 버전 변경, 삭제, 설치 설정 지정 또는 제거, 마켓플레이스 업데이트)은 조직당 **분당 60회 요청**의 제한을 공유합니다. 마켓플레이스 검증(두 엔드포인트 모두)은 읽기 요청으로 계산되며, 검증은 두 엔드포인트를 합쳐 조직당 분당 10회로 추가 제한됩니다. 두 제한 모두 요청 본문을 읽기 전에 확인됩니다. 이러한 제한은 조직의 모든 키에 걸쳐 계산되며, 조직의 다른 Admin API 제한과는 별개입니다. 제한을 초과한 요청은 `retry-after` 헤더와 함께 **429 Too Many Requests**를 반환합니다. 응답에는 적용되는 제한에 대한 `anthropic-ratelimit-requests-*` 헤더가 포함됩니다(마켓플레이스 검증의 경우 분당 10회 제한, `429`의 경우 요청을 거부한 제한).

업로드, 제공 버전 변경 또는 검증은 서비스에 일시적으로 추가 작업을 처리할 용량이 없을 때도 `retry-after`와 함께 `429`를 반환할 수 있으며, 업로드는 조직이 콘텐츠 스캔 속도를 초과한 경우에도 `429`를 반환합니다. 이 모든 경우를 같은 방식으로 처리하세요. `retry-after`만큼 기다린 후 다시 시도하면 됩니다. 이러한 제한과는 별도로, 같은 플러그인에 대한 설치 설정 쓰기 요청은 한 번에 하나씩 전송하세요. 여러 요청이 동시에 도착하면 일부는 `503` 및 `x-should-retry: true`로 응답될 수 있으며, 이러한 요청은 1\~2초 후에 다시 전송해도 안전합니다([설치 설정 지정](https://platform.claude.com/docs/ko/manage-claude/plugins-api#set-an-installation-setting) 참조).

## 페이지네이션

목록 엔드포인트는 **불투명 커서(opaque cursor)**&#xB97C; 사용합니다. 첫 번째 요청은 최대 `limit`개의 행과 `next_page` 커서를 반환합니다. 다음 요청에서 이 커서를 변경하지 않고 `page` 매개변수로 전달하고, `next_page`가 `null`이 될 때까지 반복하세요. 커서 문자열은 불투명한 값으로 취급하세요. 직접 파싱하거나, 수정하거나, 생성하지 마세요. [플러그인 목록 조회](https://platform.claude.com/docs/ko/manage-claude/plugins-api#list-plugins)는 `next_page`가 여전히 설정된 상태에서 `limit`보다 적은 수의 플러그인이 있거나 플러그인이 없는 페이지를 반환할 수 있으므로, `next_page`가 `null`이 될 때까지 계속 페이지를 요청하세요. Python, TypeScript, C#, Go, Java, Ruby SDK의 목록 반복자와 CLI(`--format raw` 사용 시 제외)는 이를 자동으로 처리합니다. 이들은 `next_page`가 설정되어 있는 동안 다음 페이지를 요청하므로, 짧거나 빈 페이지로 인해 종료되지 않습니다. PHP와 curl에서는 각 페이지를 직접 요청하고 해당 `next_page`를 `page`로 전달하세요.

`limit`의 기본값은 20이며 최솟값은 1입니다. 최댓값은 플러그인, 설치 설정, 공유의 경우 100이고, 버전과 마켓플레이스의 경우 1,000입니다. 모든 목록은 최신 항목부터 정렬됩니다.

## 오류 응답

오류 응답은 [오류](https://platform.claude.com/docs/ko/api/errors)에 설명된 표준 형식을 따릅니다. 지원팀에 문의할 때는 응답 본문의 `request_id`를 함께 알려 주세요.

| 상태  | 의미                                                                                                                                                                                                     |
| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 400 | 입력이 잘못되었거나, 해당 작업을 이 플러그인 또는 마켓플레이스에 적용할 수 없습니다(각 엔드포인트 섹션 참조). 엔드포인트가 인식하지 못하는 쿼리 매개변수가 포함된 경우와 Claude Enterprise 조직이 아닌 조직인 경우(`this endpoint is not supported for this organization type`)에도 반환됩니다. |
| 401 | `x-api-key` 헤더가 없거나 키를 인식할 수 없습니다.                                                                                                                                                                     |
| 403 | 키에 필요한 scope(범위)가 없거나, 요청이 구성원의 플러그인 또는 개인 마켓플레이스에 업로드하거나, 그 제공 버전을 변경하거나, 그 기본값을 설정하려고 합니다. (구성원의 플러그인 삭제는 허용됩니다.)                                                                                    |
| 404 | 리소스를 찾을 수 없습니다. 요청에 `anthropic-beta` 값이 누락되었거나 조직에서 API가 활성화되지 않은 경우에도 반환되며, 이때 엔드포인트는 존재하지 않는 것처럼 보입니다.                                                                                               |
| 409 | 이름이 이미 사용 중이거나, 콘텐츠 스캔이 아직 실행 중이거나, 충돌하는 업로드가 진행 중입니다.                                                                                                                                                 |
| 413 | 요청 본문이 크기 제한을 초과했습니다. 업로드의 경우 200 MB, 마켓플레이스 검증의 경우 32 MB입니다.                                                                                                                                          |
| 429 | 속도 제한을 초과했습니다. [속도 제한](https://platform.claude.com/docs/ko/manage-claude/plugins-api#rate-limiting)을 참조하세요.                                                                                            |
| 500 | 내부 오류입니다.                                                                                                                                                                                              |
| 503 | 일시적인 오류입니다. 하나의 플러그인에 대한 여러 설치 설정 쓰기 요청이 동시에 도착한 경우에도 반환되므로, 이러한 요청은 하나씩 보내세요. `registration_pending`(다음 표 참조)을 제외하고는 "backoff"(백오프)를 적용하여 재시도하세요.                                                     |

하나의 상태 코드에 서로 다르게 처리해야 하는 여러 원인이 있는 경우, 오류에는 `error.details.error_code`도 포함되며, 원인이 특정 플러그인이나 버전과 관련된 경우 `error.details.plugin_id` 또는 `error.details.plugin_version_id`도 포함됩니다:

```json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "...",
    "details": {
      "error_code": "plugin_name_taken",
      "plugin_id": "plugin_01Hq3vX8kZcN2mB7pR4tY9wL"
    }
  },
  "request_id": "req_018EeWyXxfu5pfWkrYcMdjWG"
}
```

| `error_code`                                    | 상태  | 의미 및 조치 방법                                                                                                                                                                                             |
| ----------------------------------------------- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `plugin_name_taken`                             | 409 | 이 이름을 가진 플러그인이 마켓플레이스에 이미 존재합니다. `details.plugin_id`가 해당 플러그인입니다. 응답을 받지 못한 생성 요청을 재시도하는 중이라면 해당 플러그인으로 계속 진행하세요. `plugin_id`가 없으면 해당 이름은 독립형 스킬이 사용 중인 것입니다. 다른 이름으로 업로드하거나 claude.ai에서 해당 스킬을 삭제하세요. |
| `skill_name_taken`                              | 409 | 플러그인이 라이브러리 마켓플레이스에 있으며, 그 스킬 중 하나가 조직 스킬(관리자가 claude.ai에서 조직 전체를 위해 업로드한 스킬)과 이름이 같습니다. `details.skill_name`에 해당 이름이 표시됩니다. 둘 중 하나의 이름을 바꾸거나 제거하세요.                                                   |
| `registration_pending`                          | 503 | 파일은 저장되었지만 플러그인의 스킬을 아직 구성원이 사용할 수 있도록 만들지 못했습니다. [업로드 재시도](https://platform.claude.com/docs/ko/manage-claude/plugins-api#retrying-uploads)를 참조하세요.                                                    |
| `scan_pending`                                  | 409 | 버전의 콘텐츠 스캔이 아직 실행 중입니다. 스캔이 완료되면 재시도하세요.                                                                                                                                                               |
| `scan_failed`                                   | 400 | 버전의 콘텐츠 스캔이 실패했거나, 오류가 발생했거나, 판정에 도달하지 못해 해당 버전을 제공할 수 없습니다. 다른 버전을 선택하세요.                                                                                                                             |
| `cmek_key_disabled`, `cmek_key_network_blocked` | 400 | 조직의 고객 관리형 암호화 키를 사용할 수 없습니다. [고객 관리형 암호화 키](https://platform.claude.com/docs/ko/manage-claude/plugins-api#customer-managed-encryption-keys)를 참조하세요.                                                   |

새로운 코드가 추가될 수 있습니다. 인식하지 못하는 코드는 해당 상태 코드와 동일하게 처리하세요.

### 업로드 재시도

어떤 엔드포인트도 `Idempotency-Key`를 허용하지 않습니다. 제공 버전 변경, 설치 설정 지정, 마켓플레이스 기본값 설정은 반복해도 안전합니다. 삭제를 반복하거나 설치 설정 제거를 반복하면 `404`가 반환됩니다.

오류를 반환한 업로드는 아무것도 저장하지 않았으며, 단 하나의 예외가 있습니다: `error_code: "registration_pending"`이 포함된 `503`입니다. 서버는 업로드된 파일을 저장한 후 새 버전의 스킬을 claude.ai에 등록하며, 이 과정을 거쳐야 구성원이 스킬을 사용할 수 있습니다. `registration_pending`은 파일은 저장되었지만 이 마지막 단계가 완료되지 않았음을 의미합니다. 동일한 파일을 한 번 더 업로드하면 이 단계가 완료됩니다(그리고 동일한 버전이 하나 더 저장됩니다):

* `POST /v1/organizations/plugins`에서는 플러그인이 *생성된 상태*이며, 응답에 `x-should-retry: false`가 포함됩니다. 생성 요청을 다시 보내지 마세요(다시 보내면 `409 plugin_name_taken`이 반환됩니다). 대신 동일한 파일을 `details.plugin_id`의 버전으로 업로드하세요.
* `POST /v1/organizations/plugins/{plugin_id}/versions`에서는 버전이 *저장된 상태*입니다(`details.plugin_version_id`). 응답에 `x-should-retry: true`가 포함되어 있으면 동일한 요청을 다시 보내고, `false`가 포함되어 있으면 다시 보내지 마세요.

생성 요청의 응답을 받지 못한 경우 재시도하세요. 재시도하면 `details.plugin_id`에 플러그인 ID가 포함된 `409 plugin_name_taken`이 반환되며, 해당 플러그인으로 계속 진행하면 됩니다. 응답을 받지 못한 버전 생성 요청을 재시도하면 동일한 두 번째 버전이 저장됩니다. 이를 방지하려면 각 업로드 전에 플러그인의 `latest_version_id`를 기록해 두세요. 응답을 받지 못한 경우 플러그인을 조회하여 `latest_version_id`가 변경되지 않았을 때만 재시도하세요.

## Activity Feed 이벤트

이 API를 통한 모든 쓰기 작업은 조직의 [Compliance API Activity Feed](https://platform.claude.com/docs/ko/manage-claude/compliance-activity-feed)에 기록되며, `apikey_` ID를 포함하는 `api_actor`로서 API 키에 귀속됩니다. 키가 생성한 플러그인과 버전의 `created_by`에도 동일한 행위자가 표시됩니다.

| 이벤트                                      | 발생 시점                                                                                                          |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `claude_plugin_created`                  | 업로드(여기 또는 claude.ai에서) 또는 승인된 게시 요청으로 플러그인이 생성될 때. Git 동기화로 생성된 플러그인은 `claude_plugin_version_created`만 발생시킵니다. |
| `claude_plugin_version_created`          | 버전이 저장될 때. Git 동기화로 저장된 버전은 `system_actor`에 귀속됩니다.                                                             |
| `claude_plugin_updated`                  | 기존 플러그인에 새 버전이 업로드될 때.                                                                                         |
| `claude_plugin_served_version_updated`   | 제공 버전이 변경될 때.                                                                                                  |
| `claude_plugin_deleted`                  | 플러그인이 여기 또는 claude.ai에서 개별적으로 삭제될 때.                                                                           |
| `plugin_installation_preference_updated` | 설치 설정이 지정되거나 제거될 때.                                                                                            |
| `marketplace_created`                    | 첫 번째 업로드로 라이브러리 마켓플레이스가 생성될 때.                                                                                 |
| `marketplace_updated`                    | 마켓플레이스의 기본 설치 설정이 변경되거나, 관리자 또는 소유자가 claude.ai에서 동기화를 시작할 때.                                                   |
| `marketplace_deleted`                    | claude.ai에서 마켓플레이스가 해당 플러그인과 함께 삭제될 때(플러그인별 이벤트는 발생하지 않음).                                                     |
| `claude_plugin_archive_accessed`         | 구성원 소유 플러그인의 아카이브가 다운로드될 때.                                                                                    |
| `claude_plugin_security_scan_completed`  | 콘텐츠 스캔이 완료될 때.                                                                                                 |

이러한 이벤트의 플러그인, 버전, 마켓플레이스 ID는 이 API가 반환하는 ID와 동일합니다. `plugin_installation_preference_updated`는 플러그인을 `id`가 아닌 `name`과 `marketplace_id`로 식별합니다.

마켓플레이스의 기본값을 변경하면 기본값을 상속하는 모든 플러그인의 값이 변경되더라도 `marketplace_updated` 이벤트 하나만 기록되고 플러그인별 이벤트는 기록되지 않습니다. 구성원 소유 플러그인의 아카이브 다운로드를 제외하고 읽기 작업은 기록되지 않습니다. 아무것도 변경하지 않는 쓰기 작업은 아무것도 기록하지 않습니다.

claude.ai에서 부여되거나 철회된 공유는 피드에 `role_assignment_granted` 및 `role_assignment_revoked` 이벤트로 표시됩니다. 이 API는 삭제를 보고하지 않습니다. 삭제된 플러그인은 다음 목록에서 단순히 나타나지 않을 뿐입니다. Git 동기화, 마켓플레이스 삭제(`marketplace_deleted` 이벤트 하나), 구성원 계정 또는 조직 삭제로 제거된 플러그인은 플러그인별 이벤트를 발생시키지 않으므로, 제거된 항목을 파악하려면 전체 인벤토리를 주기적으로 다시 조회하세요.

## 고객 관리형 암호화 키

조직에서 ["customer-managed encryption key"(고객 관리형 암호화 키)](https://platform.claude.com/docs/ko/manage-claude/cmek)를 사용하는 경우, 버전의 `description`, `release_notes`, `components` 및 파일은 해당 키로 암호화됩니다. 키를 사용할 수 없는 동안에는 다음과 같습니다:

* 읽기 및 목록 조회는 계속 성공하지만, `description`, `release_notes`, `components`는 `null`로 반환됩니다.
* 아카이브 다운로드, 생성, 버전 생성, 제공 버전 변경은 `cmek_key_disabled` 또는 `cmek_key_network_blocked`와 함께 `400`을 반환합니다.
* 라이브러리 마켓플레이스의 플러그인을 삭제하면 `400 cmek_key_disabled`가 반환되고 아무것도 삭제되지 않습니다. 플러그인의 스킬을 먼저 claude.ai에서 철회해야 하는데, 이 작업에 키가 필요하기 때문입니다. 그 외의 삭제, 설치 설정, 마켓플레이스 기본값은 정상적으로 작동합니다.

키를 복원하면 이러한 제한이 모두 해제됩니다.

## 참고 항목

<CardGroup cols={2}>
  <Card title="Admin API 키 생성" href="https://platform.claude.com/docs/ko/manage-claude/admin-api-keys">
    기본 소유자가 범위가 지정된 키를 생성하는 곳입니다.
  </Card>

  <Card title="사용자 관리" href="https://platform.claude.com/docs/ko/manage-claude/user-management">
    설치 설정에 사용되는 `rbac_group_` ID를 제공하는 그룹 엔드포인트입니다.
  </Card>

  <Card title="Compliance API Activity Feed" href="https://platform.claude.com/docs/ko/manage-claude/compliance-activity-feed">
    플러그인 쓰기 작업과 구성원 아카이브 다운로드가 기록되는 곳입니다.
  </Card>

  <Card title="Analytics API" href="https://platform.claude.com/docs/ko/manage-claude/analytics-api">
    Claude Enterprise의 플러그인 및 스킬 사용량 보고입니다.
  </Card>
</CardGroup>
