DEV Community

Cover image for A guide to Company Filings: CIK-based Analysis with FinFeedAPI
Maciej Józefowicz for FinFeedAPI

Posted on

A guide to Company Filings: CIK-based Analysis with FinFeedAPI

When you're building a financial app, your users don't want to dig through mountains of data—they want info on the specific companies they're tracking. Using a company's CIK is the most direct way to deliver that.

Filtering by CIK lets your app:

  • Create company-specific views: Pull together all the 10-Ks, 8-Ks, and other filings for a single stock.
  • Send targeted alerts: Let users know the moment a company they follow files something important.
  • Enable competitor analysis: Grab data for a handful of companies in the same industry so your users can compare them.

This guide will walk you through how to do it with the FinFeedAPI.

A Guide to Company Filings: CIK-Based Analysis

When examining public companies, it is a frequent need to concentrate on a single entity. Instead of searching through all market-wide filings, you can separate the documents of one specific company. This method uses the Central Index Key (CIK), a unique number the SEC assigns to each registrant.

This guide will show you how to use a company's CIK with the FinFeedAPI to build a detailed overview of its filing activity.

This guide covers:

  • Retrieving a company's filings using its CIK.
  • Plotting a timeline of major reports (10-K, 10-Q, 8-K).
  • Examining the frequency of different form types.
  • Getting the content of specific sections, like "Risk Factors," from a filing.

What you need:

  • Python 3.x and experience with pandas and matplotlib.
  • The api-bricks-sec-api-rest Python library.
  • Your personal FinFeedAPI key.

1. Environment Setup

The first action is to install the FinFeedAPI client library if it is not already on your system.

pip install api-bricks-sec-api-rest
Enter fullscreen mode Exit fullscreen mode

Then, import the necessary libraries and configure your API client. This example uses Apple Inc., which has a CIK of 320193.

# Import necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
import api_bricks_sec_api_rest

# --- API Configuration ---
# IMPORTANT: Replace "YOUR_API_KEY_HERE" with your actual FinFeedAPI key.
API_KEY = "YOUR_API_KEY_HERE"
api_client_config = api_bricks_sec_api_rest.Configuration()
api_client_config.api_key['Authorization'] = API_KEY
api_client = api_bricks_sec_api_rest.ApiClient(configuration=api_client_config)

# --- Target Company ---
# Example CIKs: Apple (320193), Microsoft (789019), Google (1652044)
TARGET_CIK = 320193 

# --- Plotting Configuration ---
plt.style.use('seaborn-v0_8-darkgrid')
plt.rcParams['figure.figsize'] = (15, 7)


Enter fullscreen mode Exit fullscreen mode

This cell sets up the environment. It defines the CIK for the target company (Apple) and initializes the API client with a key.

2. Retrieving All Filings for a CIK

To get a full history, you must query the /v1/filings endpoint and manage paged results. The API returns information in pages, with up to 200 records per page. The code below will request each page until all filings for the target company over the last five years are retrieved.

# Define time range and initialize API instances
end_date = datetime.now().strftime('%Y-%m-%d')
start_date = (datetime.now() - pd.DateOffset(years=5)).strftime('%Y-%m-%d')
filing_metadata_api = api_bricks_sec_api_rest.FilingMetadataApi(api_client)

print(f"Fetching all filings for CIK {TARGET_CIK} from {start_date} to {end_date}...")

company_filings = []
current_page = 1
page_size = 200 # Max page size

while True:
    try:
        page_data = filing_metadata_api.v1_filings_get(
            cik=TARGET_CIK,
            filling_date_start=start_date,
            filling_date_end=end_date,
            page_size=page_size,
            page_number=current_page
        )

        if page_data:
            company_filings.extend(page_data)
            print(f"  Fetched page {current_page}, {len(page_data)} records. Total: {len(company_filings)}")
            if len(page_data) < page_size:
                print("  Last page reached.")
                break
            current_page += 1
        else:
            print(f"  No more data found on page {current_page}.")
            break

    except api_bricks_sec_api_rest.ApiException as e:
        print(f"API Exception occurred: {e}")
        break

# Process the results into a DataFrame
if company_filings:
    company_filings_df = pd.DataFrame.from_records([vars(f) for f in company_filings])
    company_filings_df['filing_date'] = pd.to_datetime(company_filings_df['filing_date'], errors='coerce')
    print(f"\nSuccessfully fetched {len(company_filings_df)} total filings for CIK {TARGET_CIK}.")
    print("\nSample of fetched data:")
    print(company_filings_df[['filing_date', 'form', 'accession_number', 'primary_doc_description']].head())
else:
    print(f"\nNo filings found for CIK {TARGET_CIK} in the specified date range.")
    company_filings_df = pd.DataFrame() # Create empty DataFrame to avoid errors


Enter fullscreen mode Exit fullscreen mode

The code here calls the API in a loop, incrementing the page_number with each call, until all filings for the specified CIK and date range are obtained. The results are then loaded into a pandas DataFrame.

3. Plotting the Filing Timeline

A timeline plot displays when a company makes its important reports. You can create a scatter plot that shows the filing dates for major form types like 10-K (annual), 10-Q (quarterly), and 8-K (current events).

if not company_filings_df.empty:
    # Filter for major form types
    major_forms = ['10-K', '10-Q', '8-K']
    timeline_df = company_filings_df[company_filings_df['form'].isin(major_forms)].copy()
    timeline_df = timeline_df.dropna(subset=['filing_date'])

    if not timeline_df.empty:
        # Create the plot
        fig, ax = plt.subplots(figsize=(18, 8))
        colors = {'10-K': 'red', '10-Q': 'blue', '8-K': 'green'}
        markers = {'10-K': 'o', '10-Q': 's', '8-K': '^'}

        for form_type in major_forms:
            subset = timeline_df[timeline_df['form'] == form_type]
            if not subset.empty:
                ax.scatter(subset['filing_date'], subset['form'],
                           label=form_type,
                           color=colors[form_type],
                           marker=markers[form_type],
                           s=80, alpha=0.7)

        # Formatting the plot
        ax.set_title(f'Filing Timeline for CIK {TARGET_CIK}')
        ax.set_xlabel('Filing Date')
        ax.set_ylabel('Form Type')
        ax.legend(title="Form Types")
        ax.grid(True, axis='x', linestyle='--', alpha=0.6)

        # Improve date formatting on x-axis
        ax.xaxis.set_major_locator(mdates.YearLocator())
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
        plt.setp(ax.xaxis.get_majorticklabels(), rotation=45, ha='right')

        plt.tight_layout()
        plt.show()
    else:
        print("No 10-K, 10-Q, or 8-K filings found for timeline visualization.")

Enter fullscreen mode Exit fullscreen mode

This code filters the DataFrame for the three major form types and then uses matplotlib to create a scatter plot. Each point on the plot represents a single filing, showing its type and date of submission.

This scatter plot, titled

4. Examining Form Type Frequency

You can see which forms the company files most often. A bar chart can show this distribution.

if not company_filings_df.empty:
    form_counts = company_filings_df['form'].value_counts()

    # Plot the top N form types
    top_n = 15
    plt.figure(figsize=(12, 6))
    form_counts.head(top_n).plot(kind='bar', color='teal', edgecolor='black')
    plt.title(f'Top {top_n} Most Frequent Form Types for CIK {TARGET_CIK}')
    plt.xlabel('Form Type')
    plt.ylabel('Number of Filings')
    plt.xticks(rotation=45, ha='right')
    plt.grid(True, axis='y', linestyle='--', alpha=0.7)
    plt.tight_layout()
    plt.show()

Enter fullscreen mode Exit fullscreen mode

The value_counts() method in pandas is used to count the occurrences of each form type. The code then plots the top 15 most frequent forms.

This bar chart, titled

5. Getting Specific Content from a Filing

This section demonstrates getting the content of the "Risk Factors" section (Item 1A) from the company's most recent 10-K filing. This shows how to get the actual content using metadata like the accession_number.

if not company_filings_df.empty:
    # Find the most recent 10-K filing
    latest_10k_list = company_filings_df[company_filings_df['form'] == '10-K'].sort_values('filing_date', ascending=False)

    if not latest_10k_list.empty:
        latest_10k_accession_number = latest_10k_list.iloc[0]['accession_number']
        print(f"\nAttempting to extract 'Item 1A' (Risk Factors) from latest 10-K: {latest_10k_accession_number}")

        content_extraction_api = api_bricks_sec_api_rest.ContentExtractionApi(api_client)
        try:
            risk_factors_content = content_extraction_api.v1_extractor_item_get(
                accession_number=latest_10k_accession_number,
                item_number="1A" # Standard item number for Risk Factors
            )
            if risk_factors_content:
                print("\nSuccessfully extracted Risk Factors (Item 1A). Preview:")
                print(risk_factors_content[:1000] + "...")
            else:
                print("Failed to extract content for Item 1A.")
        except api_bricks_sec_api_rest.ApiException as e:
            print(f"API Exception when extracting Item 1A: {e}")
    else:
        print("\nNo 10-K filings found in the fetched data to extract from.")


Enter fullscreen mode Exit fullscreen mode

This code snippet first identifies the most recent 10-K from the DataFrame. It then uses that filing's accession_number to call the /v1/extractor/item endpoint, requesting the content for item_number="1A".

Final Thoughts

By using a company's CIK, you can retrieve its entire filing history with the FinFeedAPI. This guide showed how to get this data, plot key reporting timelines and frequencies, and then get the content of specific sections. This method is a fundamental technique for any detailed analysis of a single public company.

Top comments (0)