Skip to main content
POST
https://api.fintool.com
/
v1
/
webhooks
Webhooks
curl --request POST \
  --url https://api.fintool.com/v1/webhooks \
  --header 'Content-Type: application/json' \
  --data '
{
  "url": "<string>",
  "events": [
    {}
  ],
  "filters": {
    "tickers": [
      {}
    ],
    "doc_types": [
      {}
    ]
  },
  "secret": "<string>"
}
'
{
  "id": "<string>",
  "url": "<string>",
  "events": [
    {}
  ],
  "filters": {},
  "secret": "<string>",
  "status": "<string>",
  "created_at": "<string>"
}

Overview

Subscribe to real-time notifications when new SEC filings, earnings calls, or other financial events are published. Webhooks push data to your server immediately when events occur.

POST /v1/webhooks

Create a new webhook subscription.

Request Body

url
string
required
HTTPS callback URL where events will be delivered
events
array
required
Array of event types to subscribe to
filters
object
Filter criteria for events
secret
string
Signing secret for payload verification. Auto-generated if not provided.

Request Example

curl -X POST "https://api.fintool.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/fintool",
    "events": ["filing.new", "earnings_call.new"],
    "filters": {
      "tickers": ["AAPL", "MSFT", "GOOGL", "AMZN", "NVDA"],
      "doc_types": ["8-K", "10-K", "10-Q"]
    }
  }'

Response

id
string
Unique webhook identifier (e.g., wh_abc123xyz)
url
string
Callback URL
events
array
Subscribed event types
filters
object
Applied filter criteria
secret
string
Signing secret for payload verification. Store this securely.
status
string
Webhook status: active, paused, or failed
created_at
string
Creation timestamp (ISO 8601)

Response Example

{
  "id": "wh_abc123xyz",
  "url": "https://your-app.com/webhooks/fintool",
  "events": ["filing.new", "earnings_call.new"],
  "filters": {
    "tickers": ["AAPL", "MSFT", "GOOGL", "AMZN", "NVDA"],
    "doc_types": ["8-K", "10-K", "10-Q"]
  },
  "secret": "whsec_a1b2c3d4e5f6...",
  "status": "active",
  "created_at": "2025-01-15T10:30:00Z"
}

GET /v1/webhooks

List all webhook subscriptions.

Request Example

cURL
curl -X GET "https://api.fintool.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Example

{
  "webhooks": [
    {
      "id": "wh_abc123xyz",
      "url": "https://your-app.com/webhooks/fintool",
      "events": ["filing.new", "earnings_call.new"],
      "filters": {
        "tickers": ["AAPL", "MSFT", "GOOGL", "AMZN", "NVDA"],
        "doc_types": ["8-K", "10-K", "10-Q"]
      },
      "status": "active",
      "created_at": "2025-01-15T10:30:00Z",
      "last_triggered_at": "2025-01-15T14:22:00Z"
    }
  ]
}

DELETE /v1/webhooks/

Delete a webhook subscription.

Path Parameters

webhook_id
string
required
Webhook identifier (e.g., wh_abc123xyz)

Request Example

cURL
curl -X DELETE "https://api.fintool.com/v1/webhooks/wh_abc123xyz" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

Returns 204 No Content on success.

Webhook Payload

When an event matches your subscription, we POST to your callback URL.

Headers

HeaderDescription
Content-Typeapplication/json
X-Fintool-SignatureHMAC-SHA256 signature (e.g., sha256=abc123...)
X-Fintool-EventEvent type (e.g., filing.new)
X-Fintool-Delivery-IdUnique delivery identifier

Payload Structure

{
  "event": "filing.new",
  "timestamp": "2025-01-15T14:22:00Z",
  "data": {
    "publication_id": "0000320193-25-000042",
    "ticker": "AAPL",
    "company_name": "Apple Inc.",
    "doc_type": "8-K",
    "title": "Current Report",
    "filing_date": "2025-01-15",
    "items": ["Item 2.02", "Item 9.01"],
    "url": "https://api.fintool.com/v1/documents/0000320193-25-000042",
    "sec_url": "https://www.sec.gov/Archives/edgar/data/320193/000032019325000042"
  }
}

Event Types

EventDescription
filing.newNew SEC filing published
filing.8k_material8-K with material items (1.01, 1.02, 2.01, 4.01, 5.01)
earnings_call.newNew earnings call transcript available
earnings_call.upcomingEarnings call scheduled (24h notice)
press_release.newNew press release

Material 8-K Items

The filing.8k_material event triggers only for 8-Ks containing significant disclosures:
  • Item 1.01 - Entry into a Material Definitive Agreement
  • Item 1.02 - Termination of a Material Definitive Agreement
  • Item 2.01 - Completion of Acquisition or Disposition of Assets
  • Item 4.01 - Changes in Registrant’s Certifying Accountant
  • Item 5.01 - Changes in Control of Registrant

Signature Verification

Verify webhook authenticity by validating the X-Fintool-Signature header using your webhook secret.

Python

import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)

WEBHOOK_SECRET = "whsec_your_secret_here"

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    """Verify the webhook signature"""
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

@app.post("/webhooks/fintool")
def handle_webhook():
    signature = request.headers.get("X-Fintool-Signature")

    if not verify_webhook(request.data, signature, WEBHOOK_SECRET):
        return {"error": "Invalid signature"}, 401

    event = request.json

    if event["event"] == "filing.new":
        process_new_filing(event["data"])
    elif event["event"] == "earnings_call.new":
        process_earnings_call(event["data"])

    return {"received": True}, 200

def process_new_filing(data):
    print(f"New filing: {data['ticker']} - {data['doc_type']}")
    # Your processing logic here

def process_earnings_call(data):
    print(f"New earnings call: {data['ticker']}")
    # Your processing logic here

Node.js

const crypto = require('crypto');
const express = require('express');

const app = express();
const WEBHOOK_SECRET = 'whsec_your_secret_here';

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(`sha256=${expected}`),
    Buffer.from(signature)
  );
}

app.post('/webhooks/fintool', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-fintool-signature'];

  if (!verifyWebhook(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(req.body);

  switch (event.event) {
    case 'filing.new':
      console.log(`New filing: ${event.data.ticker} - ${event.data.doc_type}`);
      break;
    case 'earnings_call.new':
      console.log(`New earnings call: ${event.data.ticker}`);
      break;
  }

  res.json({ received: true });
});

Best Practices

Never process webhook payloads without verifying the X-Fintool-Signature header. This prevents malicious actors from sending fake events to your endpoint.
Return a 2xx response within 30 seconds. Process events asynchronously if needed. Webhooks that consistently timeout will be disabled.
Use the X-Fintool-Delivery-Id header to deduplicate events. In rare cases, the same event may be delivered multiple times.
Webhook URLs must use HTTPS. HTTP endpoints will be rejected.

Retry Policy

Failed deliveries are retried with exponential backoff:
AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
68 hours
After 6 failed attempts, the webhook is marked as failed and no further deliveries are attempted until you manually reactivate it.

Use Cases

Real-time Alerts

Notify your team instantly when companies in your portfolio file 8-Ks

Data Pipeline Triggers

Automatically ingest new filings into your data warehouse

Trading Signals

React to material disclosures with automated trading strategies

Research Automation

Trigger AI analysis when new earnings calls are available

Next Steps