Before you can get an access token and call the Kinde Management API, follow the steps to create and authorize a machine-to-machine (M2M) application, with scopes .
There are two main methods for getting an access token for the Kinde Management API.
Open the M2M application you created for API access.
Go to Test .
Select Get token .
Select Use test token . You’ll be taken to the API docs with the access token prepopulated. You can now test any endpoint.
For full details, see generate a test access token for the Kinde Management API .
To ask Kinde for an access token for calling the management API, perform a POST request to the https://<your_subdomain>.kinde.com/oauth2/token
endpoint, using the credentials of the M2M application you created in the prerequisite step.
The payload should look as follows:
--url ' https://<your_subdomain>.kinde.com/oauth2/token ' \
--header ' content-type: application/x-www-form-urlencoded ' \
--data grant_type=client_credentials \
--data ' client_id=<your_m2m_client_id> ' \
--data ' client_secret=<your_m2m_client_secret> ' \
--data ' audience=https://<your_subdomain>.kinde.com/api '
var client = new RestClient ( " https://<your_subdomain>.kinde.com/oauth2/token " );
var request = new RestRequest ( Method . POST );
request . AddHeader ( " content-type " , " application/x-www-form-urlencoded " );
request . AddParameter ( " application/x-www-form-urlencoded " , " grant_type=client_credentials&client_id=<your_m2m_client_id>&client_secret=<your_m2m_client_secret>&audience=https%3A%2F%2F<your_subdomain>.kinde.com%2Fapi " , ParameterType . RequestBody );
IRestResponse response = client . Execute ( request );
url := " https://<your_subdomain>.kinde.com/oauth2/token "
payload := strings . NewReader ( " grant_type=client_credentials&client_id=<your_m2m_client_id>&client_secret=<your_m2m_client_secret>&audience=https%3A %2F%2F <your_subdomain>.kinde.com %2F api " )
req , _ := http . NewRequest ( " POST " , url , payload )
req . Header . Add ( " content-type " , " application/x-www-form-urlencoded " )
res , _ := http . DefaultClient . Do ( req )
body , _ := ioutil . ReadAll ( res . Body )
fmt . Println ( string ( body ))
HttpResponse < String > response = Unirest . post ( " https://<your_subdomain>.kinde.com/oauth2/token " )
. header ( " content-type " , " application/x-www-form-urlencoded " )
. body ( " grant_type=client_credentials&client_id=<your_m2m_client_id>&client_secret=<your_m2m_client_secret>&audience=https%3A%2F%2F<your_subdomain>.kinde.com%2Fapi " )
async function getToken () {
const response = await fetch ( ` https://<your_subdomain>.kinde.com/oauth2/token ` , {
" content-type " : " application/x-www-form-urlencoded "
body : new URLSearchParams ( {
audience : " https://<your_subdomain>.kinde.com/api " ,
grant_type : " client_credentials " ,
client_id : " <your_m2m_client_id> " ,
client_secret : " <your_m2m_client_secret> "
throw new Error ( ` Response status: ${ response . status } ` ) ;
const json = await response . json () ;
console . error ( error . message ) ;
#import < Foundation/Foundation.h >
NSDictionary * headers = @ { @" content-type " : @" application/x-www-form-urlencoded " };
NSMutableData * postData = [[ NSMutableData alloc ] initWithData : [ @" grant_type=client_credentials " dataUsingEncoding : NSUTF8StringEncoding ]];
[ postData appendData : [ @" &client_id=<your_m2m_client_id> " dataUsingEncoding : NSUTF8StringEncoding ]];
[ postData appendData : [ @" &client_secret=<your_m2m_client_secret> " dataUsingEncoding : NSUTF8StringEncoding ]];
[ postData appendData : [ @" &audience=https://<your_subdomain>.kinde.com/api " dataUsingEncoding : NSUTF8StringEncoding ]];
NSMutableURLRequest * request = [ NSMutableURLRequest requestWithURL : [ NSURL URLWithString : @" https://<your_subdomain>.kinde.com/oauth2/token " ]
cachePolicy : NSURLRequestUseProtocolCachePolicy
[ request setHTTPMethod : @" POST " ];
[ request setAllHTTPHeaderFields : headers ];
[ request setHTTPBody : postData ];
NSURLSession * session = [ NSURLSession sharedSession ];
NSURLSessionDataTask * dataTask = [ session dataTaskWithRequest : request
completionHandler : ^ ( NSData * data , NSURLResponse * response , NSError * error ) {
NSHTTPURLResponse * httpResponse = ( NSHTTPURLResponse * ) response ;
NSLog ( @" %@ " , httpResponse );
curl_setopt_array ( $ curl , [
CURLOPT_URL => " https://<your_subdomain>.kinde.com/oauth2/token " ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1 ,
CURLOPT_CUSTOMREQUEST => " POST " ,
CURLOPT_POSTFIELDS => " grant_type=client_credentials&client_id=<your_m2m_client_id>&client_secret=<your_m2m_client_secret>&audience=https%3A%2F%2F<your_subdomain>.kinde.com%2Fapi " ,
" content-type: application/x-www-form-urlencoded "
$ response = curl_exec ( $ curl ) ;
$ err = curl_error ( $ curl ) ;
echo " cURL Error #: " . $ err ;
conn = http . client . HTTPSConnection ( "" )
payload = " grant_type=client_credentials&client_id=<your_m2m_client_id>&client_secret=<your_m2m_client_secret>&audience=https%3A %2F%2F <your_subdomain>.kinde.com %2F api "
headers = { ' content-type ' : " application/x-www-form-urlencoded " }
conn . request ( " POST " , " https://<your_subdomain>.kinde.com/oauth2/token " , payload , headers )
print ( data . decode ( " utf-8 " ))
url = URI ( " https://<your_subdomain>.kinde.com/oauth2/token " )
http = Net :: HTTP . new ( url . host , url . port )
http . verify_mode = OpenSSL :: SSL :: VERIFY_NONE
request = Net :: HTTP :: Post . new ( url )
request [ " content-type " ] = ' application/x-www-form-urlencoded '
request . body = " grant_type=client_credentials&client_id=<your_m2m_client_id>&client_secret=<your_m2m_client_secret>&audience=https%3A%2F%2F<your_subdomain>.kinde.com%2Fapi "
response = http . request ( request )
let headers = [ " content-type " : " application/x-www-form-urlencoded " ]
let postData = NSMutableData ( data : " grant_type=client_credentials " . data ( using : String .Encoding. utf8 ) ! )
postData. append ( " &client_id=<your_m2m_client_id> " . data ( using : String .Encoding. utf8 ) ! )
postData. append ( " &client_secret=<your_m2m_client_secret> " . data ( using : String .Encoding. utf8 ) ! )
postData. append ( " &audience=https://<your_subdomain>.kinde.com/api " . data ( using : String .Encoding. utf8 ) ! )
let request = NSMutableURLRequest ( url : NSURL ( string : " https://<your_subdomain>.kinde.com/oauth2/token " ) ! as URL,
cachePolicy : .useProtocolCachePolicy,
request.httpMethod = " POST "
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session. dataTask ( with : request as URLRequest, completionHandler : { ( data, response, error ) -> Void in
let httpResponse = response as? HTTPURLResponse
Make sure to replace <your_subdomain>
, <your_m2m_client_id>
and <your_m2m_client_secret>
with your own details.
The response will contain a signed JWT containing claims including the scopes the token is allowed to access and the expiry time. Here is an example token:
" https://example.kinde.com/api "
" azp " : " bd69bb9fe5db44a38b6b2dacd1f4b451 " ,
" iss " : " https://example.kinde.com " ,
" jti " : " 6f091ebe-44ba-4afc-bd2f-05fcccafc89e " ,
" scope " : " read:users update:users "
To use this token, include it in the Authorization header of your request. For example to get all users you would call:
--url ' https://<your_subdomain>.kinde.com/api/v1/users ' \
--header ' authorization: Bearer <m2m_access_token> ' \
--header ' content-type: application/json '
var client = new RestClient ( " https://<your_subdomain>.kinde.com/api/v1/users " );
var request = new RestRequest ( Method . GET );
request . AddHeader ( " content-type " , " application/json " );
request . AddHeader ( " authorization " , " Bearer <m2m_access_token> " );
IRestResponse response = client . Execute ( request );
url := " https://<your_subdomain>.kinde.com/api/v1/users "
req , _ := http . NewRequest ( " GET " , url , nil )
req . Header . Add ( " content-type " , " application/json " )
req . Header . Add ( " authorization " , " Bearer <m2m_access_token> " )
res , _ := http . DefaultClient . Do ( req )
body , _ := ioutil . ReadAll ( res . Body )
fmt . Println ( string ( body ))
HttpResponse < String > response = Unirest . get ( " https://<your_subdomain>.kinde.com/api/v1/users " )
. header ( " content-type " , " application/json " )
. header ( " authorization " , " Bearer <m2m_access_token> " )
async function getUsers () {
const response = await fetch ( ` https://<your_subdomain>.kinde.com/api/v1/users ` , {
" content-type " : " application/json " ,
authorization : " Bearer <m2m_access_token> "
throw new Error ( ` Response status: ${ response . status } ` ) ;
const json = await response . json () ;
console . error ( error . message ) ;
#import < Foundation/Foundation.h >
NSDictionary * headers = @ { @" content-type " : @" application/json " ,
@" authorization " : @" Bearer <m2m_access_token> " };
NSMutableURLRequest * request = [ NSMutableURLRequest requestWithURL : [ NSURL URLWithString : @" https://<your_subdomain>.kinde.com/api/v1/users " ]
cachePolicy : NSURLRequestUseProtocolCachePolicy
[ request setHTTPMethod : @" GET " ];
[ request setAllHTTPHeaderFields : headers ];
NSURLSession * session = [ NSURLSession sharedSession ];
NSURLSessionDataTask * dataTask = [ session dataTaskWithRequest : request
completionHandler : ^ ( NSData * data , NSURLResponse * response , NSError * error ) {
NSHTTPURLResponse * httpResponse = ( NSHTTPURLResponse * ) response ;
NSLog ( @" %@ " , httpResponse );
curl_setopt_array ( $ curl , [
CURLOPT_URL => " https://<your_subdomain>.kinde.com/api/v1/users " ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1 ,
CURLOPT_CUSTOMREQUEST => " GET " ,
" authorization: Bearer <m2m_access_token> " ,
" content-type: application/json "
$ response = curl_exec ( $ curl ) ;
$ err = curl_error ( $ curl ) ;
echo " cURL Error #: " . $ err ;
conn = http . client . HTTPSConnection ( "" )
' content-type ' : " application/json " ,
' authorization ' : " Bearer <m2m_access_token> "
conn . request ( " GET " , " https://<your_subdomain>.kinde.com/api/v1/users " , headers = headers )
print ( data . decode ( " utf-8 " ))
url = URI ( " https://<your_subdomain>.kinde.com/api/v1/users " )
http = Net :: HTTP . new ( url . host , url . port )
http . verify_mode = OpenSSL :: SSL :: VERIFY_NONE
request = Net :: HTTP :: Get . new ( url )
request [ " content-type " ] = ' application/json '
request [ " authorization " ] = ' Bearer <m2m_access_token> '
response = http . request ( request )
" content-type " : " application/json " ,
" authorization " : " Bearer <m2m_access_token> "
let request = NSMutableURLRequest ( url : NSURL ( string : " https://<your_subdomain>.kinde.com/api/v1/users " ) ! as URL,
cachePolicy : .useProtocolCachePolicy,
request.httpMethod = " GET "
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session. dataTask ( with : request as URLRequest, completionHandler : { ( data, response, error ) -> Void in
let httpResponse = response as? HTTPURLResponse
Make sure to replace <your_subdomain>
with your Kinde subdomain and <m2m_access_token>
with the token received in the previous step.
As an alternative to making HTTP calls, you can also use the Kinde Management API JS SDK.
You can use it to automatically obtain tokens for, and interact with the Kinde management API.
We recommend you do this in a non-production environment first.
If you decide to use Postman, we recommend that you set up a Postman environment. Here’s some troubleshooting solutions in case you need them.
Add your Kinde machine to machine application keys as environment variables.
Make sure you select Save
or the variables will not persist.
Go to Collections . Create a new collection called Kinde .
In the three dots menu next to the new Kinde folder, select Add request .
Go to the Authorization section and set the Type to OAuth 2.0 and set the Header Prefix to Bearer .
In the Configure New Token > Configuration options section, set the Grant Type to Client Credentials .
Enter the Access Token URL using the domain variable you created above. For example, {{business_domain}}/oauth2/token
. Note that even if you use a custom domain, the access token URL should still use your https://<your_subdomain>.kinde.com
domain.
Enter the Client ID and Client Secret using the environment variables you created earlier or by copying them from the Kinde application.
Set the audience to {{business_domain}}/api
. To do this:
Scroll down click Advanced . In the Token request section, select the audience
key and enter the above URL in the Value field. Ensure it is being sent in the body
of the request
Go to the Headers tab.
Select Accept and ensure the value is application/json
.
In the Authorization section, select Get New Access Token . You should see a confirmation message.
Select Proceed .
Select Use Token . You should now have the access token for making requests to the Kinde management API. See the Kinde API documentation for all the available end points.
You can test your API access in Postman by sending a GET
request to any Kinde API endpoint. See the Kinde Management API library for options.
Here’s an example using the Get users
endpoint.
Create a new GET
request.
Enter a URL that contains the /users
endpoint, e.g. https://<your_subdomain>.kinde.com/api/v1/users
.
Send the request. It should return your users in the body section. If it does, the connection is successful.
Repeat from step 1 for any other Kinde API endpoints you want to test.