PiTrade Client APIs Authentication
PiTrade Native APIs use a two-step authentication process. First, you generate a JWT token using your credentials, then exchange it for an access token that is used to authenticate all API requests.
Authentication Flow Overview
The authentication process consists of three main steps:
- Generate JWT Token - Create a signed JWT using your
clientIdandapiKey - Exchange for Access Token - Call
/auth/tokenwith your JWT to receive tokens - Use IdToken - Include the
IdTokenin the Authorization header for all Native API requests
Step 1: Generate JWT Token
Create a JWT payload with your client credentials:
JWT Payload Structure
{
"clientId": "YOUR_CLIENT_ID",
"iat": 1689000000,
"exp": 1689003600
}
JWT Payload Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| clientId | string | Yes | Your PiTrade API client ID provided by PiTrade |
| iat | integer | Yes | Issued at time (Unix timestamp) - time when the token was created |
| exp | integer | Yes | Expiration time (Unix timestamp) - typically 1 hour after iat |
JWT Generation
Create a JWT by:
- Encoding the payload as JSON
- Signing with your
apiKeyusing HMAC-SHA256 - Concatenating the header, payload, and signature with dots
Example in Node.js:
const jwt = require("jsonwebtoken");
const payload = {
clientId: "YOUR_CLIENT_ID",
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600,
};
const jwtToken = jwt.sign(payload, "YOUR_API_KEY", {
algorithm: "HS256",
});
Example in Python:
import jwt
import time
payload = {
'clientId': 'YOUR_CLIENT_ID',
'iat': int(time.time()),
'exp': int(time.time()) + 3600
}
jwt_token = jwt.encode(payload, 'YOUR_API_KEY', algorithm='HS256')
Step 2: Exchange JWT for Access Token
Call the /auth/token endpoint with your generated JWT to receive access credentials.
Request
curl --location 'https://api.pitrade.com/public/auth/token' \
--header 'Content-Type: application/json' \
--data '{
"token": "<GENERATED_JWT_TOKEN>"
}'
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | Yes | The JWT token you created |
Successful Response (Status 200)
{
"AccessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "refresh_token_value_here",
"IdToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| AccessToken | string | Short-lived access token (not used directly in APIs) |
| ExpiresIn | integer | Token expiration time in seconds (typically 3600 = 1 hour) |
| TokenType | string | Always "Bearer" |
| RefreshToken | string | Long-lived token used to refresh expired credentials |
| IdToken | string | Use this token for all API requests (Bearer token) |
Error Response (Status 401)
{
"message": "Invalid or expired JWT token"
}
Step 3: Use Access Token for API Requests
Use the IdToken from the /auth/token response to authenticate all PiTrade API requests.
Request Header Format
Authorization: Bearer <ID_TOKEN>
Example API Request
curl --location 'https://api.pitrade.com/client/api/portfolios' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' \
--header 'Content-Type: application/json'
Token Refresh
When your IdToken expires, use the RefreshToken to obtain new credentials without regenerating the JWT.
Refresh Request
curl --location 'https://api.pitrade.com/public/auth/refresh' \
--header 'Content-Type: application/json' \
--data '{
"refresh_token": "<REFRESH_TOKEN>"
}'
Refresh Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| refresh_token | string | Yes | The refresh token from auth/token response |
Refresh Response (Status 200)
{
"AccessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"IdToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Refresh Response Parameters
| Parameter | Type | Description |
|---|---|---|
| AccessToken | string | Short-lived access token |
| ExpiresIn | integer | Token expiration time in seconds |
| TokenType | string | Always "Bearer" |
| IdToken | string | Use this as your new Bearer token |
Refresh Error Response (Status 401)
{
"message": "Invalid or expired refresh token"
}
Complete Authentication Example
Here's a complete end-to-end authentication flow:
1. Generate JWT Token
const jwt = require("jsonwebtoken");
function generateJWT() {
const payload = {
clientId: "YOUR_CLIENT_ID",
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600,
};
return jwt.sign(payload, "YOUR_API_KEY", { algorithm: "HS256" });
}
const jwtToken = generateJWT();
2. Exchange for Access Token
async function getAccessToken(jwtToken) {
const response = await fetch("https://api.pitrade.com/public/auth/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
token: jwtToken,
}),
});
if (!response.ok) {
throw new Error(`Authentication failed: ${response.status}`);
}
const data = await response.json();
return data;
}
const tokens = await getAccessToken(jwtToken);
3. Make API Requests
async function makeAPIRequest(idToken) {
const response = await fetch(
"https://api.pitrade.com/client/api/portfolios",
{
method: "GET",
headers: {
Authorization: `Bearer ${idToken}`,
"Content-Type": "application/json",
},
},
);
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
const data = await response.json();
return data;
}
const apiData = await makeAPIRequest(tokens.IdToken);
4. Refresh Token When Needed
async function refreshAccessToken(refreshToken) {
const response = await fetch("https://api.pitrade.com/public/auth/refresh", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
refresh_token: refreshToken,
}),
});
if (!response.ok) {
throw new Error(`Token refresh failed: ${response.status}`);
}
const data = await response.json();
return data;
}
// When IdToken expires
const newTokens = await refreshAccessToken(tokens.RefreshToken);