Skip to main content

awardgetter

A Python library for identifying which funding agency issued a given award ID string, and for fetching award metadata from those agencies.

The design is analogous to image-reading libraries like imageio: given an input string, the library tries to figure out which "reader" (funder) handles it. Since award ID formats can overlap across funders, find_matching_funders returns all plausible matches and lets the caller disambiguate — either by prompting the user or by accepting a known funder slug.

Supported Funders

FUNDER_ID Display Name Accepted Alternate IDs / Names get_award_details
nsf U.S. National Science Foundation Live API
nih U.S. National Institutes of Health nci, nigms, niaid, nimh, nhlbi, niddk, ninds, nichd, nibib, nia, niehs, nidcd, nidcr, nida, niams, nei, ninr, nlm, fic, nccih, ncats Live API (NIH RePORTER)
epsrc_ukri UK Research and Innovation (UKRI) epsrc, mrc, bbsrc, nerc, esrc, ahrc, stfc, ukri Live API (Gateway to Research)
ec_cordis European Commission (CORDIS) cordis, ec, h2020, horizon, fp7 Bulk parquet (see Caching)
snsf Swiss National Science Foundation snf Bulk CSV
anr Agence Nationale de la Recherche (France) Bulk CSV
dfg Deutsche Forschungsgemeinschaft (Germany) Live API (GEPRIS)
doe U.S. Department of Energy Live API (USASpending)
jsps_kakenhi Japan Society for the Promotion of Science (KAKENHI) jsps, kakenhi Web scraping (KAKEN)
nsfc National Natural Science Foundation of China Not implemented
nkrdp National Key Research and Development Program of China Not implemented

Installation

Requires Python ≥ 3.12.

pip install awardgetter

Quick Start

Find which funders match an award ID

from awardgetter import find_matching_funders

# Unambiguous: the "NSF" prefix makes this uniquely an NSF award
find_matching_funders("NSF 1728743")
# ['nsf']

# Unambiguous: the DE- prefix is specific to DOE
find_matching_funders("DE-SC0021358")
# ['doe']

# Ambiguous: bare 7-digit numbers match NSF, NSFC, and CORDIS formats
find_matching_funders("1728743")
# ['nsf', 'nsfc', 'ec_cordis']

# No match
find_matching_funders("not-an-award-id")
# []

Fetch award details

from awardgetter import get_award_details

result = get_award_details("nsf", "1728743")

for award in result.found:
    print(award.award_id)       # "1728743"
    print(award.amount_funded)  # 523456.0
    print(award.currency)       # "USD"
    print(award.start_date)     # datetime.date(2017, 9, 1)
    print(award.end_date)       # datetime.date(2021, 8, 31)

for miss in result.not_found:
    print(miss.reason)   # NotFoundReason.NOT_FOUND
    print(miss.detail)   # human-readable message

The funder argument is case-insensitive and accepts any alternate ID or name from the table above:

get_award_details("National Science Foundation", "1728743")
get_award_details("NCI", "5R01CA123456-03")   # NIH institute alternate ID
get_award_details("EPSRC", "EP/L016796/1")    # UKRI council alternate ID

Multiple award IDs can be passed as a space- or comma-separated string:

result = get_award_details("nih", "R01GM061300 U24NS124001")
print(len(result.found))      # 2

API Reference

find_matching_funders(text) -> list[str]

Returns the FUNDER_ID of every funder whose award ID pattern matches text. Returns an empty list if nothing matches. Multiple results are by design for ambiguous formats.

get_award_details(funder, award_id, cache_dir=None, force_refresh=False) -> AwardDetailsResult

Fetches metadata for one or more award IDs from a specific funder.

Parameter Type Description
funder str A FUNDER_ID, display name, or alternate ID (case-insensitive)
award_id str One or more award IDs (space- or comma-separated)
cache_dir Path | None Override the default cache directory
force_refresh bool Re-download cached bulk data even if it is fresh

Return types

@dataclass(frozen=True)
class AwardDetails:
    funder_id: str              # e.g. "nsf"
    award_id: str               # Normalized ID as returned by the funder
    amount_funded: float | None # Award amount in the funder's currency
    currency: str | None        # ISO 4217 code, e.g. "USD", "EUR", "CHF"
    start_date: date | None
    end_date: date | None

@dataclass(frozen=True)
class AwardNotFound:
    funder_id: str
    input_text: str        # The input that could not be resolved
    reason: NotFoundReason
    detail: str            # Human-readable explanation

@dataclass(frozen=True)
class AwardDetailsResult:
    found: list[AwardDetails]
    not_found: list[AwardNotFound]

NotFoundReason values:

Value Meaning
NOT_FOUND Format is valid but the ID is not in the funder's database
PARSE_ERROR No recognizable award ID could be extracted from the input
API_ERROR Network or HTTP error when querying the funder's API
CACHE_ERROR Problem loading the cached bulk data file
RATE_LIMITED Funder API returned HTTP 429

Caching

Funders that use bulk data files (CORDIS, SNSF, ANR) cache downloads under ~/.cache/awardgetter/ by default. Files are re-downloaded automatically after 30 days, or immediately when force_refresh=True.

CORDIS requires a one-time setup step. The CORDIS parquet file must be built from Horizon raw data before get_award_details("ec_cordis", ...) will work:

awardgetter-preprocess-cordis <path-to-cordis-json-ld-directory>

This places cordis_projects.parquet in the cache directory.

Performance

Out of a sample of 4000 Award IDs, awardgetter was able to find the funded amount, and the start and end dates for ~75% of them.

Funder Total Found Success %
nsf 1368 1229 89.8
snsf 157 129 82.2
anr 176 137 77.8
epsrc_ukri 177 134 75.7
nih 1155 772 66.8
ec_cordis 220 136 61.8
dfg 382 236 61.8
jsps_kakenhi 217 124 57.1
doe 148 83 56.1

Awards requested with awardgetter were specifically those that OpenAlex didn't have the funded amount or start and date information for already.

Development

just install   # install in editable mode with dev dependencies (uses uv)
just lint      # ruff check + format, then pyrefly type checking
just clean     # remove build artifacts

pytest awardgetter/tests/           # unit tests (no network)
just test.                          # integration tests (real API calls)

Adding a new funder

  1. Create awardgetter/funders/<funder_id>.py implementing the FunderModule protocol (_spec.py). Use nsf.py as the canonical example.
  2. Import the module in awardgetter/funders/__init__.py and append it to ALL_FUNDERS (and ALL_DETAIL_FUNDERS if get_award_details is implemented).
  3. Populate the EXAMPLES constant — parametrized tests in test_check_award_id.py and test_get_award_details.py expand automatically from it.

License

MPL 2.0

AI Usage Statement

While library structure and design decisions (e.g., mirroring the structure of image reading libraries), were deliberate design choices, much of the functionality of this library was developed using Claude Code. Retrieved award results were evaluated both by humans and AI.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

awardgetter-0.1.0.tar.gz (57.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

awardgetter-0.1.0-py3-none-any.whl (72.2 kB view details)

Uploaded Python 3

File details

Details for the file awardgetter-0.1.0.tar.gz.

File metadata

  • Download URL: awardgetter-0.1.0.tar.gz
  • Upload date:
  • Size: 57.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for awardgetter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b7180ee8601834366d0cebfb9b229066a02f377cc1f944a5de4dd00a35cbe7b5
MD5 4c3eac13f263d9c0d01cfa6d7c9bbcf2
BLAKE2b-256 69c840f770eae8ef7d29f0fbc6acd31580e983c5139d32150a807b670bb9a65d

See more details on using hashes here.

Provenance

The following attestation bundles were made for awardgetter-0.1.0.tar.gz:

Publisher: ci.yml on evamaxfield/awardgetter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file awardgetter-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: awardgetter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 72.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for awardgetter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ad878db756d249c5dd55893b9b766d486a9f013b5fe0b171a984fc56616e294
MD5 2f54058e601ebe3c84f6da4c85072294
BLAKE2b-256 c4953203c18e38d86a52636a9f1805cc4290fbb6da2381874ffedb1916a8d37f

See more details on using hashes here.

Provenance

The following attestation bundles were made for awardgetter-0.1.0-py3-none-any.whl:

Publisher: ci.yml on evamaxfield/awardgetter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page