This repository contains the code responsible for v3 of the Open States API, currently in beta.
Report API Issues at https://github.com/openstates/issues/
The selected base image supports amd64
and arm64
build targets (and this is shown in the CI workflow).
Use docker buildx
for local multi-arch builds, e.g.
docker buildx create --use
docker buildx build --platform amd64,arm64 .
See infrastructure repo. Plural employees also see the Open States Maintenance ops guide
To run locally, you first need to have a running local database following these instructions
You also need to have a redis instance running. That can be run via the docker-compose config included in this package
by running docker compose up redis
You can then run the app directly with the command:
DATABASE_URL=postgresql://openstates:openstates@localhost:5405/openstatesorg poetry run uvicorn api.main:app
- Check that the port is correct for your locally running database
- Username/password/dbname in example above are from openstates-scrapers docker-compose.yml, they also need to match the local DB.
To test out hitting the API, there will need to be a user account + profile entry with an API key in the local DB. The
scripts involved in the above-mentioned instructions (openstates.org repo init DB) should result in the creation of an
API key called testkey
that can be used for local testing.
- In addition to having the normal DB container running (as described above), you need to also start the
db-test
service available in this project'sdocker-compose.yml
: in this repo directory, rundocker compose up -d db-test
- Run all tests:
poetry run pytest
in the CLI; or in PyCharm configure a python test run targeting thepytest
module - Run an individual test: add an argument to either of the above specifying the test file and function name, eg
api/tests/test_bills.py::test_bills_filter_by_jurisdiction_abbr
Components of this FastAPI application:
- Routes, found in the
api/
folder, such asapi/bills.py
. These expose HTTP API routes and contain the business logic executed when a request hits that route. - SQL Alchemy models, found in the
api/db/models
folder, such asapi/db/models/bills.py
that define the data models used by business logic to query data. - Pydantic schemas, found in the
api/schemas.py
folder, which define how data from the database is transformed into output that is returned by business logic to the client. - Pagination logic, found in
api/pagination.py
and in route files, provides a semi-magic way for business logic to use SQL Alchemy models to manage things like includes, pagination of results, etc..
If you want to make a change, such as adding a related entity to output on an endpoint, you likely need to make changes to:
- The Model file: add the new entity as a model, and a relationship property on the entity that is related to it. This informs which columns are selected via which join logic.
- The Pydantic schema: add the entity and fields to the output schema. Even if the Model changes are correct, the data will not show up in API output unless it is in the schema.
- The relevant Pagination object in the route file: you may need to add to
include_map_overrides
to tell the pagination system that sub-entities should be fetched when an include is requested. If you add a sub-sub entity here, such as "actions.related_entities" to theBillPagination
, make sure to explicitly add the sub-entity as well: "actions". Otherwise, additional queries will be generated to lazy-load the sub-entity.