Skip to main content

API Documentation

Everything you need to integrate StockAlert.pro into your applications

Examples

Real-world examples to help you get started quickly

Common Use Cases

Portfolio Monitoring

Create alerts for multiple stocks in your portfolio with different thresholds.

JavaScript
// Portfolio monitoring example
const portfolio = [
  { symbol: 'AAPL', buyPrice: 150, stopLoss: 0.1, takeProfit: 0.2 },
  { symbol: 'GOOGL', buyPrice: 2800, stopLoss: 0.1, takeProfit: 0.25 },
  { symbol: 'MSFT', buyPrice: 300, stopLoss: 0.08, takeProfit: 0.15 }
];

async function setupPortfolioAlerts(portfolio) {
  const alerts = [];
  
  for (const stock of portfolio) {
    // Stop loss alert
    const stopLossAlert = await createAlert({
      symbol: stock.symbol,
      condition: 'price_below',
      threshold: stock.buyPrice * (1 - stock.stopLoss),
      notification: 'sms' // Urgent alerts via SMS
    });
    
    // Take profit alert
    const takeProfitAlert = await createAlert({
      symbol: stock.symbol,
      condition: 'price_above',
      threshold: stock.buyPrice * (1 + stock.takeProfit),
      notification: 'email'
    });
    
    alerts.push({ 
      stock: stock.symbol, 
      stopLoss: stopLossAlert, 
      takeProfit: takeProfitAlert 
    });
  }
  
  return alerts;
}

// Usage
const portfolioAlerts = await setupPortfolioAlerts(portfolio);
console.log('Portfolio alerts created:', portfolioAlerts);
Python
# Portfolio monitoring example
portfolio = [
    {'symbol': 'AAPL', 'buy_price': 150, 'stop_loss': 0.1, 'take_profit': 0.2},
    {'symbol': 'GOOGL', 'buy_price': 2800, 'stop_loss': 0.1, 'take_profit': 0.25},
    {'symbol': 'MSFT', 'buy_price': 300, 'stop_loss': 0.08, 'take_profit': 0.15}
]

def setup_portfolio_alerts(portfolio):
    alerts = []
    
    for stock in portfolio:
        # Stop loss alert
        stop_loss_alert = client.alerts.create(
            symbol=stock['symbol'],
            condition='price_below',
            threshold=stock['buy_price'] * (1 - stock['stop_loss']),
            notification='sms'  # Urgent alerts via SMS
        )
        
        # Take profit alert
        take_profit_alert = client.alerts.create(
            symbol=stock['symbol'],
            condition='price_above',
            threshold=stock['buy_price'] * (1 + stock['take_profit']),
            notification='email'
        )
        
        alerts.append({
            'stock': stock['symbol'],
            'stop_loss': stop_loss_alert,
            'take_profit': take_profit_alert
        })
    
    return alerts

# Usage
portfolio_alerts = setup_portfolio_alerts(portfolio)
print(f'Portfolio alerts created: {len(portfolio_alerts) * 2} alerts')

Technical Analysis Alerts

Set up alerts based on technical indicators like moving averages and RSI.

// Technical indicator alerts
async function setupTechnicalAlerts(symbol) {
  const alerts = [];
  
  // Golden Cross alert (bullish signal)
  alerts.push(await createAlert({
    symbol: symbol,
    condition: 'ma_crossover_golden',
    notification: 'email'
  }));
  
  // Death Cross alert (bearish signal)
  alerts.push(await createAlert({
    symbol: symbol,
    condition: 'ma_crossover_death',
    notification: 'email'
  }));
  
  // RSI Oversold (< 30)
  alerts.push(await createAlert({
    symbol: symbol,
    condition: 'rsi_limit',
    threshold: 30,
    parameters: {
      direction: 'below',
      period: 14
    },
    notification: 'email'
  }));
  
  // RSI Overbought (> 70)
  alerts.push(await createAlert({
    symbol: symbol,
    condition: 'rsi_limit',
    threshold: 70,
    parameters: {
      direction: 'above',
      period: 14
    },
    notification: 'email'
  }));
  
  // Volume spike (50% above 10-day average)
  alerts.push(await createAlert({
    symbol: symbol,
    condition: 'volume_change',
    threshold: 150,
    parameters: {
      period: 10
    },
    notification: 'email'
  }));
  
  return alerts;
}

// Monitor multiple stocks
const techStocks = ['AAPL', 'GOOGL', 'MSFT', 'NVDA', 'TSLA'];
for (const stock of techStocks) {
  await setupTechnicalAlerts(stock);
}

Earnings & Dividend Tracking

Track important corporate events and fundamental changes.

// Track earnings and dividends
async function setupFundamentalAlerts(symbol, options = {}) {
  const alerts = [];
  
  // Earnings announcement reminder
  if (options.trackEarnings) {
    alerts.push(await createAlert({
      symbol: symbol,
      condition: 'earnings_announcement',
      parameters: {
        days_before: 1 // Alert 1 day before earnings
      },
      notification: 'email'
    }));
  }
  
  // Dividend tracking
  if (options.trackDividends) {
    // Ex-dividend date alert
    alerts.push(await createAlert({
      symbol: symbol,
      condition: 'dividend_ex_date',
      parameters: {
        days_before: 2 // Alert 2 days before ex-dividend
      },
      notification: 'email'
    }));
    
    // Payment date alert
    alerts.push(await createAlert({
      symbol: symbol,
      condition: 'dividend_payment',
      parameters: {
        shares_owned: options.shares || 100
      },
      notification: 'email'
    }));
  }
  
  // P/E ratio monitoring
  if (options.targetPE) {
    alerts.push(await createAlert({
      symbol: symbol,
      condition: 'pe_ratio_below',
      threshold: options.targetPE,
      notification: 'email'
    }));
  }
  
  return alerts;
}

// Example usage
const fundamentalAlerts = await setupFundamentalAlerts('AAPL', {
  trackEarnings: true,
  trackDividends: true,
  shares: 100,
  targetPE: 25
});

Webhook Integration Examples

Discord Bot Integration

Send alert notifications to a Discord channel using webhooks.

// Express.js webhook endpoint for Discord integration
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');

const app = express();
app.use(express.raw({ type: 'application/json' }));

const WEBHOOK_SECRET = process.env.STOCKALERT_WEBHOOK_SECRET;
const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;

// Verify webhook signature
function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return signature === 'sha256=' + expected;
}

// Format alert for Discord
function formatDiscordMessage(alert) {
  const color = alert.condition.includes('above') ? 0x00ff00 : 0xff0000;
  
  return {
    embeds: [{
      title: `🚨 ${alert.company_name} (${alert.symbol})`,
      description: `Alert triggered: ${alert.condition}`,
      color: color,
      fields: [
        {
          name: 'Target Value',
          value: `$${alert.threshold}`,
          inline: true
        },
        {
          name: 'Current Price',
          value: `$${alert.triggered_value}`,
          inline: true
        },
        {
          name: 'Change',
          value: `${((alert.triggered_value - alert.threshold) / alert.threshold * 100).toFixed(2)}%`,
          inline: true
        }
      ],
      timestamp: new Date().toISOString()
    }]
  };
}

app.post('/webhook/stockalert', async (req, res) => {
  const signature = req.headers['x-stockalert-signature'];
  const event = req.headers['x-stockalert-event'];
  
  // Verify signature
  if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const data = JSON.parse(req.body);
  
  // Handle different event types
  switch (event) {
    case 'alert.triggered':
      try {
        // Send to Discord
        await axios.post(DISCORD_WEBHOOK_URL, 
          formatDiscordMessage(data.data.alert)
        );
        console.log('Alert sent to Discord');
      } catch (error) {
        console.error('Discord webhook error:', error);
      }
      break;
      
    // Handle other events...
  }
  
  res.status(200).send('OK');
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Database Logging

Log all alert events to a database for analysis and backtesting.

// PostgreSQL integration example
const { Pool } = require('pg');
const pool = new Pool({
  connectionString: process.env.DATABASE_URL
});

// Create alerts table
async function setupDatabase() {
  await pool.query(`
    CREATE TABLE IF NOT EXISTS alert_events (
      id SERIAL PRIMARY KEY,
      event_id VARCHAR(50) UNIQUE,
      event_type VARCHAR(50),
      alert_id UUID,
      stock_symbol VARCHAR(10),
      alert_type VARCHAR(50),
      target_value DECIMAL(10, 2),
      triggered_value DECIMAL(10, 2),
      triggered_at TIMESTAMP,
      raw_data JSONB,
      created_at TIMESTAMP DEFAULT NOW()
    )
  `);
}

// Webhook handler with database logging
app.post('/webhook/stockalert', async (req, res) => {
  const signature = req.headers['x-stockalert-signature'];
  const event = req.headers['x-stockalert-event'];
  
  if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const data = JSON.parse(req.body);
  
  try {
    // Log to database
    await pool.query(`
      INSERT INTO alert_events (
        event_id, event_type, alert_id, stock_symbol,
        alert_type, target_value, triggered_value,
        triggered_at, raw_data
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
      ON CONFLICT (event_id) DO NOTHING
    `, [
      data.id,
      event,
      data.data.alert.id,
      data.data.alert.symbol,
      data.data.alert.condition,
      data.data.alert.threshold,
      data.data.alert.triggered_value,
      data.data.alert.triggered_at,
      data
    ]);
    
    // Process based on event type
    if (event === 'alert.triggered') {
      await processTriggeredAlert(data.data.alert);
    }
    
  } catch (error) {
    console.error('Database error:', error);
    return res.status(500).send('Internal error');
  }
  
  res.status(200).send('OK');
});

Advanced Patterns

Batch Alert Management

Efficiently manage large numbers of alerts with batch operations.

// Batch alert manager
class AlertBatchManager {
  constructor(apiKey, options = {}) {
    this.apiKey = apiKey;
    this.batchSize = options.batchSize || 10;
    this.concurrency = options.concurrency || 3;
    this.retryAttempts = options.retryAttempts || 3;
  }
  
  // Create multiple alerts with rate limiting
  async createBatch(alerts) {
    const results = [];
    const errors = [];
    
    // Process in batches
    for (let i = 0; i < alerts.length; i += this.batchSize) {
      const batch = alerts.slice(i, i + this.batchSize);
      
      // Process batch with concurrency limit
      const batchResults = await Promise.allSettled(
        batch.map(alert => this.createWithRetry(alert))
      );
      
      // Collect results
      batchResults.forEach((result, index) => {
        if (result.status === 'fulfilled') {
          results.push(result.value);
        } else {
          errors.push({
            alert: batch[index],
            error: result.reason
          });
        }
      });
      
      // Rate limit between batches
      if (i + this.batchSize < alerts.length) {
        await this.sleep(1000); // 1 second between batches
      }
    }
    
    return { results, errors };
  }
  
  async createWithRetry(alert, attempt = 1) {
    try {
      const response = await fetch('https://stockalert.pro/api/public/v1/alerts', {
        method: 'POST',
        headers: {
          'X-API-Key': this.apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(alert)
      });
      
      if (response.status === 429 && attempt < this.retryAttempts) {
        const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
        await this.sleep(retryAfter * 1000);
        return this.createWithRetry(alert, attempt + 1);
      }
      
      if (!response.ok) {
        throw new Error(`Failed to create alert: ${response.statusText}`);
      }
      
      return await response.json();
    } catch (error) {
      if (attempt < this.retryAttempts) {
        await this.sleep(Math.pow(2, attempt) * 1000); // Exponential backoff
        return this.createWithRetry(alert, attempt + 1);
      }
      throw error;
    }
  }
  
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage
const batchManager = new AlertBatchManager('sk_your_api_key');

// Create 100 alerts efficiently
const alerts = generateAlerts(100); // Your alert generation logic
const { results, errors } = await batchManager.createBatch(alerts);

console.log(`Created ${results.length} alerts successfully`);
console.log(`Failed to create ${errors.length} alerts`);

Alert Synchronization

Keep alerts synchronized between your application and StockAlert.pro.

// Alert synchronization service
class AlertSyncService {
  constructor(apiClient, localDb) {
    this.api = apiClient;
    this.db = localDb;
  }
  
  async syncAlerts() {
    console.log('Starting alert synchronization...');
    
    // Fetch all remote alerts
    const remoteAlerts = await this.fetchAllAlerts();
    const localAlerts = await this.db.getAllAlerts();
    
    // Create maps for efficient lookup
    const remoteMap = new Map(remoteAlerts.map(a => [a.id, a]));
    const localMap = new Map(localAlerts.map(a => [a.remote_id, a]));
    
    const operations = {
      create: [],
      update: [],
      delete: []
    };
    
    // Find alerts to create locally
    for (const [id, remote] of remoteMap) {
      if (!localMap.has(id)) {
        operations.create.push(remote);
      } else {
        const local = localMap.get(id);
        if (this.needsUpdate(local, remote)) {
          operations.update.push({ local, remote });
        }
      }
    }
    
    // Find alerts to delete locally
    for (const [remoteId, local] of localMap) {
      if (!remoteMap.has(remoteId)) {
        operations.delete.push(local);
      }
    }
    
    // Execute operations
    await this.executeSync(operations);
    
    console.log('Synchronization complete:', {
      created: operations.create.length,
      updated: operations.update.length,
      deleted: operations.delete.length
    });
  }
  
  async fetchAllAlerts() {
    const alerts = [];
    let page = 1;
    let hasMore = true;
    
    while (hasMore) {
      const response = await this.api.alerts.list({ 
        page, 
        limit: 100 
      });
      
      alerts.push(...response.data);
      hasMore = response.totalPages > page;
      page++;
    }
    
    return alerts;
  }
  
  needsUpdate(local, remote) {
    return local.is_active !== remote.is_active ||
           local.threshold !== remote.threshold ||
           local.updated_at < remote.updated_at;
  }
  
  async executeSync(operations) {
    // Create new alerts
    for (const alert of operations.create) {
      await this.db.createAlert({
        remote_id: alert.id,
        ...alert
      });
    }
    
    // Update existing alerts
    for (const { local, remote } of operations.update) {
      await this.db.updateAlert(local.id, {
        is_active: remote.is_active,
        threshold: remote.threshold,
        updated_at: remote.updated_at
      });
    }
    
    // Delete removed alerts
    for (const alert of operations.delete) {
      await this.db.deleteAlert(alert.id);
    }
  }
}

// Run sync periodically
const syncService = new AlertSyncService(apiClient, database);
setInterval(() => syncService.syncAlerts(), 5 * 60 * 1000); // Every 5 minutes

Official Integrations

Slack App

Get real-time alerts in your Slack workspace with our official app.

View on GitHub →

n8n Integration

No-code automation with our official n8n node.

View on NPM →