> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/api/user-key.md).

# 사용자 식별 키

## 익명 사용자 인증 코드 교환하기

> 미니앱이 SDK로 발급받은 일회용 인증 코드를 익명 사용자 식별 키로 교환해요. 코드는 발급 후 5분 안에 한 번만 쓸 수 있고, 코드를 발급한 미니앱의 인증서로만 교환할 수 있어요. 파트너 서버는 이 응답의 익명 사용자 식별 키로 회원을 조회하거나 만들면 돼요.\
> \
> \### 비즈니스 오류 코드\
> \
> 아래 오류는 HTTP 200과 \`resultType: FAIL\`로 응답해요.\
> \
> \| errorCode | 설명 |\
> \| --- | --- |\
> \| \`4011\` | 익명 사용자 인증 코드가 유효하지 않아요. |\
> \| \`4095\` | 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요. |\
> \
> \*\*요청 한도\*\*: 앱당 분당 3,000회

```json
{"openapi":"3.1.0","info":{"title":"Apps in Toss 파트너 API","version":"1.0.0"},"tags":[{"description":"파트너 서버에서 사용자 식별 키를 확인하거나 인증 코드를 교환할 때 사용하는 API예요.","name":"user-key"}],"servers":[{"description":"운영 (간편 로그인·메시지 발송·토스 포인트 지급 등)","url":"https://apps-in-toss-api.toss.im"}],"security":[{"mutualTLS":[]}],"components":{"securitySchemes":{"mutualTLS":{"description":"파트너에게 발급된 클라이언트 인증서 기반 mTLS 인증이에요. 인증서의 CN으로 미니앱을 식별해요. 인증서 발급·관리 방법은 [서버 API 이용하기](https://developers-apps-in-toss.toss.im/documentation/integration/server-api) 문서를 참고하세요.","type":"mutualTLS"}},"schemas":{"ExchangeAnonAuthCodeRequest":{"description":"익명 사용자 인증 코드를 익명 사용자 식별 키로 교환하기 위한 요청 본문이에요.","properties":{"code":{"description":"미니앱이 SDK로 발급받아 파트너 서버에 전달한 일회용 인증 코드예요. 발급 후 5분 안에 한 번만 쓸 수 있어요.","type":"string"}},"required":["code"]},"TossApiSuccessExchangeAnonAuthCodeResponse":{"description":"성공 응답 봉투예요.","properties":{"resultType":{"description":"처리 결과예요. 성공이면 `SUCCESS`예요.","enum":["SUCCESS"],"type":"string"},"success":{"$ref":"#/components/schemas/ExchangeAnonAuthCodeResponse"}},"required":["resultType","success"],"type":"object"},"ExchangeAnonAuthCodeResponse":{"description":"익명 사용자 인증 코드 교환 결과예요.","properties":{"anonKey":{"description":"코드를 발급받은 사용자의 익명 사용자 식별 키예요. 같은 미니앱에서는 항상 같은 값이에요.","type":"string"}},"required":["anonKey"]},"TossApiFail":{"description":"실패 응답 봉투예요. 비즈니스 오류는 HTTP 200으로 응답하니 `resultType`을 반드시 확인하세요.","properties":{"error":{"$ref":"#/components/schemas/TossApiError"},"resultType":{"description":"처리 결과예요. `SUCCESS`가 아닌 값은 모두 실패로 처리하세요. 일반적으로 `FAIL`이에요.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"실패 시 항상 null이에요."}},"required":["error","resultType"],"type":"object"},"TossApiError":{"description":"오류 상세 정보예요.","properties":{"data":{"description":"오류 부가 정보예요. 요청 한도 초과 시 `retryAfterSeconds`가 담겨요.","type":"object"},"errorCode":{"description":"오류 코드예요. 각 API의 비즈니스 오류 코드 표를 참고하세요.","type":"string"},"errorType":{"description":"내부 오류 분류 값이에요. 오류 구분에는 `errorCode`를 사용하세요.","format":"int32","type":"integer"},"reason":{"description":"사람이 읽을 수 있는 오류 설명이에요.","type":"string"},"title":{"description":"오류 제목이에요. 대부분 null이에요.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiValidationFail":{"description":"요청 필드 검증에 실패했을 때의 응답이에요.","properties":{"error":{"$ref":"#/components/schemas/TossApiValidationFailError"},"resultType":{"description":"처리 결과예요. `SUCCESS`가 아닌 값은 모두 실패로 처리하세요. 일반적으로 `FAIL`이에요.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"실패 시 항상 null이에요."}},"required":["error","resultType"],"type":"object"},"TossApiValidationFailError":{"description":"오류 상세 정보예요.","properties":{"data":{"description":"오류 부가 정보예요. 요청 한도 초과 시 `retryAfterSeconds`가 담겨요.","properties":{"errorDetails":{"description":"필드별 검증 실패 상세 목록이에요.","items":{"$ref":"#/components/schemas/TossApiFieldError"},"type":"array"}},"type":"object"},"errorCode":{"description":"오류 코드예요. 각 API의 비즈니스 오류 코드 표를 참고하세요.","type":"string"},"errorType":{"description":"내부 오류 분류 값이에요. 오류 구분에는 `errorCode`를 사용하세요.","format":"int32","type":"integer"},"reason":{"description":"사람이 읽을 수 있는 오류 설명이에요.","type":"string"},"title":{"description":"오류 제목이에요. 대부분 null이에요.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiFieldError":{"description":"필드별 검증 실패 상세 목록이에요.","properties":{"field":{"description":"검증에 실패한 필드 이름이에요.","type":"string"},"message":{"description":"검증 실패 사유예요.","type":"string"},"rejectedValue":{"description":"거부된 입력 값이에요."}},"type":"object"}}},"paths":{"/api-partner/v1/apps-in-toss/users/anon-key/exchange":{"post":{"description":"미니앱이 SDK로 발급받은 일회용 인증 코드를 익명 사용자 식별 키로 교환해요. 코드는 발급 후 5분 안에 한 번만 쓸 수 있고, 코드를 발급한 미니앱의 인증서로만 교환할 수 있어요. 파트너 서버는 이 응답의 익명 사용자 식별 키로 회원을 조회하거나 만들면 돼요.\n\n### 비즈니스 오류 코드\n\n아래 오류는 HTTP 200과 `resultType: FAIL`로 응답해요.\n\n| errorCode | 설명 |\n| --- | --- |\n| `4011` | 익명 사용자 인증 코드가 유효하지 않아요. |\n| `4095` | 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요. |\n\n**요청 한도**: 앱당 분당 3,000회","operationId":"exchangeAnonAuthCode","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeAnonAuthCodeRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"discriminator":{"mapping":{"FAIL":"#/components/schemas/TossApiFail","SUCCESS":"#/components/schemas/TossApiSuccessExchangeAnonAuthCodeResponse"},"propertyName":"resultType"},"oneOf":[{"$ref":"#/components/schemas/TossApiSuccessExchangeAnonAuthCodeResponse"},{"$ref":"#/components/schemas/TossApiFail"}]}}},"description":"익명 사용자 식별 키가 돌아와요."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiValidationFail"}}},"description":"요청 본문이 형식에 맞지 않아요. `error.data.errorDetails`에서 필드별 상세를 확인하세요."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiFail"}}},"description":"분류되지 않은 서버 오류예요. 계속 실패하면 파트너 지원 채널로 문의해 주세요."}},"summary":"익명 사용자 인증 코드 교환하기","tags":["user-key"]}}}}
```

## 익명 사용자 식별 키 검증하기

> x-anon-key 헤더로 전달한 익명 사용자 식별 키가 발급된 키이고 호출한 미니앱 소유인지 확인해요. 요청을 보낸 쪽이 그 사용자임을 증명하지는 않아요. 사용자 sign-in에는 익명 사용자 인증 코드 교환 API를 사용하세요.\
> \
> \### 비즈니스 오류 코드\
> \
> 아래 오류는 HTTP 200과 \`resultType: FAIL\`로 응답해요.\
> \
> \| errorCode | 설명 |\
> \| --- | --- |\
> \| \`4010\` | 인증 정보를 찾을 수 없어요. |\
> \| \`4095\` | 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요. |\
> \
> \*\*요청 한도\*\*: 앱당 분당 3,000회

```json
{"openapi":"3.1.0","info":{"title":"Apps in Toss 파트너 API","version":"1.0.0"},"tags":[{"description":"파트너 서버에서 사용자 식별 키를 확인하거나 인증 코드를 교환할 때 사용하는 API예요.","name":"user-key"}],"servers":[{"description":"운영 (간편 로그인·메시지 발송·토스 포인트 지급 등)","url":"https://apps-in-toss-api.toss.im"}],"security":[{"mutualTLS":[]}],"components":{"securitySchemes":{"mutualTLS":{"description":"파트너에게 발급된 클라이언트 인증서 기반 mTLS 인증이에요. 인증서의 CN으로 미니앱을 식별해요. 인증서 발급·관리 방법은 [서버 API 이용하기](https://developers-apps-in-toss.toss.im/documentation/integration/server-api) 문서를 참고하세요.","type":"mutualTLS"}},"schemas":{"TossApiSuccessBoolean":{"description":"성공 응답 봉투예요.","properties":{"resultType":{"description":"처리 결과예요. 성공이면 `SUCCESS`예요.","enum":["SUCCESS"],"type":"string"},"success":{"description":"성공 시 실제 응답 데이터예요.","type":"boolean"}},"required":["resultType","success"],"type":"object"},"TossApiFail":{"description":"실패 응답 봉투예요. 비즈니스 오류는 HTTP 200으로 응답하니 `resultType`을 반드시 확인하세요.","properties":{"error":{"$ref":"#/components/schemas/TossApiError"},"resultType":{"description":"처리 결과예요. `SUCCESS`가 아닌 값은 모두 실패로 처리하세요. 일반적으로 `FAIL`이에요.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"실패 시 항상 null이에요."}},"required":["error","resultType"],"type":"object"},"TossApiError":{"description":"오류 상세 정보예요.","properties":{"data":{"description":"오류 부가 정보예요. 요청 한도 초과 시 `retryAfterSeconds`가 담겨요.","type":"object"},"errorCode":{"description":"오류 코드예요. 각 API의 비즈니스 오류 코드 표를 참고하세요.","type":"string"},"errorType":{"description":"내부 오류 분류 값이에요. 오류 구분에는 `errorCode`를 사용하세요.","format":"int32","type":"integer"},"reason":{"description":"사람이 읽을 수 있는 오류 설명이에요.","type":"string"},"title":{"description":"오류 제목이에요. 대부분 null이에요.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiValidationFail":{"description":"요청 필드 검증에 실패했을 때의 응답이에요.","properties":{"error":{"$ref":"#/components/schemas/TossApiValidationFailError"},"resultType":{"description":"처리 결과예요. `SUCCESS`가 아닌 값은 모두 실패로 처리하세요. 일반적으로 `FAIL`이에요.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"실패 시 항상 null이에요."}},"required":["error","resultType"],"type":"object"},"TossApiValidationFailError":{"description":"오류 상세 정보예요.","properties":{"data":{"description":"오류 부가 정보예요. 요청 한도 초과 시 `retryAfterSeconds`가 담겨요.","properties":{"errorDetails":{"description":"필드별 검증 실패 상세 목록이에요.","items":{"$ref":"#/components/schemas/TossApiFieldError"},"type":"array"}},"type":"object"},"errorCode":{"description":"오류 코드예요. 각 API의 비즈니스 오류 코드 표를 참고하세요.","type":"string"},"errorType":{"description":"내부 오류 분류 값이에요. 오류 구분에는 `errorCode`를 사용하세요.","format":"int32","type":"integer"},"reason":{"description":"사람이 읽을 수 있는 오류 설명이에요.","type":"string"},"title":{"description":"오류 제목이에요. 대부분 null이에요.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiFieldError":{"description":"필드별 검증 실패 상세 목록이에요.","properties":{"field":{"description":"검증에 실패한 필드 이름이에요.","type":"string"},"message":{"description":"검증 실패 사유예요.","type":"string"},"rejectedValue":{"description":"거부된 입력 값이에요."}},"type":"object"}}},"paths":{"/api-partner/v1/apps-in-toss/users/anon-key/verify":{"post":{"description":"x-anon-key 헤더로 전달한 익명 사용자 식별 키가 발급된 키이고 호출한 미니앱 소유인지 확인해요. 요청을 보낸 쪽이 그 사용자임을 증명하지는 않아요. 사용자 sign-in에는 익명 사용자 인증 코드 교환 API를 사용하세요.\n\n### 비즈니스 오류 코드\n\n아래 오류는 HTTP 200과 `resultType: FAIL`로 응답해요.\n\n| errorCode | 설명 |\n| --- | --- |\n| `4010` | 인증 정보를 찾을 수 없어요. |\n| `4095` | 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요. |\n\n**요청 한도**: 앱당 분당 3,000회","operationId":"verifyAnonKey","parameters":[{"description":"사용자를 인증하기 위한 키예요. 미니앱 SDK의 [User.getAnonymousKey](https://developers-apps-in-toss.toss.im/documentation/sdk/domains-api/user/user.getanonymouskey) 함수로 발급받을 수 있어요","in":"header","name":"x-anon-key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"discriminator":{"mapping":{"FAIL":"#/components/schemas/TossApiFail","SUCCESS":"#/components/schemas/TossApiSuccessBoolean"},"propertyName":"resultType"},"oneOf":[{"$ref":"#/components/schemas/TossApiSuccessBoolean"},{"$ref":"#/components/schemas/TossApiFail"}]}}},"description":"익명 사용자 식별 키 검증 결과가 true 또는 false로 돌아와요."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiValidationFail"}}},"description":"요청 형식이 올바르지 않아요. `error.data`는 빈 객체이고 `error.reason`은 `Unknown Error`로 내려가요. `x-anon-key` 헤더 누락은 이 응답이 아니라 HTTP 200의 비즈니스 오류(`4010`)로 내려가요."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiFail"}}},"description":"분류되지 않은 서버 오류예요. 계속 실패하면 파트너 지원 채널로 문의해 주세요."}},"summary":"익명 사용자 식별 키 검증하기","tags":["user-key"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers-apps-in-toss.toss.im/api/user-key.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
