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 ID 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 tokens - Call
/auth/tokenwith your JWT to receive an ID token and a refresh token - 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 Tokens
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)
{
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "pt1.AQICAHh...",
"IdToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| ExpiresIn | integer | Token expiration time in seconds (typically 3600 = 1 hour) |
| TokenType | string | Always "Bearer" |
| RefreshToken | string | Opaque, long-lived; send it only to /public/auth/refresh (see below) |
| IdToken | string | Use this token for all API requests (Bearer token) |
The response has no AccessToken. Use the IdToken for every API request.
Error Response (Status 401)
{
"message": "Invalid or expired JWT token"
}
Step 3: Use the ID 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 RefreshToken from the auth/token response, unchanged |
Treat the refresh token as opaque and pass it back exactly as you received it. It only works with this endpoint. It stops working when the API key is rotated or deleted, and refresh tokens issued before this format are refused; when a refresh returns 401, sign in again with your JWT.
Refresh Response (Status 200)
{
"ExpiresIn": 3600,
"TokenType": "Bearer",
"IdToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Refresh Response Parameters
| Parameter | Type | Description |
|---|---|---|
| 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 Tokens
async function getTokens(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 getTokens(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 refreshIdToken(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 refreshIdToken(tokens.RefreshToken);