Skip to main content
Every request to the StratAlerts Partner API must include an API key. Keys are scoped — each key grants access only to the specific endpoints and channels listed in its scope set. You manage keys from your account settings after subscribing to the API Access plan.

Getting an API key

1

Subscribe to API Access

API access is a separate subscription from your standard StratAlerts plan. Visit the API Access subscription page and complete checkout.
2

Generate a key

After subscribing, go to your account settings and generate a new API key. Give it a descriptive label so you can identify it later.
3

Copy the raw key immediately

The full key value is only shown once at creation time. Copy it to a secure location before closing the dialog — you cannot retrieve the raw key afterward, only revoke and regenerate it.

Passing your key

You can pass your API key in either of two request headers. Both are accepted on every REST endpoint and on the WebSocket handshake.
Use the standard HTTP Authorization header with the Bearer scheme:
Authorization: Bearer YOUR_API_KEY

Code examples

curl -s \
  -H "Authorization: Bearer YOUR_API_KEY" \
  https://app.stratalerts.com/api/market/v1/market-status

Key scopes

When you generate a key, you choose which scopes to grant. A request to an endpoint whose scope is not on the key returns a 403 missing_scope error. The table below lists all available scopes.
ScopeGrants access to
metadata:readGET /instruments, GET /instruments/{symbol}, GET /market-status
prices:readGET /prices/latest, WebSocket quotes channel
candles:readGET /candles/{symbol}
states:readGET /states/{symbol}, GET /setups/current, WebSocket states channel
alerts:readGET /alerts/in-force, GET /alerts/simultaneous-breaks, WebSocket alerts.in_force and alerts.simultaneous_breaks channels
ws:connectEstablish a WebSocket connection (required in addition to channel-specific scopes)
Grant only the scopes your integration actually uses. A key scoped to metadata:read and prices:read cannot accidentally be used to pull alert data if it is ever leaked.

Error responses

Authentication failures return a JSON error envelope. The HTTP status code and code field tell you exactly what went wrong.
HTTP statusError codeMeaning
401missing_api_keyNo key was found in the request headers — either the header is absent or the value is empty
403inactive_entitlementYour API Access subscription has lapsed or been cancelled
403missing_scopeThe key is valid but does not have the scope required by this endpoint
A 401 response looks like this:
{
  "error": {
    "code": "missing_api_key",
    "message": "missing api key"
  }
}
A 403 scope error looks like this:
{
  "error": {
    "code": "missing_scope",
    "message": "missing scope"
  }
}

Security best practices

Never embed your API key in client-side code, browser JavaScript, or a public repository. If a key is exposed, revoke it immediately from your account settings and generate a new one.
  • Store your key in an environment variable or secrets manager, not in source code.
  • Use a separate key per integration so you can revoke one without affecting others.
  • Grant only the scopes each key requires — avoid creating full-access keys for read-only integrations.
  • Rotate keys on a regular schedule or immediately if you suspect exposure.

WebSocket authentication

The WebSocket connection handshake also requires your API key. Pass it in the same headers (Authorization: Bearer or X-API-Key) during the initial HTTP upgrade request. Your key must include both ws:connect and the scope for every channel you plan to subscribe to. If authentication fails during the WebSocket handshake, the connection is closed with one of these close codes before any messages are exchanged:
Close codeMeaning
4401No valid API key found in the handshake headers
4403Active subscription not found, or key lacks ws:connect scope
import asyncio
import json
import websockets

API_KEY = "YOUR_API_KEY"
WS_URL = "wss://app.stratalerts.com/ws/market/v1"

async def stream_quotes():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    async with websockets.connect(WS_URL, additional_headers=headers) as ws:
        await ws.send(json.dumps({
            "op": "subscribe",
            "topics": [{"channel": "quotes", "symbols": ["AAPL", "TSLA"]}],
        }))
        async for message in ws:
            print(json.loads(message))

asyncio.run(stream_quotes())