API Authentication Guide
Simplified authentication for OptionsPlay® RESTful APIs
Overview
OptionsPlay is introducing a streamlined authentication method for our RESTful APIs. The new approach eliminates the need for OAuth token management, reducing your integration complexity from multiple steps to a single API key.
The legacy OAuth approach continues to work. You can migrate at your convenience—there's no deadline to switch. However, we recommend the new approach for simpler integration and reduced maintenance.
What's Changing
The new approach handles OAuth behind the scenes. You simply include your subscription key with each request—no token acquisition, no token refresh, no expiration handling.
Quick Comparison
- Two credentials (clientId + clientSecret)
- Requires token endpoint call
- Tokens expire (~60 minutes)
- You manage token refresh logic
- Base URL:
app.optionsplay.com - Header:
Authorization: Bearer ...
- Single API key
- No token endpoint needed
- Key doesn't expire
- No refresh logic required
- Base URL:
apis.optionsplay.com - Header:
Op-Subscription-Key: ...
| Aspect | Legacy | New |
|---|---|---|
| Credentials | clientId + clientSecret | Single API key |
| Base URL | https://app.optionsplay.com |
https://apis.optionsplay.com |
| Auth Header | Authorization: Bearer {token} |
Op-Subscription-Key: {apiKey} |
| Token Management | Required (acquire + refresh) | Not needed |
| Usage Analytics | Limited | Full portal access |
New Approach: Subscription Key
With the new approach, include your subscription key in the Op-Subscription-Key
header with every request. That's it.
Request Format
curl -X GET "https://apis.optionsplay.com/api/v1/platform/why/AAPL" \
-H "Op-Subscription-Key: YOUR_API_KEY"
Authentication Flow
handled automatically
The API gateway manages OAuth tokens internally. Your code simply sends the subscription key—no need to handle token expiration, refresh logic, or retry mechanisms.
Legacy Approach: OAuth Bearer Token
The legacy approach remains fully supported. If you have an existing integration, it will continue to work without changes.
Step 1: Acquire Token
curl -X POST "https://app.optionsplay.com/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"
Step 2: Use Token
curl -X GET "https://app.optionsplay.com/api/v1/platform/why/AAPL" \
-H "Authorization: Bearer {access_token}"
Token Lifecycle
Migration Steps
Migrating to the new approach takes just a few minutes:
Get Your Subscription Key
Contact your OptionsPlay account representative or email support@optionsplay.com to receive your new API subscription key.
Update Base URL
Change your API base URL from app.optionsplay.com to
apis.optionsplay.com. The API paths remain the same.
Replace Auth Header
Replace Authorization: Bearer {token} with
Op-Subscription-Key: {apiKey} in your requests.
Remove Token Logic
Delete your token acquisition and refresh code. It's no longer needed—enjoy the simpler codebase!
Code Examples
Before (Legacy)
# Step 1: Get token
TOKEN=$(curl -s -X POST "https://app.optionsplay.com/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" | jq -r '.access_token')
# Step 2: Call API
curl -X GET "https://app.optionsplay.com/api/v1/platform/why/AAPL" \
-H "Authorization: Bearer $TOKEN"
import requests
from datetime import datetime, timedelta
class OptionsPlayClient:
def __init__(self, client_id, client_secret):
self.client_id = client_id
self.client_secret = client_secret
self.base_url = "https://app.optionsplay.com"
self.token = None
self.token_expiry = None
def _get_token(self):
"""Acquire or refresh OAuth token"""
if self.token and self.token_expiry > datetime.now():
return self.token
response = requests.post(
f"{self.base_url}/token",
data={
"grant_type": "client_credentials",
"client_id": self.client_id,
"client_secret": self.client_secret
}
)
response.raise_for_status()
data = response.json()
self.token = data["access_token"]
self.token_expiry = datetime.now() + timedelta(seconds=data["expires_in"] - 60)
return self.token
def get_why(self, symbol):
"""Get trade ideas for a symbol"""
token = self._get_token()
response = requests.get(
f"{self.base_url}/api/v1/platform/why/{symbol}",
headers={"Authorization": f"Bearer {token}"}
)
response.raise_for_status()
return response.json()
# Usage
client = OptionsPlayClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
data = client.get_why("AAPL")
class OptionsPlayClient {
constructor(clientId, clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.baseUrl = 'https://app.optionsplay.com';
this.token = null;
this.tokenExpiry = null;
}
async getToken() {
// Return cached token if still valid
if (this.token && this.tokenExpiry > Date.now()) {
return this.token;
}
const response = await fetch(`${this.baseUrl}/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret
})
});
if (!response.ok) throw new Error('Token acquisition failed');
const data = await response.json();
this.token = data.access_token;
this.tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
return this.token;
}
async getWhy(symbol) {
const token = await this.getToken();
const response = await fetch(
`${this.baseUrl}/api/v1/platform/why/${symbol}`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
if (!response.ok) throw new Error('API request failed');
return response.json();
}
}
// Usage
const client = new OptionsPlayClient('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');
const data = await client.getWhy('AAPL');
public class OptionsPlayClient
{
private readonly string _clientId;
private readonly string _clientSecret;
private readonly string _baseUrl = "https://app.optionsplay.com";
private readonly HttpClient _httpClient;
private string _token;
private DateTime _tokenExpiry;
public OptionsPlayClient(string clientId, string clientSecret)
{
_clientId = clientId;
_clientSecret = clientSecret;
_httpClient = new HttpClient();
}
private async Task<string> GetTokenAsync()
{
if (_token != null && _tokenExpiry > DateTime.UtcNow)
return _token;
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", _clientId),
new KeyValuePair<string, string>("client_secret", _clientSecret)
});
var response = await _httpClient.PostAsync($"{_baseUrl}/token", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var tokenResponse = JsonSerializer.Deserialize<TokenResponse>(json);
_token = tokenResponse.AccessToken;
_tokenExpiry = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn - 60);
return _token;
}
public async Task<string> GetWhyAsync(string symbol)
{
var token = await GetTokenAsync();
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
var response = await _httpClient.GetAsync(
$"{_baseUrl}/api/v1/platform/why/{symbol}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
// Usage
var client = new OptionsPlayClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
var data = await client.GetWhyAsync("AAPL");
After (New Approach)
# Single step - no token needed!
curl -X GET "https://apis.optionsplay.com/api/v1/platform/why/AAPL" \
-H "Op-Subscription-Key: YOUR_API_KEY"
import requests
class OptionsPlayClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://apis.optionsplay.com"
def get_why(self, symbol):
"""Get trade ideas for a symbol"""
response = requests.get(
f"{self.base_url}/api/v1/platform/why/{symbol}",
headers={"Op-Subscription-Key": self.api_key}
)
response.raise_for_status()
return response.json()
# Usage - that's it!
client = OptionsPlayClient("YOUR_API_KEY")
data = client.get_why("AAPL")
class OptionsPlayClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://apis.optionsplay.com';
}
async getWhy(symbol) {
const response = await fetch(
`${this.baseUrl}/api/v1/platform/why/${symbol}`,
{ headers: { 'Op-Subscription-Key': this.apiKey } }
);
if (!response.ok) throw new Error('API request failed');
return response.json();
}
}
// Usage - that's it!
const client = new OptionsPlayClient('YOUR_API_KEY');
const data = await client.getWhy('AAPL');
public class OptionsPlayClient
{
private readonly string _apiKey;
private readonly string _baseUrl = "https://apis.optionsplay.com";
private readonly HttpClient _httpClient;
public OptionsPlayClient(string apiKey)
{
_apiKey = apiKey;
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Op-Subscription-Key", _apiKey);
}
public async Task<string> GetWhyAsync(string symbol)
{
var response = await _httpClient.GetAsync(
$"{_baseUrl}/api/v1/platform/why/{symbol}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
// Usage - that's it!
var client = new OptionsPlayClient("YOUR_API_KEY");
var data = await client.GetWhyAsync("AAPL");
Notice how the new approach eliminates ~50-70% of your authentication code. No token class, no expiry tracking, no refresh logic—just a simple header.
Developer Portal
With the new subscription key approach, you gain access to the OptionsPlay Developer Portal for self-service management and analytics.
OptionsPlay Developer Portal
View usage reports, manage your subscription, and explore API documentation.
developer.optionsplay.com →Portal Features
| Feature | Description |
|---|---|
| Usage Analytics | View request counts, response times, and error rates over time |
| API Explorer | Test API endpoints directly from your browser |
| Key Management | Regenerate your subscription key if needed |
| Documentation | Access detailed API reference and guides |
Frequently Asked Questions
app.optionsplay.com to apis.optionsplay.com)
and the authentication header.
Support
Need help with your integration? We're here to assist.
| Channel | Contact |
|---|---|
| Email Support | support@optionsplay.com |
| Developer Portal | developer.optionsplay.com |
| API Reference | Swagger Documentation |