Authentication
The Pearsana Partner API uses OAuth 2.0 Client Credentials for authentication. Your server requests a short-lived access token and includes it on every API call.
Environments
| Environment | API Base URL | Auth URL |
|---|---|---|
| Sandbox | https://sandbox.api.pearsana.com | https://sandbox.auth.pearsana.com |
| Production | https://api.pearsana.com | https://auth.pearsana.com |
Start with Sandbox
Use the Sandbox environment for development and testing. Switch to Production URLs when you are ready to go live.
Prerequisites
You need a Client ID and Client Secret. These are created in the Pearsana organisation portal by an Org Admin.
Client Credentials Flow
1. Request an access token
Send a POST to the token endpoint:
curl -X POST https://sandbox.auth.pearsana.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=pearsana-partner/partners.users:write pearsana-partner/partners.invitations:write"2. Response
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "pearsana-partner/partners.users:write pearsana-partner/partners.invitations:write"
}3. Use the token
Include the token in the Authorization header of every API request:
curl https://sandbox.api.pearsana.com/v1/users \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-H "X-API-Version: 2026-01-30"Token Caching
Access tokens expire after the duration specified in expires_in (typically 3600 seconds / 1 hour). Cache the token and request a new one only when the current token is close to expiry:
let cachedToken = null;
let tokenExpiry = null;
async function getAccessToken() {
if (cachedToken && tokenExpiry > Date.now()) {
return cachedToken;
}
const response = await fetch(`${process.env.PEARSANA_AUTH_URL}/oauth2/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.PEARSANA_CLIENT_ID,
client_secret: process.env.PEARSANA_CLIENT_SECRET,
scope: 'pearsana-partner/partners.users:write'
})
});
const data = await response.json();
cachedToken = data.access_token;
tokenExpiry = Date.now() + data.expires_in * 1000 - 60000; // refresh 1 min early
return cachedToken;
}Scopes
When requesting a token, include only the scopes your integration needs. Scopes are space-separated in the token request.
| Scope | Grants access to |
|---|---|
pearsana-partner/ping | GET /ping — connectivity test |
pearsana-partner/partners.externalRefs:read | Read external reference status |
pearsana-partner/partners.externalRefs:write | Write external references (required for invitations) |
pearsana-partner/partners.invitations:read | Read invitations |
pearsana-partner/partners.invitations:write | Create invitations |
pearsana-partner/partners.documents:write | Submit documents |
pearsana-partner/partners.verifications:write | Create verifications (when submitting documents with a verification intent) |
pearsana-partner/partners.users:write | Create users |
Least privilege
Request only the scopes your application actually needs. You select scopes when creating the App Client — the token can only contain scopes that were enabled on the client.
Error Responses
401 Unauthorized
Returned when the Authorization header is missing, the token is expired, or the token is invalid.
{
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required.",
"requestId": "abc-123-def"
}
}403 Insufficient Scope
Returned when the token is valid but does not contain the scopes required by the endpoint.
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "Insufficient OAuth scopes for this operation.",
"details": {
"requiredScopes": ["pearsana-partner/partners.users:write"],
"providedScopes": ["pearsana-partner/ping"]
},
"requestId": "abc-123-def"
}
}Environment Variables
Store your credentials securely. Never commit them to version control.
# .env — Sandbox
PEARSANA_CLIENT_ID=3ieqbnqrjeocomi19jsb6cccf2
PEARSANA_CLIENT_SECRET=your-client-secret-here
PEARSANA_AUTH_URL=https://sandbox.auth.pearsana.com
PEARSANA_API_URL=https://sandbox.api.pearsana.com# .env — Production
PEARSANA_CLIENT_ID=your-production-client-id
PEARSANA_CLIENT_SECRET=your-production-client-secret
PEARSANA_AUTH_URL=https://auth.pearsana.com
PEARSANA_API_URL=https://api.pearsana.comSecurity Best Practices
- Store credentials in environment variables or a secrets manager
- Cache tokens — do not request a new token on every API call
- Request only the scopes you need
- Keep client secrets on the server — never expose them in client-side code
- Never commit credentials to version control
- Never log access tokens