Skip to main content

Get an access_token

Obtain the app-level access_token. A third-party app backend exchanges the token with the client_credentials grant and uses it to call open APIs for members, organization structure, enterprise information, and robots.

API information​

ItemDescription
API nameGet an access_token
HTTP methodPOST
Endpointhttps://{gateway_host}/auth/v1/oauth/token
Data formatapplication/json
AuthenticationNone; the app credential is exchanged for the token
Cross-originBrowser cross-origin requests are supported; Access-Control-Allow-Credentials is not returned. The App Secret must still never be sent to a browser.

Prerequisites​

  1. The app has been created and published under "Internal Apps" in the admin console.
  2. AppId (the client_id) and AppSecret (the client_secret) are available in the app details under "Credentials and basic information".
  3. Store AppSecret only in the app backend; never send it to a frontend or client.

Request parameters​

Request headers​

HeaderRequiredDescription
Content-TypeYesFixed to application/json

Request body​

{
"client_id": "app_10001",
"client_secret": "link_xxxxxxxxx",
"grant_type": "client_credentials"
}
ParameterTypeRequiredDescription
client_idstringYesApp AppId
client_secretstringYesApp AppSecret
grant_typestringYesGrant type, fixed to client_credentials

Response parameters​

Successful response (the standard OAuth JSON envelope without the platform {code,msg,data} wrapper):

{
"access_token": "opaque-app-access-token",
"expires_in": 7200
}
FieldTypeDescription
access_tokenstringApp-level credential token, valid for 7200 seconds by default (2 hours)
expires_inintegerRemaining credential validity, in seconds

Token usage rules​

  1. Reuse and caching: Reuse access_token during its validity period. The app backend should cache it centrally and refresh it early, for example when five minutes remain, to avoid frequent calls to this API.
  2. Credential isolation: access_token is an app-level credential, not a user session. Do not put it in cookies, send it to clients, or use it as the business system's own Bearer token.
  3. Secret rotation: When an administrator rotates AppSecret, every access_token issued with the old secret becomes invalid immediately. Request a new token with this API.
  4. Transport: When calling open APIs, send the token in Authorization: Bearer <access_token> where possible. Some APIs also support the query parameter ?access_token=<access_token>.

Error codes​

Token exchange failures are returned with an HTTP status code and the OAuth error field:

{
"error": "INVALID_CLIENT",
"error_description": "invalid client credentials"
}
HTTP statuserror codeMeaning and suggested handling
400INVALID_REQUESTThe request is not valid JSON, grant_type is not client_credentials, or a required field is missing.
401INVALID_CLIENTThe app does not exist, is disabled/deleted, or client_id and client_secret do not match.
500SERVER_ERRORServer error; retry later.

Multilingual call examples​

The following examples run on the server; never send app secrets or app tokens to a client.

Shell​

curl -sS -X POST "https://{gateway_host}/auth/v1/oauth/token" \
-H "Content-Type: application/json" \
-d '{"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"}'

PHP​

<?php
// Check the HTTP status and response body in production before mapping business errors.
$handle = curl_init('https://{gateway_host}/auth/v1/oauth/token');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"}',
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($handle);
curl_close($handle);

Golang​

package main

import (
"bytes"
"net/http"
)

func main() {
// Use the token only in a server-side request and send it as specified by the API.
request, _ := http.NewRequest(http.MethodPost, "https://{gateway_host}/auth/v1/oauth/token", bytes.NewBufferString(`{"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"}`))
request.Header.Set("Content-Type", "application/json")
response, _ := http.DefaultClient.Do(request)
defer response.Body.Close()
}

C++​

#include <curl/curl.h>

int main() {
// Enable TLS verification and handle HTTP errors in production.
CURL* handle = curl_easy_init();
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(handle, CURLOPT_URL, "https://{gateway_host}/auth/v1/oauth/token");
curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, R"({"client_id":"app_10001","client_secret":"link_xxxxxxxxx","grant_type":"client_credentials"})");
const CURLcode result = curl_easy_perform(handle);
curl_slist_free_all(headers);
curl_easy_cleanup(handle);
return result == CURLE_OK ? 0 : 1;
}