# openFEC is a Flask and Postgres API for federal campaign finance data

> The openFEC repository holds the Federal Election Commission's public API, a Python and Flask service that reads campaign finance records out of PostgreSQL and serves them over REST with an OpenSearch index behind it. It suits journalists and researchers who need filing data, and the local setup involves several services.

**fecgov/openFEC** — The first RESTful API for the Federal Election Commission. We're aiming to make campaign finance more accessible for journalists, academics, developers, and other transparency seekers.

- Repository: https://github.com/fecgov/openFEC
- Website: https://api.open.fec.gov/developers
- Stars: 536 · Forks: 120
- Language: Python
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/fecgov-openfec

## The API is a Flask service over a relational database with a search index

The architecture is conventional and the parts are visible in the repository layout. The service is Python, with a `src/` directory holding the application, `webservices/` for the API layer, `tests/` for the test suite and `data/` for the database tooling and migrations. The database is PostgreSQL, and the requirements file pins the stack in detail, with Flask 3.1.3, Flask-SQLAlchemy 3.1.1 and SQLAlchemy 2.0.41 for the data access, Flask-RESTful and Flask-Cors for the HTTP layer, and psycopg2-binary 2.9.1 for the PostgreSQL driver. The search side is OpenSearch, with opensearch-py 2.8.0 pinned in the same file, and OpenSearch 2.11 is listed as a project prerequisite. Marshalling and pagination are handled by flask-apispec 0.11.4, marshmallow 3.26.2 and marshmallow-sqlalchemy 1.4.2, with a fork of marshmallow-pagination pulled directly from a GitHub URL. Background work runs on Celery 5.2.2 with Redis 6.2.0 as the broker and kombu 5.5.3, and celery-once 3.0.0 for scheduled tasks.

## Flyway owns the schema, and a TOML file points it at your local database

Schema management is done with Flyway, and this is the part of the setup that catches people out. Flyway 13.7.0 is a project prerequisite, and after downloading it you create a TOML file at `flyway-13.7.0/conf/flyway.toml` and set the flyway environment variables `environment`, `url`, `user`, `password` and `locations`. The example configuration in the documentation is:

```toml
       [environments.local]
       url = "jdbc:postgresql://localhost:5432/cfdm_test"
       user = "<your local database username>"
       password = "<your local database password>"

       [flyway]
       environment = "local"
       locations = ["filesystem:/Users/<user>/<project>/api/openFEC/data/migrations"]
```bash

The `locations` entry points at the migration files, which the documentation calls the SQL for the database migration files, and it is worth noting that the example path is an absolute path into a checkout. The `environment = "local"` line selects which environment block Flyway uses, so a second environment means a second block. Because the schema is defined by migrations rather than by an ORM model, a developer who skips the Flyway step will find tables missing rather than get a helpful error, which is why the documentation points at the database migration section for more on installing and configuring it.

## Two databases, one for tests and one for development

The setup asks for two PostgreSQL databases, and the reason is that the test suite and the development server want different states. For the tests, the documentation says you need a test database and gives one command:

```bash
createdb cfdm_unit_test
```bash

For running the project itself, you need a development database:

```bash
createdb cfdm_test
```bash

Then the connection is passed in through the environment rather than a config file, using the SQLA_SAMPLE_DB_CONN variable:

```bash
export SQLA_SAMPLE_DB_CONN="postgresql://<username>:<password>@localhost:<port - default is 5432>/cfdm_test"
```bash

Loading the data is a single task:

```bash
invoke create-sample-db
```bash

That runs the Flyway migrations on the empty database to create the schema, then loads sample data from `data/sample_db.sql`. The order matters, because the migrations create the structure the sample data expects. The `invoke` command is the task runner, and the repository also has a `tasks.py` at the root, so the development commands are declared in one place rather than scattered across scripts.

## Python and JavaScript dependencies are installed side by side

The project is a hybrid, and the install steps reflect that. The Python side is two pip commands:

```bash
pip install -r requirements.txt
pip install -r requirements-dev.txt
```bash

The JavaScript side is a Node setup, with an LTS switch first:

```bash
nvm use --lts
npm install
npm run build
```bash

The package manifest explains what the JavaScript is for. The dependencies are react and react-dom, both at 16.7.0, with prop-types, minimist and the braintree sanitize-url package, and swagger-ui-dist 4.5.0, which is the piece that matters if you are consuming the API. The scripts cover the build, where `npm run build` runs the linter and then webpack with the production config, the development server, the formatter and the linter, and the combined format-and-lint target. The webpack setup has separate development and production config files at the root. The engines field pins Node at 24.16.0 and npm at 11.13.0, so a machine with an older Node will need a version manager, which is what the `nvm use --lts` step is about. The prerequisites also call for the latest 3.11 release of Python, which includes pip and the built-in venv module.

## Git hooks and invoke tasks keep the dependency files honest

The repository treats dependency files as something that can go stale, and it has machinery for that. It includes optional post-merge and post-checkout hooks that ensure dependencies are up to date, and if enabled these hooks update the Python dependencies when you check out or merge changes to `requirements.txt`. They are turned on and off with two commands:

```bash
invoke add-hooks
```bash

```bash
invoke remove-hooks
```bash

The word optional matters. The hooks are not installed by default, so a contributor who clones and forgets will not find them silently reinstalling packages, and a contributor who wants them can opt in. The same pattern of explicit opt-in appears in the security scanning, where the badges cover the known vulnerabilities in `package.json`, in `requirements.txt` and in the Flyway build file, so three dependency surfaces are tracked separately. That is a detail worth noticing about how this project is maintained, since the requirements file is where most of the risk lives and it is fully pinned.

## RDS boxes and replica followers are configured through two variables

The last part of the setup describes pointing the application at a managed database instead of a local one, and it does so with two environment variables and a warning. An FEC member can set the SQL connection to one of the RDS boxes with `export SQLA_CONN=<psql:address-to-box>`. The warning attached to it is emphatic: never perform an update all when pointing to an RDS box via the SQLA_CONN env var. The second variable configures the mirrors and replica boxes, with `export SQLA_FOLLOWERS=<psql:address-to-replica-box-1>[,<psql:address-to-replica-box-2>,...]`, and it takes a comma separated list with no space. The reason for a follower list is that reads can be directed at replicas while writes go to the primary, and the fact that it is a list rather than a single value says the deployment expects more than one. The documentation also points to a set up instructions page for running the apps on your own machine.

## The wider FEC project, and where to send what

This repository is one of four, and the project documentation is explicit about which is which, which matters if you file the wrong kind of issue. openFEC is described as the first RESTful API for the Federal Election Commission. The `fec` repository is a general discussion forum, and it is where feedback collected from the FEC.gov feedback widget is compiled, and it is described as the best place to submit general feedback. `fec-cms` is the content management system for the project. `fec-proxy` is a lightweight app that coordinates the paths between the web app and the CMS. So the API is its own codebase with its own issues, while general discussion and the feedback widget live elsewhere. The API documentation for developers is hosted at api.open.fec.gov/developers, and the general contribution route is to read the contributing guidelines and then file an issue or submit a pull request, with an email address given as an alternative for people who prefer it.

## What running this locally does not give you

Two limits are worth naming before you plan around this repository. The first is that the repository is the source of the service, not a hosted endpoint you can call. Running it locally means standing up PostgreSQL, OpenSearch and Flyway, migrating a schema, loading sample data, and serving the application yourself, and the sample data is a sample, not the full filing corpus. The second is the data model's shape. Federal campaign finance data is a graph of committees, candidates, receipts, disbursements and contributors, and the API's usefulness depends on the joins being right, so a consumer who queries the endpoint without reading the schema will get plausible but wrong aggregates. The alternative approach to weigh against is a bulk download and a local analytical tool, where the data is a set of flat files you load into your own database and query with SQL you control. The difference in approach is that the API gives you a normalised, join-ready model and a query language shaped around the domain, while a bulk file gives you the raw records and the freedom to model them however you like, at the cost of building the joins yourself. For a one-off analysis of a single committee's receipts, the bulk route is less work. For an application that has to answer questions across committees, contributors and filings, the API's model is the point.

## Conclusion

openFEC is the right starting point for a journalist, academic or transparency project that needs structured federal campaign finance data, because the filing records are already modelled, the schema is migrated with Flyway and the API is documented for developers at api.open.fec.gov/developers. It is a poor fit if you need a hosted endpoint you can depend on without running the stack yourself, since the repository is the service source and the local setup asks for PostgreSQL, OpenSearch and Flyway before anything responds. Before you build on it, confirm the licence terms, since the repository records a custom licence and carries a LICENSE.md file, and read the schema rather than the sample data, because the data model comes from the SQL migrations in the `data/migrations` directory. The last push to the repository was on 2026-10-21, on the `develop` branch.

## FAQ

### How do I set up openFEC for local development?

Install the prerequisites, which are Python 3.11, the latest LTS Node.js, PostgreSQL 13, Opensearch 2.11 and Flyway 13.7.0, then clone the repository, run pip install -r requirements.txt and pip install -r requirements-dev.txt, run nvm use --lts followed by npm install and npm run build, create the databases with createdb, and load the sample data with invoke create-sample-db.

### What does Flyway do in the openFEC setup?

Flyway owns the database schema through SQL migration files. You create a TOML file at flyway-13.7.0/conf/flyway.toml with the environment, url, user, password and locations settings, and the invoke create-sample-db task runs the migrations on an empty database before loading the sample data from data/sample_db.sql.

### Which database does openFEC use in development and which for tests?

The tests use a unit test database created with createdb cfdm_unit_test, and the development server uses a development database created with createdb cfdm_test. The connection string for the development database is set through the SQLA_SAMPLE_DB_CONN environment variable, and FEC members can point at an RDS box with SQLA_CONN or at replica boxes with SQLA_FOLLOWERS.

### Where should I send feedback or an issue about openFEC?

General feedback belongs in the fec repository, which is the discussion forum where feedback from the FEC.gov feedback widget is compiled, and it is described as the best place to submit general feedback. Bugs and pull requests for the API itself go to the openFEC repository, and the contributing guidelines are in CONTRIBUTING.md. An email address is also given as an alternative.

## Sources

- [fecgov/openFEC on GitHub](https://github.com/fecgov/openFEC)
- [Issues](https://github.com/fecgov/openFEC/issues)
- [Project website](https://api.open.fec.gov/developers)
- [README](https://github.com/fecgov/openFEC/blob/develop/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fecgov-openfec
