CommonGrants Python SDK
A Python SDK for interacting with the CommonGrants protocol, providing a type-safe interface for managing grant opportunities.
Table of contents
Installation
# Using pip
pip install common-grants-sdk
# Using Poetry
poetry add common-grants-sdk
Usage
Quick start
from common_grants_sdk.client import Client, Auth
from common_grants_sdk.client.config import Config
# 1. Create a client
config = Config(base_url="https://api.example.org", api_key="YOUR_API_KEY")
client = Client(config=config, auth=Auth.api_key("YOUR_API_KEY"))
# 2. List opportunities
response = client.opportunities.list()
for opp in response.items:
print(f"{opp.title} ({opp.status.value})")
Kitchen sink example
This example shows how the SDK's modules work together: declaring a plugin with typed custom fields and a custom filter, getting a pre-bound client from it, searching with both standard and custom filters, and validating standalone data with schemas.
from typing import Optional
from pydantic import Field
from common_grants_sdk.client import Config
from common_grants_sdk.extensions import (
CustomField,
CustomFieldSet,
PluginMeta,
PluginRoutes,
PluginSchemas,
ResourceRoutes,
define_plugin,
f,
schema,
)
from common_grants_sdk.schemas.pydantic.filters.opportunity import (
OpportunityFilters,
StringArray,
)
from common_grants_sdk.schemas.pydantic.models import OpportunityBase
# Custom fields attach to schemas. The value type on CustomField[V] flows through
# to opp.custom_fields.<field>.value on every parsed response row.
class OppFields(CustomFieldSet):
program_area: Optional[CustomField[str]] = Field(
default=None, description="Grant program area"
)
legacy_id: Optional[CustomField[int]] = Field(
default=None, description="Legacy system ID"
)
# Custom filters attach to routes. This one subclass both registers the filter
# and types the consumer's search(filters=...) call site.
class OppSearchFilters(OpportunityFilters, total=False):
agency: StringArray
plugin = define_plugin(
PluginSchemas(Opportunity=schema(common_schema=OpportunityBase[OppFields])),
routes=PluginRoutes(opportunities=ResourceRoutes(search=OppSearchFilters)),
meta=PluginMeta(name="my-system", source_system="my-system.example.gov"),
)
# A plugin-bound client parses responses with the plugin's schemas and types
# search(filters=...) by the filters it registered — no per-call schema argument.
client = plugin.get_client(
Config(base_url="https://api.example.org", api_key="YOUR_API_KEY")
)
result = client.opportunities.search(
search="education",
filters={
"status": f.in_(["open"]), # standard filter → top-level request field
"agency": f.in_(["HHS"]), # registered custom filter → customFilters
},
)
for opp in result.items:
print(f"{opp.title} ({opp.status.value})")
# Custom fields are fully typed
fields = opp.custom_fields
if fields is not None and fields.program_area is not None:
print(f" Program area: {fields.program_area.value}") # typed as str
# Rows that failed to parse are partitioned out rather than raising
for err in result.errors:
print(f" parse error at row {err.index}: {err.message}")
# Validate standalone data directly against the schema
raw = {
"id": "ac201443-5480-4e36-9799-a39765225153",
"title": "Community Health Grant",
"description": "A grant supporting community health initiatives.",
"status": {"value": "open"},
"createdAt": "2025-01-01T00:00:00Z",
"lastModifiedAt": "2025-01-01T00:00:00Z",
}
validated_opp = OpportunityBase.model_validate(raw)
print(validated_opp.title)
Modules
The SDK is organized into modules, each with its own documentation:
| Module | Description |
|---|---|
| Client | HTTP client with auth, pagination, and low-level HTTP methods |
| Schemas | Pydantic models, validation, and generic response schemas |
| Extensions | Custom fields and plugin framework |
API Client
HTTP client with built-in authentication, auto-pagination, and environment variable configuration. See the Client guide for setup, authentication, and usage examples.
Schemas and Validation
Pydantic v2 models for validating and parsing CommonGrants data, along with type-safe enum constants. See the Schemas guide for validation examples, type safety patterns, and the full API reference.
Extensions and Plugins
Extension framework for adding typed custom fields to CommonGrants schemas, either ad hoc or as reusable plugins. See the Extensions guide for the full guide.
License
See LICENSE
Metadata
Release files for common-grants-sdk 0.8.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| common_grants_sdk-0.8.1.tar.gz | 63.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| common_grants_sdk-0.8.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 152.0 kB
Release files / common_grants_sdk-0.8.1.tar.gz
| Download URL | common_grants_sdk-0.8.1.tar.gz |
|---|---|
| Size | 63.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ddd7d16a1f7458d3d57ca79efc3623337a9ee5581330d13245cf0842795cab7c
|
|
BLAKE2b-256 checksum How to use checksums |
878cb4a0b1b90ebbba8c9a171289b893d1c32d281c3beab97cc98b05776262f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1020-azure
|
Release files / common_grants_sdk-0.8.1-py3-none-any.whl
| Download URL | common_grants_sdk-0.8.1-py3-none-any.whl |
|---|---|
| Size | 88.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3ebe3d02570c59fc4538673bed37df0d30698264ffe686ce52b90e1d02f64ae0
|
|
BLAKE2b-256 checksum How to use checksums |
7dcab74ee1217880e8af888785a981c6d821d18cf7b57c4a9deaee1391aea517
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1020-azure
|