> For the complete documentation index, see [llms.txt](https://docs.blynk.io/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.blynk.io/en/blynk.cloud/platform-https-api/authentication.md).

# Authentication

OAuth2 authentication endpoints for obtaining and refreshing access tokens

## Get access token using client credentials

> Authenticate using your OAuth2 client credentials to obtain an organization-level access token.

```json
{"openapi":"3.0.3","info":{"title":"Blynk Platform API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"OAuth2 authentication endpoints for obtaining and refreshing access tokens"}],"servers":[{"url":"https://{server_address}","description":"Blynk Server","variables":{"server_address":{"default":"blynk.cloud","description":"Your Blynk server domain"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic","description":"HTTP Basic authentication using OAuth2 client credentials (base64-encoded `client_id:client_secret`)"}},"schemas":{"OAuth2Token":{"type":"object","description":"OAuth2 access token response.\n\n**Token lifetimes (subject to change):** Currently, access tokens expire after **24 hours** (86,400 seconds) and refresh tokens share the same lifetime. Always use the `expires_in` value from the response to determine the actual expiration rather than assuming a fixed TTL, as these defaults may be adjusted in the future.\n","properties":{"access_token":{"type":"string","description":"Access token for authenticating API requests. Use as `Bearer` token in the `Authorization` header."},"token_type":{"type":"string","enum":["Bearer"],"description":"Token type"},"expires_in":{"type":"integer","format":"int32","description":"Token expiration time in seconds. Currently defaults to 86,400 (24 hours). This value is subject to change — always rely on the returned value."},"refresh_token":{"type":"string","nullable":true,"description":"Refresh token for obtaining new access tokens. The refresh token currently shares the same lifetime as the access token (24 hours, subject to change). Each refresh token can only be used once."}},"required":["access_token","token_type","expires_in"]},"OAuth2ErrorResponse":{"type":"object","description":"OAuth2 error response following RFC 6749","properties":{"error":{"type":"string","description":"Error code","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type"]},"error_description":{"type":"string","description":"Human-readable error description"}},"required":["error","error_description"]}}},"paths":{"/oauth2/token?grant_type=client_credentials":{"post":{"tags":["Authentication"],"summary":"Get access token using client credentials","description":"Authenticate using your OAuth2 client credentials to obtain an organization-level access token.","operationId":"getAccessTokenByClientCredentials","parameters":[],"responses":{"200":{"description":"Access token issued successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2Token"}}}},"400":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2ErrorResponse"}}}},"500":{"description":"Internal server error"}}}}}}
```

## Get access token using user credentials

> Authenticate using OAuth2 client credentials along with the user's email and password to obtain a user-level access token.\
> The user must belong to the same organization (or its child) as the OAuth2 client.<br>

```json
{"openapi":"3.0.3","info":{"title":"Blynk Platform API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"OAuth2 authentication endpoints for obtaining and refreshing access tokens"}],"servers":[{"url":"https://{server_address}","description":"Blynk Server","variables":{"server_address":{"default":"blynk.cloud","description":"Your Blynk server domain"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic","description":"HTTP Basic authentication using OAuth2 client credentials (base64-encoded `client_id:client_secret`)"}},"schemas":{"OAuth2Token":{"type":"object","description":"OAuth2 access token response.\n\n**Token lifetimes (subject to change):** Currently, access tokens expire after **24 hours** (86,400 seconds) and refresh tokens share the same lifetime. Always use the `expires_in` value from the response to determine the actual expiration rather than assuming a fixed TTL, as these defaults may be adjusted in the future.\n","properties":{"access_token":{"type":"string","description":"Access token for authenticating API requests. Use as `Bearer` token in the `Authorization` header."},"token_type":{"type":"string","enum":["Bearer"],"description":"Token type"},"expires_in":{"type":"integer","format":"int32","description":"Token expiration time in seconds. Currently defaults to 86,400 (24 hours). This value is subject to change — always rely on the returned value."},"refresh_token":{"type":"string","nullable":true,"description":"Refresh token for obtaining new access tokens. The refresh token currently shares the same lifetime as the access token (24 hours, subject to change). Each refresh token can only be used once."}},"required":["access_token","token_type","expires_in"]},"OAuth2ErrorResponse":{"type":"object","description":"OAuth2 error response following RFC 6749","properties":{"error":{"type":"string","description":"Error code","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type"]},"error_description":{"type":"string","description":"Human-readable error description"}},"required":["error","error_description"]}}},"paths":{"/oauth2/token?grant_type=user_credentials":{"post":{"tags":["Authentication"],"summary":"Get access token using user credentials","description":"Authenticate using OAuth2 client credentials along with the user's email and password to obtain a user-level access token.\nThe user must belong to the same organization (or its child) as the OAuth2 client.\n","operationId":"getAccessTokenByUserCredentials","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userEmail":{"type":"string","format":"email","description":"User email address"},"password":{"type":"string","format":"password","description":"User password"}},"required":["userEmail","password"]}}}},"responses":{"200":{"description":"Access token issued successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2Token"}}}},"400":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2ErrorResponse"}}}},"500":{"description":"Internal server error"}}}}}}
```

## Refresh an access token

> Exchange a refresh token for a new access token.\
> Each refresh token can only be used \*\*once\*\* — after use, the previous refresh token is invalidated and a new one is returned.<br>

```json
{"openapi":"3.0.3","info":{"title":"Blynk Platform API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"OAuth2 authentication endpoints for obtaining and refreshing access tokens"}],"servers":[{"url":"https://{server_address}","description":"Blynk Server","variables":{"server_address":{"default":"blynk.cloud","description":"Your Blynk server domain"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic","description":"HTTP Basic authentication using OAuth2 client credentials (base64-encoded `client_id:client_secret`)"}},"schemas":{"OAuth2Token":{"type":"object","description":"OAuth2 access token response.\n\n**Token lifetimes (subject to change):** Currently, access tokens expire after **24 hours** (86,400 seconds) and refresh tokens share the same lifetime. Always use the `expires_in` value from the response to determine the actual expiration rather than assuming a fixed TTL, as these defaults may be adjusted in the future.\n","properties":{"access_token":{"type":"string","description":"Access token for authenticating API requests. Use as `Bearer` token in the `Authorization` header."},"token_type":{"type":"string","enum":["Bearer"],"description":"Token type"},"expires_in":{"type":"integer","format":"int32","description":"Token expiration time in seconds. Currently defaults to 86,400 (24 hours). This value is subject to change — always rely on the returned value."},"refresh_token":{"type":"string","nullable":true,"description":"Refresh token for obtaining new access tokens. The refresh token currently shares the same lifetime as the access token (24 hours, subject to change). Each refresh token can only be used once."}},"required":["access_token","token_type","expires_in"]},"OAuth2ErrorResponse":{"type":"object","description":"OAuth2 error response following RFC 6749","properties":{"error":{"type":"string","description":"Error code","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type"]},"error_description":{"type":"string","description":"Human-readable error description"}},"required":["error","error_description"]}}},"paths":{"/oauth2/token?grant_type=refresh_token":{"post":{"tags":["Authentication"],"summary":"Refresh an access token","description":"Exchange a refresh token for a new access token.\nEach refresh token can only be used **once** — after use, the previous refresh token is invalidated and a new one is returned.\n","operationId":"refreshAccessToken","parameters":[{"name":"refresh_token","in":"query","required":true,"schema":{"type":"string"},"description":"The refresh token obtained from a previous token response"}],"responses":{"200":{"description":"Access token refreshed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2Token"}}}},"400":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2ErrorResponse"}}}},"500":{"description":"Internal server error"}}}}}}
```

## Introspect an access token

> Determine whether an access token is currently active and, if so, return metadata about it (RFC 7662 style).\
> \
> \- The calling client authenticates with its own OAuth2 client credentials (HTTP Basic, same as \`/oauth2/token\`).\
> \- The token to introspect \*\*must\*\* be sent in the request body as \`application/x-www-form-urlencoded\`\
> &#x20; (\`token=\<token>\`). It is \*\*never\*\* accepted via the query string.\
> \
> The endpoint always responds with \`200\` when the request and caller are valid. A token that is invalid, expired,\
> or revoked (including OAuth client deletion/secret regeneration, user deactivation, or organization removal) is\
> reported with the exact body \`{"active": false}\` and no reason detail. A token issued in another region is not\
> present in this region's token store and is therefore also reported as \`{"active": false}\`.\
> \
> The response schema is a stable, versioned contract — only additive changes will be made.<br>

```json
{"openapi":"3.0.3","info":{"title":"Blynk Platform API","version":"1.0.0"},"tags":[{"name":"Authentication","description":"OAuth2 authentication endpoints for obtaining and refreshing access tokens"}],"servers":[{"url":"https://{server_address}","description":"Blynk Server","variables":{"server_address":{"default":"blynk.cloud","description":"Your Blynk server domain"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic","description":"HTTP Basic authentication using OAuth2 client credentials (base64-encoded `client_id:client_secret`)"}},"schemas":{"OAuth2IntrospectionResponse":{"type":"object","description":"Token introspection response (RFC 7662 style).\n\nThis schema is a stable, versioned contract: only additive changes are made. For an inactive token only the\n`active` field is present (the body is exactly `{\"active\": false}`); all other fields are omitted.\n","properties":{"active":{"type":"boolean","description":"Whether the token is currently active (valid, not expired, not revoked, and local to this region)."},"org_id":{"type":"integer","format":"int32","description":"Organization the token belongs to. Present only for active tokens."},"grant_type":{"type":"string","enum":["client_credentials","user_credentials"],"description":"The grant type the token was issued with. Present only for active tokens."},"client_id":{"type":"string","description":"The OAuth2 client the token was issued to. Present only for active tokens."},"sub":{"type":"string","nullable":true,"description":"The user id the token is scoped to. Only present (non-null) for user-scoped tokens."},"role":{"type":"string","nullable":true,"description":"The user's organization role. Only present (non-null) for user-scoped tokens."},"exp":{"type":"integer","format":"int64","description":"Expiration time in epoch seconds. Present for active tokens; omitted for permanent tokens."},"iat":{"type":"integer","format":"int64","description":"Issued-at time in epoch seconds. Present only for active tokens."},"token_type":{"type":"string","enum":["Bearer"],"description":"Token type. Present only for active tokens."}},"required":["active"]},"OAuth2ErrorResponse":{"type":"object","description":"OAuth2 error response following RFC 6749","properties":{"error":{"type":"string","description":"Error code","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type"]},"error_description":{"type":"string","description":"Human-readable error description"}},"required":["error","error_description"]}}},"paths":{"/oauth2/introspect":{"post":{"tags":["Authentication"],"summary":"Introspect an access token","description":"Determine whether an access token is currently active and, if so, return metadata about it (RFC 7662 style).\n\n- The calling client authenticates with its own OAuth2 client credentials (HTTP Basic, same as `/oauth2/token`).\n- The token to introspect **must** be sent in the request body as `application/x-www-form-urlencoded`\n  (`token=<token>`). It is **never** accepted via the query string.\n\nThe endpoint always responds with `200` when the request and caller are valid. A token that is invalid, expired,\nor revoked (including OAuth client deletion/secret regeneration, user deactivation, or organization removal) is\nreported with the exact body `{\"active\": false}` and no reason detail. A token issued in another region is not\npresent in this region's token store and is therefore also reported as `{\"active\": false}`.\n\nThe response schema is a stable, versioned contract — only additive changes will be made.\n","operationId":"introspectToken","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The access token to introspect."}},"required":["token"]}}}},"responses":{"200":{"description":"Introspection result (always returned when the request and caller are valid)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2IntrospectionResponse"}}}},"400":{"description":"Malformed request (e.g. missing token, token supplied in the query string, or wrong Content-Type)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2ErrorResponse"}}}},"401":{"description":"Missing or invalid caller credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuth2ErrorResponse"}}}},"500":{"description":"Internal server error"}}}}}}
```


---

# 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 current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.blynk.io/en/blynk.cloud/platform-https-api/authentication.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
