인증

인증 (Authentication)

Claude API는 요청을 인증하는 세 가지 방법을 지원해요:

방법 자격 증명 가장 적합한 경우
API 키 Authorization 헤더에 베어러 토큰으로 보내는 정적 sk-ant-api... 비밀 비밀 저장소를 제어하는 로컬 개발, 프로토타이핑, 스크립트, 서버
Workload Identity Federation ID 제공자의 ID 토큰에서 교환한 단기 베어러 토큰 정적 비밀을 없애고자 하는 클라우드 플랫폼(AWS, Google Cloud, Azure)의 프로덕션 워크로드, CI/CD 파이프라인, Kubernetes
App Attest 등록된 iOS 또는 macOS 앱의 진짜 검증된 설치본에 발급된 단기 액세스 토큰 백엔드나 프록시 없이 앱이 Claude API를 직접 호출하는, 최종 사용자에게 배포하는 iOS·macOS 앱

API 키와 Workload Identity Federation은 Claude API 엔드포인트에 동일한 접근 권한을 부여해요. 빠르게 시작하려면 API 키를 선택하세요: 개인 개발용 개인 키, 공유용 서비스 계정 키. 워크로드가 이미 페더레이션할 수 있는 플랫폼 발급 신원을 가질 때는 Workload Identity Federation으로 전환하세요. 최종 사용자에게 배포하는 iOS·macOS 앱에는 App Attest를 사용하세요.

출처: 문서

본문

API 키

API 키는 Claude Console에서 만들고 모든 요청에 Authorization 헤더의 베어러 토큰으로 보내는 정적 비밀이에요.

키 유형

키를 만들 때 유형을 선택하는데, 이는 키가 무엇을 할 수 있는지, 어디서 작동하는지, 언제 작동을 멈추는지 결정해요:

키 유형 동작하는 주체 작동 범위 작동을 멈추는 시점
개인 키 역할·권한을 가진 사용자 자신 키를 만들 때 선택하는 단일 워크스페이스 또는 역할이 API 사용을 허용하는 워크스페이스들 조직 접근을 잃거나(단일 워크스페이스 키라면 해당 워크스페이스) 조직에서 제거될 때. 개인 키는 조직에서 제거되면 보관 처리돼요. 다시 초대되면 새 키를 만들고, 보관된 키는 복원되지 않아요
서비스 계정 키 서비스 계정 키를 만들 때 선택하는 단일 워크스페이스 또는 서비스 계정이 접근할 수 있는 모든 것. 서비스 계정은 Default Workspace와 추가된 워크스페이스에 접근할 수 있어요 서비스 계정이 보관 처리되거나(단일 워크스페이스 키라면 그 워크스페이스에서 제거될 때)
워크스페이스 키(이전 방식) 아무도 아님: 만들어진 워크스페이스에 속함 해당 워크스페이스 만료, 비활성화·삭제, 또는 만들 사람이 조직을 떠나는 것과 무관하게 워크스페이스가 보관 처리될 때

개인 키와 서비스 계정 키는 신원 연동형이에요. 각각은 조직이 이미 관리하는 사용자 또는 서비스 계정에 속하며, 모든 요청이 그 신원으로 동작해요. 그 신원이 조직에서 제거되면 키가 작동을 멈춰요. 즉, 키가 주인인 사람·워크로드보다 오래 살아남는 일이 우연히 발생하지 않아요. 새 통합에는 워크스페이스 키보다 이것들을 선호하세요.

자신의 개발과 스크립트에는 개인 키를 사용하세요. 공유된 개인 키는 한 사람으로 동작하며 그 사람이 떠나면 깨져요. 공유 또는 자동화 워크로드(CI, 프로덕션 서비스)에서는 조직 admin이 서비스 계정을 만들어 워크로드가 자체 신원을 갖게 하세요.

워크스페이스 API 키는 여전히 작동하지만 이전 방식으로 간주돼요. 신원 연동형 키나 Workload Identity Federation을 선호해요. 마이그레이션하려면 워크스페이스 API 키 교체 참고.

키 만들고 사용하기

  • 키 만들기: Claude Console의 Settings → API keys로 이동해 Create key를 클릭하세요. 키 이름을 정하고 만료를 선택하세요. Linked account를 개인 키라면 자신으로, 여러 사용자 간 공유 키라면 서비스 계정으로 설정하세요. 키를 특정 워크스페이스로 범위를 제한할 수도 있는데, 이렇게 하면 이후 요청에서 워크스페이스 ID를 수동으로 설정하는 것을 건너뛸 수 있어요.
  • 키 사용: 직접 HTTP 요청에서는 Authorization: Bearer <KEY>로 보내거나, ANTHROPIC_API_KEY 환경 변수를 설정하면 클라이언트 SDK가 자동으로 읽어요.
POST /v1/messages
Authorization: Bearer <KEY>
anthropic-version: 2023-06-01
content-type: application/json

이전 방식의 x-api-key: <KEY> 헤더도 Authorization 대신 여전히 지원돼요.

API 키를 비밀 관리자에 저장하고 주기적으로 교체하며, 유출이 의심되는 키는 비활성화하거나 삭제하세요. API keys 페이지에서 Disable은 되돌릴 수 있어요(Admin API가 키의 status"inactive"로 보고하며, Re-enable"active"로 되돌려요). 반면 Delete는 영구적이에요: 키가 보관 처리되고 List API Keysstatus: "archived"로 계속 나타나요. 만료된 키는 삭제만 할 수 있어요. 또한 키를 만들 때 만료를 설정해 유출된 자격 증명이 사용 가능한 기간을 제한할 수 있어요.

```bash cURL curl https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-5-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello, Claude"}] }' ```
client = Anthropic(api_key="my-anthropic-api-key")
# or, with ANTHROPIC_API_KEY set in the environment:
client = Anthropic()
const client = new Anthropic({ apiKey: "my-anth...key" });
// or, with ANTHROPIC_API_KEY set in the environment:
// const client = new Anthropic();
client := anthropic.NewClient(
	option.WithAPIKey("sk-ant-..."), // defaults to os.LookupEnv("ANTHROPIC_API_KEY")
)
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

// Explicit
AnthropicClient client = AnthropicOkHttpClient.builder()
  .apiKey("my-anthropic-api-key")
  .build();

// From ANTHROPIC_API_KEY (or anthropic.apiKey system property)
AnthropicClient clientFromEnv = AnthropicOkHttpClient.fromEnv();
using Anthropic;

AnthropicClient client = new() { ApiKey = "my-anthropic-api-key" };
// Or, with ANTHROPIC_API_KEY set in the environment:
// AnthropicClient client = new();
// Reads ANTHROPIC_API_KEY from the environment
$client = new Client();
// Or pass the key explicitly:
$client = new Client(apiKey: 'my-anth...');
anthropic = Anthropic::Client.new(api_key: "my-anthropic-api-key")
# or, with ANTHROPIC_API_KEY set in the environment:
anthropic = Anthropic::Client.new
# See /docs/en/cli-sdks-libraries/cli/authentication#api-key for zsh, bash, and Windows variants
export ANTHROPIC_API_KEY=sk-ant-...

워크스페이스 선택

특정 워크스페이스용으로 만든 API 키는 그 워크스페이스에서만 작동하며, 이 키를 사용하는 API 요청은 워크스페이스 ID를 생략할 수 있어요.

API 키가 워크스페이스로 범위가 제한되지 않았다면 각 요청에서 anthropic-workspace-id 헤더에 워크스페이스 ID를 지정해야 해요. 요청이나 SDK에서 이 헤더를 설정하는 방법은 아래 예시를 참고하세요.

Admin API는 키가 특정 워크스페이스로 범위가 제한되지 않은 경우에만 개인 키나 서비스 계정 키를 허용해요.

워크스페이스 ID는 Claude Console의 Settings → Workspaces ID 열에서 찾거나 List Workspaces 엔드포인트를 호출해 찾을 수 있어요. List Workspaces는 Default Workspace를 생략해요. 그 ID는 그곳에서 실행되는 요청의 anthropic-workspace-id 응답 헤더에 있어요.

```bash cURL # Required on every request for a multi-workspace key. # Omit the anthropic-workspace-id header for a single-workspace key. curl https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-workspace-id: wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ" \ -H "content-type: application/json" \ -d '{ "model": "claude-opus-5-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello, Claude"}] }' ```
# Required on every command for a multi-workspace key.
# Omit --workspace-id for a single-workspace key.
ant messages create \
  --workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ \
  --model claude-opus-5-5 \
  --max-tokens 1024 \
  --message '{role: user, content: "Hello, Claude"}'
client = Anthropic()  # reads ANTHROPIC_API_KEY

# Required on every request for a multi-workspace key.
# Omit extra_headers for a single-workspace key.
message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude"}],
    extra_headers={"anthropic-workspace-id": "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"},
)
print(message.content)

# Or set it once for every request from this client:
workspace_client = Anthropic(
    default_headers={"anthropic-workspace-id": "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"},
)
const client = new Anthropic(); // reads ANTHROPIC_API_KEY

// Required on every request for a multi-workspace key.
// Omit the second argument for a single-workspace key.
const message = await client.messages.create(
  {
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }]
  },
  { headers: { "anthropic-workspace-id": "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ" } }
);
console.log(message.content);

// Or set it once for every request from this client:
const workspaceClient = new Anthropic({
  defaultHeaders: { "anthropic-workspace-id": "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ" }
});
AnthropicClient client = new(); // reads ANTHROPIC_API_KEY

MessageCreateParams parameters = new()
{
    Model = Model.ClaudeOpus5_5,
    MaxTokens = 1024,
    Messages = [new() { Role = Role.User, Content = "Hello, Claude" }],
};

// Required on every request for a multi-workspace key.
// Call client.Messages.Create(parameters) directly for a single-workspace key.
var message = await client
    .WithOptions(options =>
        options with
        {
            ExtraHeaders = new Dictionary<string, string>
            {
                ["anthropic-workspace-id"] = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
            },
        }
    )
    .Messages.Create(parameters);
Console.WriteLine(message);

// Or set it once for every request from this client:
AnthropicClient workspaceClient = new(new ClientOptions
{
    ExtraHeaders = new Dictionary<string, string>
    {
        ["anthropic-workspace-id"] = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
    },
});
client := anthropic.NewClient() // reads ANTHROPIC_API_KEY

// Required on every request for a multi-workspace key.
// Omit the option for a single-workspace key.
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
	Model:     anthropic.ModelClaudeOpus5_5,
	MaxTokens: 1024,
	Messages: []anthropic.MessageParam{
		anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),
	},
}, option.WithHeader("anthropic-workspace-id", "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"))
if err != nil {
	log.Fatal(err)
}
fmt.Println(message.Content)

// Or set it once for every request from this client:
workspaceClient := anthropic.NewClient(
	option.WithHeader("anthropic-workspace-id", "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"),
)
AnthropicClient client = AnthropicOkHttpClient.fromEnv(); // reads ANTHROPIC_API_KEY

// Required on every request for a multi-workspace key.
// Omit putAdditionalHeader for a single-workspace key.
Message message = client.messages().create(MessageCreateParams.builder()
    .model(Model.CLAUDE_OPUS_5_5)
    .maxTokens(1024)
    .addUserMessage("Hello, Claude")
    .putAdditionalHeader("anthropic-workspace-id", "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ")
    .build());

IO.println(message.content());

// Or set it once for every request from this client:
AnthropicClient workspaceClient = AnthropicOkHttpClient.builder()
    .fromEnv()
    .putHeader("anthropic-workspace-id", "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ")
    .build();
$client = new Client(); // reads ANTHROPIC_API_KEY

// Required on every request for a multi-workspace key.
// Omit requestOptions for a single-workspace key.
$message = $client->messages->create(
    model: Model::CLAUDE_OPUS_5_5,
    maxTokens: 1024,
    messages: [['role' => 'user', 'content' => 'Hello, Claude']],
    requestOptions: [
        'extraHeaders' => ['anthropic-workspace-id' => 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ'],
    ],
);

echo json_encode($message->content), PHP_EOL;
client = Anthropic::Client.new # reads ANTHROPIC_API_KEY

# Required on every request for a multi-workspace key.
# Omit request_options for a single-workspace key.
message = client.messages.create(
  model: Anthropic::Model::CLAUDE_OPUS_5_5,
  max_tokens: 1024,
  messages: [{role: "user", content: "Hello, Claude"}],
  request_options: {extra_headers: {"anthropic-workspace-id" => "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"}}
)

puts message.content

워크스페이스로 범위가 제한되지 않은 키로 만든 요청이 헤더를 생략하면 API는 400 invalid_request_error를 반환해요:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "anthropic-workspace-id is required when authenticating with an identity-linked API key; send the id of the workspace this request acts in."
  },
  "request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}

유효한 워크스페이스 ID가 아닌 헤더 값은 anthropic-workspace-id header must be a valid workspace ID. 메시지와 함께 400 invalid_request_error를 반환해요. 워크스페이스가 존재하지 않거나 키의 사용자·서비스 계정이 접근 권한이 없으면 API는 알 수 없는 워크스페이스와 동일하게 Workspace not found. 메시지와 함께 404 not_found_error를 반환해요.

Workload Identity Federation은 대신 토큰 교환 시 워크스페이스를 선택해요. 자세한 내용은 WIF 참조를 참고하세요.

키 만료

Claude Console의 API keys 페이지에서 API 키를 만들 때 만료를 선택해요: 사전 설정(3시간, 1일, 7일, 30일), 커스텀 기간, 또는 비밀 관리자에 저장하고 직접 교체하는 키라면 Never. 조직에 최대 만료 정책이 있으면 Console은 사전 설정과 커스텀 기간을 정책 최댓값으로 제한하고 Never는 사용할 수 없어요. 기존 키는 현재 동작을 유지해요. 만료는 생성 시 설정되며 이후에 변경할 수 없어요. Claude Console에서 Admin API 키를 만들 때에도 동일한 만료 선택이 적용돼요.

Anthropic은 만료가 가까워지면 키의 생성자에게 이메일을 보내요: 수명이 최소 14일인 키는 만료 7일 전, 수명이 최소 7일인 키는 1일 전이에요. 수명이 더 짧은 키는 경고 이메일 없이 만료돼요.

키가 만료된 후 그 키로 만든 요청은 401 authentication_error를 반환해요. 접근을 복원하려면 새 키를 만들고, 만료된 키는 재활성화할 수 없어요.

Console API 키 표는 각 키의 만료를 보여주고, Admin API는 List API KeysRetrieve API Key 엔드포인트에서 각 키의 expires_at 타임스탬프를 보고해요. 그래서 키가 만료되기 전에 감사하고 교체할 수 있어요. 만료가 없는 키의 필드는 null이에요.

만료는 유출된 자격 증명의 수명을 제한하지만 비밀 위생을 대체하지는 않아요. 만료와 관계없이 키를 비밀 관리자에 저장하고 유출이 의심되는 키는 비활성화하거나 삭제하세요.

워크스페이스 API 키 교체

워크스페이스 키가 있다면 Workload Identity Federation이나 개인·서비스 계정 키로 교체하고 싶을 거예요. 이는 더 나은 보안과 관찰성을 제공해요.

장기 키보다 선호되는 Workload Identity Federation 구성에 대한 자세한 내용은 Workload Identity Federation을 참고하세요.

워크스페이스 키를 개인·서비스 계정 키로 교체하려면:

  1. 키 유형 결정 — 자신의 도구에는 개인 키를 사용하세요. 공유 또는 무인 워크로드에는 서비스 계정 키를 사용하세요.
  2. 필요하면 서비스 계정 만들기 — 조직 admin에게 Settings → Service accounts에서 하나를 만들고 관련 워크스페이스에 추가해 달라고 요청해야 할 수 있어요.
  3. 새 키 만들기 — 여러 워크스페이스가 필요하지 않다면 통합의 워크스페이스 전용으로 만드세요.
  4. 새 키 배포 — 통합이 키를 읽는 곳(보통 ANTHROPIC_API_KEY 환경 변수나 비밀 관리자 항목)에서 이전 키를 교체하세요. 다중 워크스페이스 키라면 워크스페이스 선택에서 보여준 대로 anthropic-workspace-id 헤더도 보내세요.
  5. 이전 키 삭제 — 요청이 성공하는지 확인한 뒤 API keys 페이지에서 워크스페이스 키를 삭제하세요.

Workload Identity Federation

Workload Identity Federation(WIF)은 워크로드가 이미 신뢰하는 ID 제공자(IdP)(예: AWS IAM, Google Cloud, 또는 GitHub Actions, Kubernetes 서비스 계정, SPIFFE, Microsoft Entra ID, Okta 같은 표준 준수 OIDC 발급자)가 발급한 단기 ID 토큰으로 인증하게 해 줘요. 워크로드는 POST /v1/oauth/token에서 IdP가 발급한 JWT를 단기 Claude API 액세스 토큰으로 교환하고, SDK는 만료 전에 그 토큰을 자동으로 갱신해요. 발급·배포·교체할 sk-ant-api... 문자열이 없어요.

페더레이션은 환경에서 장기 Claude API 키를 제거해, 유출된 자격 증명의 폭발 반경을 줄이고 클라우드 리소스에 이미 사용하는 것과 같은 IdP 제어로 접근을 관리하게 해 줘요. 이것만으로 종단 간 보안을 보장하지는 않아요. 신뢰 체인은 ID 제공자 구성만큼만 강하며, 한 홉 위쪽의 장기 비밀(예: IdP 토큰을 발급할 수 있는 정적 클라우드 자격 증명)이 여전히 이를 훼손할 수 있어요. 페더레이션을 IP 허용 목록, MFA, 감사 로깅 같은 제공자 제어와 함께 사용하세요.

페더레이션을 구성하려면 Claude Console에서 세 가지 리소스(서비스 계정, 페더레이션 발급자, 페더레이션 규칙)를 만들고 SDK를 규칙으로 지정하면 돼요. 전체 설정 과정은 Workload Identity Federation을 참고하세요.

App Attest

App Attest는 기기에서 Claude API를 직접 호출하는 iOS·macOS 앱을 인증해요. 각 설치본은 Apple의 App Attest 서비스를 사용해 자신이 Claude Console에 등록한 앱의 진짜 수정되지 않은 빌드임을 증명해요. 그러면 Anthropic이 기기에 단기 액세스 토큰을 발급하고 사용량은 워크스페이스로 청구돼요. 토큰은 워크스페이스로 범위가 제한되고 1시간 후 만료되며 Messages API 호출만 허용해요.

앱을 등록하고 클라이언트 ID를 얻으려면 iOS 및 macOS 앱용 App Attest를 참고하세요.

다음 단계

  • Workload Identity Federation 설정이동 — 발급자·규칙·서비스 계정을 구성한 뒤 토큰을 교환하세요.
  • ID 제공자 가이드이동 — AWS, Google Cloud, Azure, GitHub Actions, Kubernetes, SPIFFE, Okta용 단계별 가이드.
  • WIF 참조이동 — 환경 변수, 검증 규칙, 프로필 구성, 오류 참조.
  • iOS·macOS 앱용 App Attest이동 — 앱의 진짜 설치본이 API 키를 포함하지 않고 Claude API를 호출하게 하세요.
  • 클라이언트 SDK이동 — Python, TypeScript, C#, Go, Java, PHP, Ruby, CLI.

더 알아보기 (Learn more)