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
- Create
awardgetter/funders/<funder_id>.pyimplementing theFunderModuleprotocol (_spec.py). Usensf.pyas the canonical example. - Import the module in
awardgetter/funders/__init__.pyand append it toALL_FUNDERS(andALL_DETAIL_FUNDERSifget_award_detailsis implemented). - Populate the
EXAMPLESconstant — parametrized tests intest_check_award_id.pyandtest_get_award_details.pyexpand 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7180ee8601834366d0cebfb9b229066a02f377cc1f944a5de4dd00a35cbe7b5
|
|
| MD5 |
4c3eac13f263d9c0d01cfa6d7c9bbcf2
|
|
| BLAKE2b-256 |
69c840f770eae8ef7d29f0fbc6acd31580e983c5139d32150a807b670bb9a65d
|
Provenance
The following attestation bundles were made for awardgetter-0.1.0.tar.gz:
Publisher:
ci.yml on evamaxfield/awardgetter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awardgetter-0.1.0.tar.gz -
Subject digest:
b7180ee8601834366d0cebfb9b229066a02f377cc1f944a5de4dd00a35cbe7b5 - Sigstore transparency entry: 2520365127
- Sigstore integration time:
-
Permalink:
evamaxfield/awardgetter@0943e481bb42b300f7d4312f76ca3da5c567489e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/evamaxfield
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@0943e481bb42b300f7d4312f76ca3da5c567489e -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ad878db756d249c5dd55893b9b766d486a9f013b5fe0b171a984fc56616e294
|
|
| MD5 |
2f54058e601ebe3c84f6da4c85072294
|
|
| BLAKE2b-256 |
c4953203c18e38d86a52636a9f1805cc4290fbb6da2381874ffedb1916a8d37f
|
Provenance
The following attestation bundles were made for awardgetter-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on evamaxfield/awardgetter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awardgetter-0.1.0-py3-none-any.whl -
Subject digest:
9ad878db756d249c5dd55893b9b766d486a9f013b5fe0b171a984fc56616e294 - Sigstore transparency entry: 2520365271
- Sigstore integration time:
-
Permalink:
evamaxfield/awardgetter@0943e481bb42b300f7d4312f76ca3da5c567489e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/evamaxfield
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@0943e481bb42b300f7d4312f76ca3da5c567489e -
Trigger Event:
push
-
Statement type: