LDA Gov
A Ruby client for the LDA.gov Lobbying Disclosure Act API. Access lobbying filings, contributions, registrants, clients, lobbyists, and reference data.
No API key required for basic access (15 req/min anonymous). Optional API key available at lda.gov/api for higher rate limits.
Installation
Add to your Gemfile:
gem 'lda_gov'
Then bundle install, or install directly:
gem install lda_gov
Quick Start
require 'lda_gov'
# Search recent lobbying filings
filings = LDA.filings.list(filing_year: 2024)
filings.each { |f| puts f['filing_uuid'] }
Usage
Filings
# List filings with filters
filings = LDA.filings.list(filing_year: 2024, filing_period: 'Q1')
# Find a specific filing
filing = LDA.filings.find('some-filing-uuid')
# Quarterly filings
LDA.filings.quarterly(year: 2024, quarter: 1)
# Filter by registrant and client
LDA.filings.by_registrant_and_client(
registrant_name: 'Acme Lobbying',
client_name: 'Big Corp'
)
# Filter by filing type (quarterly reports, registrations, etc.)
LDA.filings.list(filing_year: 2024, filing_type: 'Q1')
Contributions
contributions = LDA.contributions.list
contribution = LDA.contributions.find(123)
Registrants
registrants = LDA.registrants.list
registrant = LDA.registrants.find(456)
Clients
clients = LDA.clients.list
client = LDA.clients.find(789)
Lobbyists
lobbyists = LDA.lobbyists.list
lobbyist = LDA.lobbyists.find(101)
Constants (Reference Data)
LDA.constants.filing_types
LDA.constants.
LDA.constants.government_entities
LDA.constants.states
LDA.constants.countries
LDA.constants.contribution_types
Pagination
Iterate page by page with each_page:
LDA.filings.each_page(filing_year: 2024) do |page|
page.each { |filing| process(filing) }
end
Fetch all results at once:
all_filings = LDA.filings.all_filings(filing_year: 2024)
all_filings.size # => total count
# Available on all resources
LDA.contributions.all_contributions
LDA.registrants.all_registrants
LDA.clients.all_clients
LDA.lobbyists.all_lobbyists
Configuration
LDA.configure do |config|
config.api_key = ENV['LDA_API_KEY'] # Optional — enables higher rate limits
config.timeout = 60 # Request timeout in seconds (default: 30)
config.retries = 5 # Max retries on 429/5xx (default: 3)
config.max_pages = 800 # Max pages per paginate call (default: 1000)
config.logger = Logger.new($stdout) # Optional request logging
end
Rails Initializer
# config/initializers/lda_gov.rb
LDA.configure do |config|
config.api_key = ENV['LDA_API_KEY']
config.timeout = 30
config.retries = 3
config.logger = Rails.logger if Rails.env.development?
end
Per-Instance Client
For different configurations in the same process:
client = LDA::Client.new(custom_config)
client.filings.list(filing_year: 2024)
client.contributions.list
Response Object
All API calls return an LDA::Response:
response = LDA.filings.list(filing_year: 2024)
response.results # Array of result hashes
response.each { |r| ... } # Enumerable — supports map, select, first, etc.
response.size # Results on this page
response.empty? # No results?
response.count # Total matching records (from API envelope)
response.total_count # Alias for count
response.next_page? # More pages available?
response.next_page_number # Page number from next URL
response.success? # HTTP 2xx?
response['key'] # Direct hash access
response.dig('nested', 'key')
response.raw # Raw parsed JSON body
response.to_h # Always returns a Hash
response.to_json # JSON string
Error Handling
begin
LDA.filings.find('INVALID')
rescue LDA::BadRequestError => e
puts "Bad request: #{e.status} — #{e.body}"
rescue LDA::NotFoundError => e
puts "Not found: #{e.status}"
rescue LDA::UnauthorizedError => e
puts "Unauthorized: #{e.body}"
rescue LDA::RateLimitError
puts 'Rate limited — retries exhausted'
rescue LDA::ServerError => e
puts "Server error: #{e.status}"
rescue LDA::ConnectionError => e
puts "Network issue: #{e.}"
end
Error hierarchy:
LDA::Error
├── ClientError
│ ├── BadRequestError (400)
│ ├── NotFoundError (404)
│ ├── UnauthorizedError (401)
│ ├── UnprocessableEntityError (422)
│ └── RateLimitError (429)
├── ServerError (500+)
└── ConnectionError (timeouts, DNS, refused)
All ClientError and ServerError subclasses expose .status and .body.
API Limitations
The LDA.gov API does not support server-side filtering by lobbying issue code. Passing a lobbying_issue parameter to the filings endpoint has no effect — the API returns all filings regardless.
Supported filters (confirmed working server-side):
filing_year— calendar yearfiling_type— filing type code (Q1–Q4,RR,RA,1T,1TY, etc.)filing_period— filing period (first_quarter,second_quarter, etc.)registrant_name— registrant name searchclient_name— client name search
To filter by issue code, iterate over filings and check lobbying_activities on each filing:
LDA.filings.each_page(filing_year: 2024, filing_type: 'Q1') do |page|
page.each do |filing|
issues = filing['lobbying_activities']&.map { |a| a['general_issue_code'] } || []
next unless issues.include?('DEF')
process(filing)
end
end
Development
git clone https://github.com/xjackk/lda_gov.git
cd lda_gov
bundle install
bundle exec rspec # Run tests
bundle exec rubocop # Lint
Requirements
- Ruby >= 3.1
- Faraday ~> 2.0
Support
License
MIT License. See LICENSE.txt.