SSO Authentication
This feature is in beta. Your AlphaSense account team must enable it on your account before you can use this authentication flow.
This page is for accounts that sign in to AlphaSense through SSO (single sign-on / SAML). Because SSO accounts do not have a separate AlphaSense password, they authenticate to the API with a refresh token grant. You generate a long-lived refresh token once from the AlphaSense web app, then exchange it for short-lived access tokens whenever you call the API.
- You sign in with SSO (your organization's identity provider, no AlphaSense password) — use this page.
- You sign in with an AlphaSense username and password — use Authentication (Username & Password) instead.
The refresh-token grant described here is the go-forward authentication method for all accounts. If you are unsure which applies to you, ask your AlphaSense account team.
Overview
There are two parts to SSO authentication:
- One-time setup (in the web app): Copy your API credentials and generate a refresh token from the API Keys page.
- Every time you call the API (in code): Send the access token to the API and if that expires generate a new access token using the refresh token.
Auth endpoint:
There is an updated authentication endpoint for SSO Authentication.
POST https://auth.research.alpha-sense.com/oauth/token
Step 1 — Get your API credentials
Your credentials live on the API Keys page in the AlphaSense web app:
- Sign in to research.alpha-sense.com.
- Open Preferences.
- Select API Keys.
If your account has an API license attached, the API Credentials panel shows everything you need to authenticate:
| Field | Description |
|---|---|
| Client ID | The client ID issued to your application (client_id). |
| Client Secret | The client secret issued to your application (client_secret). |
| API Key | Your AlphaSense API key, sent as the x-api-key header. |
| API Key ID | An identifier for the API key (reference only — not sent in requests). |
| API Key Created At | When the API key was issued (reference only). |
Click any value to copy it to the clipboard. Use the eye icon to reveal the masked Client Secret and API Key values.
The page only appears when your account has an API license. If you should have access but are seeing an error message contact your AlphaSense account team to confirm your API entitlement.
Step 2 — Generate a refresh token
On the same API Keys page, scroll to the Generate Refresh Token panel:
- Click Generate Refresh Token.
- Complete the quick SSO authentication prompt to confirm your identity.
- The new token appears in the table below, showing its Refresh Token ID, Issued At, and Expires At.
- Click Copy next to the token to copy it.
Store the refresh token somewhere secure (see Credential security) — you will use it in every authentication call.
Refresh tokens are long-lived. The Expires At column on the API Keys page is the source of truth for when a token stops working (typically ~90 days from issuance). When a refresh token expires, return to the API Keys page and generate a new one. You can keep multiple active tokens — for example, one per integration.
Step 3 — Exchange the refresh token for an access token
Send a POST request to the auth endpoint with grant_type=refresh_token. The response contains a
short-lived access token (a signed JWT) that you attach to every API call.
Request parameters
The body must be sent as application/x-www-form-urlencoded.
| Parameter | Type | Location | Required | Description |
|---|---|---|---|---|
x-api-key | string | Header | Yes | Your AlphaSense API key (from Step 1). |
grant_type | string | Body | Yes | Must be "refresh_token". |
client_id | string | Body | Yes | The client ID (from Step 1). |
client_secret | string | Body | Yes | The client secret (from Step 1). |
refresh_token | string | Body | Yes | The refresh token you generated in Step 2. |
Token response
A successful request returns a JSON object with a new access token.
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp...",
"refresh_token": "abcdef-9876-54...",
"token_type": "Bearer",
"expires_in": xxxx
}
| Field | Type | Description |
|---|---|---|
access_token | string | Signed JWT used as the Bearer token in the Authorization header. |
refresh_token | string | A refresh token for the next renewal. If present, store it and use it for subsequent calls. |
token_type | string | Always "Bearer". |
expires_in | integer | Access-token lifetime in seconds. The default is 1800 (30 minutes). |
The access_token is a signed JSON Web Token — do not modify or re-sign it; AlphaSense validates
the signature on every request. If the response includes a rotated refresh_token, use it for your
next refresh; the token you generated in the web app remains valid until its Expires At.
Using the access token
Attach the access token to every API request in the Authorization header:
Authorization: Bearer <access_token>
Code examples
The examples below read all credentials from environment variables. Set these before running:
export ALPHASENSE_API_KEY="your-api-key"
export ALPHASENSE_CLIENT_ID="your-client-id"
export ALPHASENSE_CLIENT_SECRET="your-client-secret"
export ALPHASENSE_REFRESH_TOKEN="the-refresh-token-from-the-api-keys-page"
Get an access token
- Python
- JavaScript
- cURL
import os
import requests
def get_access_token() -> str:
"""Exchange a refresh token for an AlphaSense access token."""
url = "https://auth.research.alpha-sense.com/oauth/token"
headers = {
"x-api-key": os.environ["ALPHASENSE_API_KEY"],
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {
"grant_type": "refresh_token",
"client_id": os.environ["ALPHASENSE_CLIENT_ID"],
"client_secret": os.environ["ALPHASENSE_CLIENT_SECRET"],
"refresh_token": os.environ["ALPHASENSE_REFRESH_TOKEN"],
}
response = requests.post(url, headers=headers, data=payload)
response.raise_for_status()
return response.json()["access_token"]
if __name__ == "__main__":
token = get_access_token()
print("Token acquired (expires per expires_in)")
# Use the token in subsequent requests:
# headers = {"Authorization": f"Bearer {token}"}
async function getAccessToken() {
const url = 'https://auth.research.alpha-sense.com/oauth/token'
const params = new URLSearchParams({
grant_type: 'refresh_token',
client_id: process.env.ALPHASENSE_CLIENT_ID,
client_secret: process.env.ALPHASENSE_CLIENT_SECRET,
refresh_token: process.env.ALPHASENSE_REFRESH_TOKEN,
})
const response = await fetch(url, {
method: 'POST',
headers: {
'x-api-key': process.env.ALPHASENSE_API_KEY,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString(),
})
if (!response.ok) {
const errorBody = await response.text()
throw new Error(`Authentication failed (${response.status}): ${errorBody}`)
}
const tokenData = await response.json()
return tokenData.access_token
}
// Usage
getAccessToken()
.then(token => {
console.log('Token acquired (expires per expires_in)')
// Use the token in subsequent requests:
// const headers = { Authorization: `Bearer ${token}` };
})
.catch(err => console.error(err))
curl -X POST "https://auth.research.alpha-sense.com/oauth/token" \
-H "x-api-key: ${ALPHASENSE_API_KEY}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=${ALPHASENSE_CLIENT_ID}" \
-d "client_secret=${ALPHASENSE_CLIENT_SECRET}" \
-d "refresh_token=${ALPHASENSE_REFRESH_TOKEN}"
Token caching pattern
Access tokens are valid for 30 minutes. For applications that make many API calls, cache the access token and reuse it until it is close to expiry, then exchange the refresh token again. Avoid authenticating on every request.
- Python
- JavaScript
import os
import time
import requests
class AlphaSenseAuth:
"""Manages AlphaSense API authentication using a refresh token (SSO accounts)."""
AUTH_URL = "https://auth.research.alpha-sense.com/oauth/token"
def __init__(self):
self._token = None
self._refresh_token = os.environ["ALPHASENSE_REFRESH_TOKEN"]
self._expires_at = 0
def get_token(self) -> str:
"""Return a valid access token, refreshing if necessary."""
if self._token and time.time() < self._expires_at:
return self._token
headers = {
"x-api-key": os.environ["ALPHASENSE_API_KEY"],
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {
"grant_type": "refresh_token",
"client_id": os.environ["ALPHASENSE_CLIENT_ID"],
"client_secret": os.environ["ALPHASENSE_CLIENT_SECRET"],
"refresh_token": self._refresh_token,
}
response = requests.post(self.AUTH_URL, headers=headers, data=payload)
response.raise_for_status()
data = response.json()
self._token = data["access_token"]
# Use a rotated refresh token if one is returned
self._refresh_token = data.get("refresh_token", self._refresh_token)
# Refresh 5 minutes before actual expiry for safety
self._expires_at = time.time() + data["expires_in"] - 300
return self._token
def get_headers(self) -> dict:
"""Return headers dict ready for authenticated API calls."""
return {
"Authorization": f"Bearer {self.get_token()}",
"x-api-key": os.environ["ALPHASENSE_API_KEY"],
}
class AlphaSenseAuth {
static AUTH_URL = 'https://auth.research.alpha-sense.com/oauth/token'
constructor() {
this.token = null
this.refreshToken = process.env.ALPHASENSE_REFRESH_TOKEN
this.expiresAt = 0
}
async getToken() {
if (this.token && Date.now() < this.expiresAt) {
return this.token
}
const params = new URLSearchParams({
grant_type: 'refresh_token',
client_id: process.env.ALPHASENSE_CLIENT_ID,
client_secret: process.env.ALPHASENSE_CLIENT_SECRET,
refresh_token: this.refreshToken,
})
const response = await fetch(AlphaSenseAuth.AUTH_URL, {
method: 'POST',
headers: {
'x-api-key': process.env.ALPHASENSE_API_KEY,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString(),
})
if (!response.ok) {
const errorBody = await response.text()
throw new Error(`Authentication failed (${response.status}): ${errorBody}`)
}
const data = await response.json()
this.token = data.access_token
// Use a rotated refresh token if one is returned
this.refreshToken = data.refresh_token ?? this.refreshToken
// Refresh 5 minutes before actual expiry for safety
this.expiresAt = Date.now() + (data.expires_in - 300) * 1000
return this.token
}
async getHeaders() {
return {
Authorization: `Bearer ${await this.getToken()}`,
'x-api-key': process.env.ALPHASENSE_API_KEY,
}
}
}
Quick validation
Use the following one-liner to verify that your credentials and refresh token are configured
correctly. A 200 response means authentication succeeded.
- Python
- cURL
python3 -c "
import os, requests
r = requests.post('https://auth.research.alpha-sense.com/oauth/token',
headers={'x-api-key': os.environ['ALPHASENSE_API_KEY'], 'Content-Type': 'application/x-www-form-urlencoded'},
data={'grant_type':'refresh_token','client_id':os.environ['ALPHASENSE_CLIENT_ID'],
'client_secret':os.environ['ALPHASENSE_CLIENT_SECRET'],'refresh_token':os.environ['ALPHASENSE_REFRESH_TOKEN']})
print('Success' if r.ok else f'Error {r.status_code}: {r.text}')
"
curl -s -o /dev/null -w "%{http_code}" -X POST "https://auth.research.alpha-sense.com/oauth/token" \
-H "x-api-key: ${ALPHASENSE_API_KEY}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&client_id=${ALPHASENSE_CLIENT_ID}&client_secret=${ALPHASENSE_CLIENT_SECRET}&refresh_token=${ALPHASENSE_REFRESH_TOKEN}" \
| xargs -I {} sh -c 'if [ "{}" = "200" ]; then echo "Success"; else echo "Error: HTTP {}"; fi'
Credential security
- Load the API key, client secret, and refresh token from environment variables or a secrets manager — never hard-code or commit them.
- Treat the refresh token like a password: anyone holding it can mint access tokens until it expires.
- Rotate tokens by generating a new one on the API Keys page and retiring the old one.
Error handling
Common authentication errors and how to resolve them:
| HTTP Status | Cause | Resolution |
|---|---|---|
400 | Missing or malformed request parameters | Verify all required fields are present and grant_type is "refresh_token". |
401 | Invalid or expired refresh token / credentials | Check your client ID, client secret, and API key. If the refresh token has expired, generate a new one on the API Keys page. |
403 | Valid credentials but insufficient permissions | Confirm your API key is active and your account has API access. |
429 | Too many authentication requests | Cache the access token to reduce auth calls. Back off and retry. |
500 | Server-side error | Retry after a brief delay. Contact support if the issue persists. |
- Authentication (Username & Password) — the password-grant flow for non-SSO accounts.
- On Behalf Of Requests — for service accounts that act on behalf of multiple end users.
- Quick Start — get up and running with the Agent API.
- Explorer — interactively test API endpoints with your credentials.