API Authentication

Developer Resource: This guide covers authentication setup for the Profitelligence API. Choose the method that fits your use case.

Authentication Methods

The API supports two authentication methods:

MethodUse CaseBest For
Firebase JWTUser-authenticated requestsWeb/mobile apps where users log in
API KeyServer-to-server requestsBackend services, scripts, automation

Both methods provide the same data access. Your subscription tier (Free, Pro, Elite) determines which symbols and features you can access.

Method 1: Firebase JWT

Use Firebase Authentication when building applications where end users log in with their Profitelligence accounts.

How It Works

  1. User logs in via Firebase Auth (email/password, Google, etc.)
  2. Firebase returns a JWT token
  3. Include the token in API requests
  4. API validates the token and applies user's subscription tier

Setup

1. Initialize Firebase in your app:

    
    import { initializeApp } from 'firebase/app';
import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';

const firebaseConfig = {
  apiKey: "YOUR_FIREBASE_API_KEY",
  authDomain: "profitelligence.firebaseapp.com",
  projectId: "profitelligence"
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

  

2. Authenticate the user:

    
    const userCredential = await signInWithEmailAndPassword(
  auth,
  email,
  password
);

  

3. Get the JWT token:

    
    const token = await userCredential.user.getIdToken();

  

4. Include in API requests:

    
    const response = await fetch(
  'https://apollo.profitelligence.com/v1/company-profile?symbol=AAPL',
  {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  }
);

  

Token Refresh

Firebase tokens expire after 1 hour. The Firebase SDK handles automatic refresh, but you should:

    
    // Always get a fresh token before API calls
const token = await auth.currentUser.getIdToken(/* forceRefresh */ false);

  

The SDK returns a cached token if valid, or refreshes automatically if expired.

Python Example

    
    import firebase_admin
from firebase_admin import credentials, auth
import requests

# Initialize Firebase Admin SDK
cred = credentials.Certificate('path/to/serviceAccount.json')
firebase_admin.initialize_app(cred)

# For server-side token verification (if you're validating tokens):
# decoded_token = auth.verify_id_token(id_token)

# For making API calls with a user's token:
def fetch_company_profile(jwt_token: str, symbol: str):
    response = requests.get(
        f"https://apollo.profitelligence.com/v1/company-profile",
        params={"symbol": symbol},
        headers={"Authorization": f"Bearer {jwt_token}"}
    )
    return response.text  # CSV data

  

Method 2: API Key

Use API keys for backend services, scripts, and automated systems that don't involve user login.

How It Works

  1. Request an API key from your account settings
  2. Include the key in a custom header
  3. API validates the key and applies your account's subscription tier

Setup

1. Obtain your API key:

Contact support or visit your account settings to generate an API key. Keys are tied to your account and inherit your subscription tier.

2. Include in requests:

    
    curl -H "X-API-Key: YOUR_API_KEY" \
  "https://apollo.profitelligence.com/v1/company-profile?symbol=AAPL"

  

JavaScript Example

    
    const API_KEY = process.env.PROFITELLIGENCE_API_KEY;

async function getCompanyProfile(symbol) {
  const response = await fetch(
    `https://apollo.profitelligence.com/v1/company-profile?symbol=${symbol}`,
    {
      headers: {
        'X-API-Key': API_KEY
      }
    }
  );
  return response.text();
}

  

Python Example

    
    import os
import requests

API_KEY = os.environ.get('PROFITELLIGENCE_API_KEY')

def get_company_profile(symbol: str) -> str:
    response = requests.get(
        "https://apollo.profitelligence.com/v1/company-profile",
        params={"symbol": symbol},
        headers={"X-API-Key": API_KEY}
    )
    response.raise_for_status()
    return response.text

  

Security Best Practices

Never expose API keys in:

  • Client-side JavaScript
  • Public repositories
  • Browser network requests

Do:

  • Store keys in environment variables
  • Use keys only in backend/server code
  • Rotate keys periodically
  • Use separate keys for development and production

Rate Limits

Both authentication methods are subject to rate limits based on subscription tier:

TierDaily LimitHourly Limit
Free10 requests2 requests
Pro100 requests25 requests
Elite1,000 requests100 requests

Rate Limit Headers

Every response includes rate limit information:

    
    X-RateLimit-Limit: 100        # Your daily limit
X-RateLimit-Remaining: 87     # Requests remaining today
X-RateLimit-Reset: 1705449600 # Unix timestamp when limit resets

  

Handling Rate Limits

When you exceed your limit, the API returns 429 Too Many Requests:

    
    {
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "details": "Daily limit of 100 requests exceeded. Resets at 2024-01-17T00:00:00Z"
}

  

Implement exponential backoff:

    
    import time
import requests

def api_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)

        if response.status_code == 429:
            wait_time = 2 ** attempt  # 1, 2, 4 seconds
            time.sleep(wait_time)
            continue

        return response

    raise Exception("Max retries exceeded")

  

Optimizing API Usage

1. Use page aggregation endpoints:

Instead of multiple calls:

    
    GET /company-profile?symbol=AAPL
GET /ohlc?symbol=AAPL
GET /technical-signals?symbol=AAPL

  

Use one call:

    
    GET /company-info-page?symbol=AAPL

  

2. Cache responses:

Company profiles and historical data don't change frequently. Cache for 5-15 minutes.

3. Batch your requests:

If checking multiple symbols, spread requests over time rather than bursting.

Symbol Access Tiers

Your subscription tier determines which symbols you can query:

TierSymbols Available
FreeTop 500 by average daily volume
ProTop 6,000 by average daily volume
EliteAll symbols (unlimited)

Requesting a symbol outside your tier returns 403 Forbidden:

    
    {
  "error": "Symbol access denied",
  "code": "SYMBOL_TIER_RESTRICTED",
  "details": "SMALLCAP is not available on the Free tier. Upgrade to Pro for access.",
  "upgrade_url": "https://profitelligence.com/subscribe"
}

  

Error Responses

Authentication Errors

401 Unauthorized — Missing or invalid credentials:

    
    {
  "error": "Authentication required",
  "code": "AUTH_REQUIRED",
  "details": "Include Authorization header with Bearer token or X-API-Key header"
}

  

401 Unauthorized — Expired JWT:

    
    {
  "error": "Token expired",
  "code": "TOKEN_EXPIRED",
  "details": "Firebase token has expired. Please refresh and retry."
}

  

401 Unauthorized — Invalid API key:

    
    {
  "error": "Invalid API key",
  "code": "INVALID_API_KEY",
  "details": "The provided API key is not valid or has been revoked"
}

  

Authorization Errors

403 Forbidden — Feature not available on tier:

    
    {
  "error": "Feature access denied",
  "code": "FEATURE_TIER_RESTRICTED",
  "details": "Advanced analytics requires Pro subscription",
  "upgrade_url": "https://profitelligence.com/subscribe"
}

  

Testing Authentication

Verify JWT Setup

    
    # Replace with your actual JWT token
curl -i -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  "https://apollo.profitelligence.com/v1/user-status"

  

Successful response includes your user info and tier:

    
    {
  "user_id": "abc123",
  "email": "user@example.com",
  "subscription_tier": "pro",
  "feature_version": "main",
  "available_features": ["form4_light", "form4_medium", "analytics"]
}

  

Verify API Key Setup

    
    curl -i -H "X-API-Key: YOUR_API_KEY" \
  "https://apollo.profitelligence.com/v1/company-profile?symbol=AAPL"

  

A successful response returns company data. Check the X-RateLimit-* headers to confirm your tier limits.

Common Issues

"Token expired" errors

Firebase tokens last 1 hour. Always call getIdToken() before API requests—the SDK handles refresh automatically.

"Invalid API key" errors

  • Verify the key is copied correctly (no extra spaces)
  • Check the key hasn't been revoked
  • Ensure you're using the correct header name (X-API-Key)

Rate limit exceeded unexpectedly

  • Check if you have multiple services using the same key
  • Review your code for unnecessary duplicate requests
  • Consider upgrading your tier for higher limits

Next Steps

With authentication configured, explore the available endpoints: