> 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/en/user-key.md).

# User identification key

## Exchange anonymous user authentication code

> Exchange the one-time authentication code that the mini app obtained through the SDK for an anonymous user identification key. The code can be used only once, within 5 minutes of being issued, and can be exchanged only with the certificate of the mini app that issued it. The partner server can look up or create the member using the anonymous user identification key in this response.\
> \
> \### Business error code\
> \
> The errors below respond with HTTP 200 and \`resultType: FAIL\`.\
> \
> \| errorCode | Description |\
> \| --- | --- |\
> \| \`4011\` | The anonymous user authentication code is invalid. |\
> \| \`4095\` | You have exceeded the request limit. Please try again later. |\
> \
> \*\*Request limit\*\*: 3,000 times per minute per app

```json
{"openapi":"3.1.0","info":{"title":"Apps in Toss partner API","version":"1.0.0"},"tags":[{"description":"This is the API used by a partner server to verify a user identification key or exchange an authentication code.","name":"user-key"}],"servers":[{"description":"Operations (simple login, message sending, Toss points payouts, etc.)","url":"https://apps-in-toss-api.toss.im"}],"security":[{"mutualTLS":[]}],"components":{"securitySchemes":{"mutualTLS":{"description":"This is client-certificate-based mTLS authentication issued to the partner. The mini app is identified by the certificate's CN. Refer to the [Use the server API](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/integration/server-api) document for how to issue and manage certificates.","type":"mutualTLS"}},"schemas":{"ExchangeAnonAuthCodeRequest":{"description":"This is the request body for exchanging an anonymous user authentication code for an anonymous user identification key.","properties":{"code":{"description":"This is the one-time authentication code that the mini app obtained through the SDK and passed to the partner server. It can be used only once, within 5 minutes of being issued.","type":"string"}},"required":["code"]},"TossApiSuccessExchangeAnonAuthCodeResponse":{"description":"This is the success response envelope.","properties":{"resultType":{"description":"This is the processing result. If successful, it is `SUCCESS`.","enum":["SUCCESS"],"type":"string"},"success":{"$ref":"#/components/schemas/ExchangeAnonAuthCodeResponse"}},"required":["resultType","success"],"type":"object"},"ExchangeAnonAuthCodeResponse":{"description":"This is the result of exchanging the anonymous user authentication code.","properties":{"anonKey":{"description":"This is the anonymous user identification key of the user to whom the code was issued. It is always the same value within the same mini app.","type":"string"}},"required":["anonKey"]},"TossApiFail":{"description":"This is the failure response envelope. Business errors are returned with HTTP 200, so be sure to check `resultType`.","properties":{"error":{"$ref":"#/components/schemas/TossApiError"},"resultType":{"description":"This is the processing result. Treat any value other than `SUCCESS` as a failure. It is usually `FAIL`.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"It is always null on failure."}},"required":["error","resultType"],"type":"object"},"TossApiError":{"description":"This is detailed error information.","properties":{"data":{"description":"This is additional error information. When the request limit is exceeded, `retryAfterSeconds` is included.","type":"object"},"errorCode":{"description":"This is the error code. Refer to each API's business error code table.","type":"string"},"errorType":{"description":"This is the internal error classification value. Use `errorCode` for error categorization.","format":"int32","type":"integer"},"reason":{"description":"This is a human-readable error description.","type":"string"},"title":{"description":"This is the error title. It is usually null.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiValidationFail":{"description":"This is the response when request field validation fails.","properties":{"error":{"$ref":"#/components/schemas/TossApiValidationFailError"},"resultType":{"description":"This is the processing result. Treat any value other than `SUCCESS` as a failure. It is usually `FAIL`.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"It is always null on failure."}},"required":["error","resultType"],"type":"object"},"TossApiValidationFailError":{"description":"This is detailed error information.","properties":{"data":{"description":"This is additional error information. When the request limit is exceeded, `retryAfterSeconds` is included.","properties":{"errorDetails":{"description":"This is a detailed list of field-by-field validation failures.","items":{"$ref":"#/components/schemas/TossApiFieldError"},"type":"array"}},"type":"object"},"errorCode":{"description":"This is the error code. Refer to each API's business error code table.","type":"string"},"errorType":{"description":"This is the internal error classification value. Use `errorCode` for error categorization.","format":"int32","type":"integer"},"reason":{"description":"This is a human-readable error description.","type":"string"},"title":{"description":"This is the error title. It is usually null.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiFieldError":{"description":"This is a detailed list of field-by-field validation failures.","properties":{"field":{"description":"This is the name of the field that failed validation.","type":"string"},"message":{"description":"This is the reason for validation failure.","type":"string"},"rejectedValue":{"description":"This is the rejected input value."}},"type":"object"}}},"paths":{"/api-partner/v1/apps-in-toss/users/anon-key/exchange":{"post":{"description":"Exchange the one-time authentication code that the mini app obtained through the SDK for an anonymous user identification key. The code can be used only once, within 5 minutes of being issued, and can be exchanged only with the certificate of the mini app that issued it. The partner server can look up or create the member using the anonymous user identification key in this response.\n\n### Business error code\n\nThe errors below respond with HTTP 200 and `resultType: FAIL`.\n\n| errorCode | Description |\n| --- | --- |\n| `4011` | The anonymous user authentication code is invalid. |\n| `4095` | You have exceeded the request limit. Please try again later. |\n\n**Request limit**: 3,000 times per minute per app","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":"The anonymous user identification key is returned."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiValidationFail"}}},"description":"The request body is not in the correct format. Check the field-by-field details in `error.data.errorDetails`."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiFail"}}},"description":"This is an unclassified server error. If it keeps failing, please contact the partner support channel."}},"summary":"Exchange anonymous user authentication code","tags":["user-key"]}}}}
```

## Verify anonymous user identification key

> Check whether the anonymous user identification key passed in the x-anon-key header is an issued key and belongs to the calling mini app. This does not prove that the requester is that user. For user sign-in, use the anonymous user authentication code exchange API.\
> \
> \### Business error code\
> \
> The errors below respond with HTTP 200 and \`resultType: FAIL\`.\
> \
> \| errorCode | Description |\
> \| --- | --- |\
> \| \`4010\` | Authentication information could not be found. |\
> \| \`4095\` | You have exceeded the request limit. Please try again later. |\
> \
> \*\*Request limit\*\*: 3,000 times per minute per app

```json
{"openapi":"3.1.0","info":{"title":"Apps in Toss partner API","version":"1.0.0"},"tags":[{"description":"This is the API used by a partner server to verify a user identification key or exchange an authentication code.","name":"user-key"}],"servers":[{"description":"Operations (simple login, message sending, Toss points payouts, etc.)","url":"https://apps-in-toss-api.toss.im"}],"security":[{"mutualTLS":[]}],"components":{"securitySchemes":{"mutualTLS":{"description":"This is client-certificate-based mTLS authentication issued to the partner. The mini app is identified by the certificate's CN. Refer to the [Use the server API](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/integration/server-api) document for how to issue and manage certificates.","type":"mutualTLS"}},"schemas":{"TossApiSuccessBoolean":{"description":"This is the success response envelope.","properties":{"resultType":{"description":"This is the processing result. If successful, it is `SUCCESS`.","enum":["SUCCESS"],"type":"string"},"success":{"description":"This is the actual response data on success.","type":"boolean"}},"required":["resultType","success"],"type":"object"},"TossApiFail":{"description":"This is the failure response envelope. Business errors are returned with HTTP 200, so be sure to check `resultType`.","properties":{"error":{"$ref":"#/components/schemas/TossApiError"},"resultType":{"description":"This is the processing result. Treat any value other than `SUCCESS` as a failure. It is usually `FAIL`.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"It is always null on failure."}},"required":["error","resultType"],"type":"object"},"TossApiError":{"description":"This is detailed error information.","properties":{"data":{"description":"This is additional error information. When the request limit is exceeded, `retryAfterSeconds` is included.","type":"object"},"errorCode":{"description":"This is the error code. Refer to each API's business error code table.","type":"string"},"errorType":{"description":"This is the internal error classification value. Use `errorCode` for error categorization.","format":"int32","type":"integer"},"reason":{"description":"This is a human-readable error description.","type":"string"},"title":{"description":"This is the error title. It is usually null.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiValidationFail":{"description":"This is the response when request field validation fails.","properties":{"error":{"$ref":"#/components/schemas/TossApiValidationFailError"},"resultType":{"description":"This is the processing result. Treat any value other than `SUCCESS` as a failure. It is usually `FAIL`.","enum":["FAIL","HTTP_TIMEOUT","NETWORK_ERROR","EXECUTION_FAIL","INTERRUPTED","INTERNAL_ERROR"],"type":"string"},"success":{"description":"It is always null on failure."}},"required":["error","resultType"],"type":"object"},"TossApiValidationFailError":{"description":"This is detailed error information.","properties":{"data":{"description":"This is additional error information. When the request limit is exceeded, `retryAfterSeconds` is included.","properties":{"errorDetails":{"description":"This is a detailed list of field-by-field validation failures.","items":{"$ref":"#/components/schemas/TossApiFieldError"},"type":"array"}},"type":"object"},"errorCode":{"description":"This is the error code. Refer to each API's business error code table.","type":"string"},"errorType":{"description":"This is the internal error classification value. Use `errorCode` for error categorization.","format":"int32","type":"integer"},"reason":{"description":"This is a human-readable error description.","type":"string"},"title":{"description":"This is the error title. It is usually null.","type":"string"}},"required":["errorCode","reason"],"type":"object"},"TossApiFieldError":{"description":"This is a detailed list of field-by-field validation failures.","properties":{"field":{"description":"This is the name of the field that failed validation.","type":"string"},"message":{"description":"This is the reason for validation failure.","type":"string"},"rejectedValue":{"description":"This is the rejected input value."}},"type":"object"}}},"paths":{"/api-partner/v1/apps-in-toss/users/anon-key/verify":{"post":{"description":"Check whether the anonymous user identification key passed in the x-anon-key header is an issued key and belongs to the calling mini app. This does not prove that the requester is that user. For user sign-in, use the anonymous user authentication code exchange API.\n\n### Business error code\n\nThe errors below respond with HTTP 200 and `resultType: FAIL`.\n\n| errorCode | Description |\n| --- | --- |\n| `4010` | Authentication information could not be found. |\n| `4095` | You have exceeded the request limit. Please try again later. |\n\n**Request limit**: 3,000 times per minute per app","operationId":"verifyAnonKey","parameters":[{"description":"It's a key for authenticating users. You can issue it with the [User.getAnonymousKey](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/sdk/domains-api/user/user.getanonymouskey) function in the mini app SDK","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":"The anonymous user identification key verification result is returned as true or false."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiValidationFail"}}},"description":"Request format is invalid. `error.data` is an empty object, and `error.reason` is returned as `Unknown Error`. Missing the `x-anon-key` header is not returned in this response, but as an HTTP 200 business error (`4010`)."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TossApiFail"}}},"description":"This is an unclassified server error. If it keeps failing, please contact the partner support channel."}},"summary":"Verify anonymous user identification key","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 dynamically 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/en/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 `build a script that syncs our docs to a CMS` 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.
