Building a Reactive SEC EDGAR Data Fetcher with Spring Boot

The U.S. Securities and Exchange Commission (SEC) provides a wealth of financial data through its EDGAR database. For developers and financial analysts, accessing this data programmatically can unlock powerful insights.

In this post, we’ll walk through a lightweight Java application designed to fetch company submission data directly from the SEC’s public APIs using Spring Boot and Spring WebFlux.

🚀 Project Overview

The goal of this project is simple: create a REST API that takes a company’s CIK (Central Index Key) and returns their filing history from the SEC.

Tech Stack:

  • Java 17
  • Spring Boot 3.5.8 (WebFlux for reactive programming)
  • Lombok (to reduce boilerplate)
  • Maven

🛠️ Implementation Details

1. The Data Model

First, we define a simple model to map the JSON response from the SEC. We use Lombok’s @Data  annotation to automatically generate getters, setters, and toString method

package com.leveraon.app.sec.edgar.model;

import java.util.Map;
import lombok.Data;

@Data
public class EdgarSubmission {
    private String name;
    private String cik;
    private Map<String, Object> filings;
}

2. The Service Layer (The Core Logic)

The EdgarApiService is where the magic happens. We use Spring’s WebClient  to make non-blocking HTTP requests.

Critical Detail: The SEC requires a valid 

User-Agent

 header in the format Sample Company Name AdminContact@<sample company domain>.com . Without this, your requests will be blocked.

@Service
public class EdgarApiService {
    private final WebClient webClient;
    // IMPORTANT: Replace with your actual contact info as per SEC guidelines
    private static final String USER_AGENT = "Joe Doe contact@example.com";
    private static final String BASE_URL = "https://data.sec.gov";

    public EdgarApiService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl(BASE_URL)
                .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                .build();
    }

    public Mono<EdgarSubmission> getSubmissionsByCik(String cik) {
        // SEC API expects CIK in a specific format, e.g., CIK0000320193.json
        String urlPath = String.format("/submissions/CIK%s.json", cik);

        return webClient.get()
                .uri(urlPath)
                .retrieve()
                .bodyToMono(EdgarSubmission.class);
    }
}

3. The Controller

Finally, we expose the functionality via a REST controller. The endpoint returns a Mono<EdgarSubmission> adhering to reactive principles.

@RestController
@RequestMapping("/api/edgar")
public class EdgarController {

    private final EdgarApiService edgarService;

    public EdgarController(EdgarApiService edgarService) {
        this.edgarService = edgarService;
    }

    @GetMapping("/submissions/{cik}")
    public Mono<EdgarSubmission> getSubmissions(@PathVariable String cik) {
        return edgarService.getSubmissionsByCik(cik);
    }
}

🏃‍♂️ Running the Application

To run the application, ensure you have Maven installed and run the following command in your terminal:

./mvnw spring-boot:run

Once the application is started, you can test it using curl or your browser. For example, to fetch data for Apple Inc. (CIK: 0000320193):

 curl http://localhost:8080/api/edgar/submissions/0000320193

💡 Key Takeaways

  1. Reactive by Default: Using WebClient and Mono ensures our application handles I/O efficiently, which is crucial when dealing with external APIs that might have latency.
  2. Compliance: Respecting API usage guidelines (like the User-Agent header) is essential for building robust scrapers or data fetchers.
  3. Simplicity: Spring Boot allows us to spin up a powerful integration service with just three main classes.

Happy Coding! 🚀

Leave a Comment

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

Scroll to Top