Get Access Token

Exchange your API application's client ID and secret for a bearer token, then use it to call any PerspioTalk API.

PerspioTalk APIs use the OAuth 2.0 client credentials grant. Your integration sends its client_id and client_secret to the token endpoint and gets back a short-lived access token. There is no interactive login and no refresh token: when a token expires, you request a new one the same way.

🚧

Before you start

You need an API application in your Perspio tenant. Create Application gives you the four values used on this page:

  • Client ID (client_id) and client secret (client_secret), to request a token
  • Tenant ID (tid) and subscription key (Ocp-Apim-Subscription-Key), to call the APIs with it

Request a token

Send a POST to the token endpoint for the region your tenant is hosted in. It's the same host you use for every other PerspioTalk API.

RegionToken endpoint
AUhttps://talk.perspio.io/auth/v3/token
UShttps://us-talk.perspio.io/auth/v3/token

Send the body form-encoded (Content-Type: application/x-www-form-urlencoded), not as JSON. No other headers are needed: the token request doesn't take your tenant ID or subscription key.

Body parameters

ParameterValue
grant_typeAlways client_credentials
client_idThe client ID of your API application
client_secretThe client secret of your API application
POST /auth/v3/token HTTP/1.1
Host: talk.perspio.io
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}
curl --request POST 'https://talk.perspio.io/auth/v3/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_id={client_id}' \
  --data-urlencode 'client_secret={client_secret}'
$body = @{
    grant_type    = 'client_credentials'
    client_id     = '{client_id}'
    client_secret = '{client_secret}'
}
$token = Invoke-RestMethod -Method Post -Uri 'https://talk.perspio.io/auth/v3/token' `
    -ContentType 'application/x-www-form-urlencoded' -Body $body

$token.access_token
import requests

response = requests.post(
    "https://talk.perspio.io/auth/v3/token",
    data={
        "grant_type": "client_credentials",
        "client_id": "{client_id}",
        "client_secret": "{client_secret}",
    },
    timeout=30,
)
response.raise_for_status()
access_token = response.json()["access_token"]
const response = await fetch("https://talk.perspio.io/auth/v3/token", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "client_credentials",
    client_id: "{client_id}",
    client_secret: "{client_secret}",
  }),
});
if (!response.ok) throw new Error(`Token request failed: ${response.status}`);
const { access_token } = await response.json();
using var http = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "https://talk.perspio.io/auth/v3/token")
{
    Content = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        ["grant_type"] = "client_credentials",
        ["client_id"] = "{client_id}",
        ["client_secret"] = "{client_secret}",
    }),
};

using var response = await http.SendAsync(request);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
var accessToken = json.GetProperty("access_token").GetString();

Token response

A successful request returns 200 OK with the token in JSON.

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_in": 3600,
  "token_type": "bearer"
}
PropertyDescription
access_tokenThe token to send on every API call, as Authorization: Bearer {access_token}
expires_inSeconds until the token expires. Tokens last one hour (3600)
token_typeAlways bearer

Call an API with the token

Every PerspioTalk request needs three headers. The access token proves who is calling, the tenant ID says which tenant, and the subscription key identifies your tenant's API subscription.

HeaderValue
AuthorizationBearer {access_token}
tidYour tenant ID
Ocp-Apim-Subscription-KeyYour subscription key

The tenant ID must be the tenant your API application belongs to. A token used with any other tenant ID returns 401 Unauthorized.

For example, Get Assets lists the assets in your tenant:

curl --request GET 'https://talk.perspio.io/assets/v3/' \
  --header 'Authorization: Bearer {access_token}' \
  --header 'tid: {tid}' \
  --header 'Ocp-Apim-Subscription-Key: {subscription_key}' \
  --header 'Accept: application/json'
$headers = @{
    Authorization               = "Bearer $($token.access_token)"
    tid                         = '{tid}'
    'Ocp-Apim-Subscription-Key' = '{subscription_key}'
}
Invoke-RestMethod -Uri 'https://talk.perspio.io/assets/v3/' -Headers $headers
👍

Try it in these docs

Every endpoint page has a Credentials panel. Enter your access token, tenant ID and subscription key there, on a page such as Get Assets, to send live requests from your browser.

When the token expires

Tokens last one hour.

  • Reuse the token. Cache it and send it on every call until it's close to expiry. Don't request a new token per API call.
  • Renew early. Request a new token a few minutes before the hour is up, so in-flight calls don't fail.
  • Handle 401. An expired or invalid token returns 401 Unauthorized. Request a new token and retry the call once.

There are no refresh tokens with the client credentials grant. A new token request with the same client_id and client_secret is how you renew.

Errors

Token errors use the standard OAuth 2.0 format: an error code, usually with an error_description.

{
  "error": "invalid_client",
  "error_description": "Application not found."
}
StatuserrorMeaning
400invalid_requestclient_id or client_secret is missing
400unsupported_grant_typegrant_type isn't client_credentials, or the body was sent as JSON instead of form-encoded
401invalid_clientThe client ID or client secret is wrong
429Too many requests. Wait and retry with backoff
5xxThe sign-in service is briefly unavailable. Retry with backoff
❗️

Keep these values server-side

Your client secret and subscription key grant access to your Perspio tenant. Never put them in browser or mobile app code, and never commit them to source control. If a secret is exposed, generate a new one from the API application in Perspio.