Generate Session Token NEW
POST /session/token
The Generate Session Token API is the direct way for headless / server-to-server integrations to obtain a session token using your OAuth app's apiKey and apiSecret — without launching a browser-based OAuth login.
Two ways to obtain a session token
- Direct (this page) —
POST /session/tokenwithapiKey+apiSecret. Recommended for backend bots, scheduled jobs, and any flow where the user is not present in a browser. - OAuth 2.1 Authorization-Code Flow — your app redirects the end-user to the SAMCO consent page; the user authorises on SAMCO's domain; the browser is redirected back to your callback URL with a short-lived
code, and your backend exchanges it atPOST /oauth/tokenfor anaccess_token(used asx-session-token). Recommended when you're building a third-party app that signs in end-users (you never see their password or the API secret).
Both flows produce a session token that is sent as the x-session-token header on subsequent Trade API calls.
Pre-requisites
- The OAuth app must be Active (created via the Web Dashboard).
- At least one Static IP must be registered for the app via the dashboard. Calls to order-related APIs are rejected from non-whitelisted IPs.
Parameter
| Name | Type | Required | Description |
|---|---|---|---|
apiKey | string | true | AES-encrypted API key of the app. |
apiSecret | string | true | AES-encrypted API secret of the app. |
Sample Request Body
requestBody={
"apiKey" : "<AES_ENCRYPTED_API_KEY>",
"apiSecret" : "<AES_ENCRYPTED_API_SECRET>"
}Sample Code
curl -X POST 'https://tradeapi.samco.in/session/token' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"apiKey":"<AES_ENCRYPTED_API_KEY>","apiSecret":"<AES_ENCRYPTED_API_SECRET>"}'import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Sample {
public static void main(String[] args) throws Exception {
String requestBody = """
{
"apiKey": "<AES_ENCRYPTED_API_KEY>",
"apiSecret": "<AES_ENCRYPTED_API_SECRET>"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://tradeapi.samco.in/session/token"))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}(async () => {
const headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
const requestBody = {
apiKey: "<AES_ENCRYPTED_API_KEY>",
apiSecret: "<AES_ENCRYPTED_API_SECRET>"
};
const response = await fetch('https://tradeapi.samco.in/session/token', {
method: 'POST',
headers,
body: JSON.stringify(requestBody),
});
const data = await response.json();
console.log(data);
})();import requests
import json
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
}
requestBody = {
"apiKey": "<AES_ENCRYPTED_API_KEY>",
"apiSecret": "<AES_ENCRYPTED_API_SECRET>"
}
r = requests.post('https://tradeapi.samco.in/session/token',
data=json.dumps(requestBody),
headers=headers)
print(r.json())Sample Response
{
"serverTime": "29/01/26 10:46:06",
"msgId": "d5f083f3-1b04-4b97-9385-1e578fdfeb7a",
"status": "Success",
"statusMessage": "Session token generated successfully",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenId": "550e8400-e29b-41d4-a716-446655440000",
"accountID": "DV99999",
"accountName": "JOHN DOE",
"exchangeList": ["NSE", "BSE", "NFO", "MCX"],
"orderTypeList": ["L", "MKT", "SL", "SL-M"],
"productList": ["MIS", "CNC", "NRML"],
"srcIp": "203.0.113.10",
"primaryIp": "203.0.113.10",
"secondaryIp": "203.0.113.11"
}{
"status": "Failure",
"statusMessage": "apiKey and apiSecret are required"
}{
"status": "Failure",
"statusMessage": "Invalid API key",
"errorCode": "EOAUTH001"
}{
"status": "Failure",
"statusMessage": "Invalid or inactive API key",
"errorCode": "EOAUTH001"
}{
"status": "Failure",
"statusMessage": "Invalid API secret format",
"errorCode": "EOAUTH008"
}{
"status": "Failure",
"statusMessage": "Invalid API secret",
"errorCode": "EOAUTH008"
}{
"status": "Failure",
"statusMessage": "User not subscribed. Please subscribe to access trade API"
}{
"status": "Failure",
"statusMessage": "User account is blocked"
}{
"status": "Failure",
"statusMessage": "Unable to start your trading session. Please open the SAMCO mobile app, sign in once, and then retry."
}"Unable to start your trading session" — what to do
This response means your apiKey + apiSecret were accepted, but our trading backend could not establish a session for the underlying SAMCO trading account. The fastest fix is for the account holder to:
- Open the SAMCO mobile app (or Samco Web) and sign in once with their Client ID + password (and OTP).
- If the password is rejected, complete a password reset from the mobile app's Forgot Password flow.
- If the account shows as blocked / dormant / under review, the user must clear that status before any API session can be issued — reach out to support@samco.in or call the SAMCO support desk to unblock / reactivate the account.
- Once a mobile-app login succeeds, retry
POST /session/tokenfrom your integration.
This applies to both this Direct flow and the OAuth 2.1 Authorization-Code Flow — the underlying trading-account check is the same in both cases.
Response Schema
Status Code 200
| Name | Type | Description |
|---|---|---|
serverTime | string | The date and time when the server generated the response. |
msgId | string | Unique identifier for the API response message. |
status | string | Success on a valid login. |
statusMessage | string | Human-readable message. |
sessionToken | string | JWT session token — send as x-session-token on all subsequent Trade API calls. Expires at the next 08:00 IST. |
tokenId | string | Server-side identifier for this session (used internally for revocation / audit). |
accountID | string | Trading account / client ID. |
accountName | string | Display name on the trading account. |
exchangeList | array | Exchanges available to this account (NSE, BSE, NFO, MCX, …). |
orderTypeList | array | Order types this account is permitted to place. |
productList | array | Product types this account is permitted to trade (MIS, CNC, NRML). |
srcIp | string | The source IP our server sees this request coming from. |
primaryIp | string | The PRIMARY IP currently registered for this app (or default mapping). |
secondaryIp | string | The SECONDARY IP currently registered for this app, if any. |
Verify your IP at integration time
Compare srcIp against primaryIp and secondaryIp immediately after login. If they don't match, order-related endpoints will reject this host with HTTP 403 and statusMessage: "The IP is not the registered static IP". For ongoing diagnostics from any backend host (multi-pod deployments, fallback hosts), call GET /ip/whoami instead.
Token lifetime
The sessionToken is valid until 08:00 IST the next day. After expiry, call this endpoint again with the same apiKey + apiSecret to obtain a fresh token.
Error codes
The same errorCode scheme used by the OAuth endpoints applies here so a single error-handling block in your integration can cover both flows.
errorCode | Meaning | Remediation |
|---|---|---|
EOAUTH001 | The apiKey cannot be decrypted, or no active OAuth app exists for it. | Confirm you are sending the AES-encrypted value emailed at app creation, and that the app is in Active state. If the app was created in a different environment than the one being called (or after an AES_KEY rotation), regenerate the app in the target environment. |
EOAUTH008 | The apiSecret cannot be decrypted, or its hash does not match the secret stored for the app. | Re-fetch the secret from the dashboard's API Keys → Reveal Secret flow, or regenerate it. |
EOAUTH009 | Calling IP is not registered for this app (only enforced on order-related calls; not on this login). | Register the IP under Static IPs in the dashboard. |