CommonGrants Protocol Specification: Key Features and Implementation Guide

The CommonGrants protocol defines a stable, versioned API contract for sharing grant-related data across the grants ecosystem, balancing strict compliance with flexible implementation extensions.

The hhs/simpler-grants-protocol repository provides the canonical reference for standardizing how grant opportunities, applications, and awards are exchanged between systems. This specification ensures interoperability while providing clear extension points for domain-specific requirements.

Versioned RFC-Style Specification

The protocol follows Semantic Versioning (Major.Minor.Patch) and uses BCP 14 keywords for requirement levels, as defined in website/src/content/docs/protocol/specification/v0_1_0.md.

  • Major increments indicate breaking changes, such as new required routes or fields.
  • Minor increments add backward-compatible features like optional routes or enum values.
  • Patch increments cover non-functional changes including documentation updates.

This versioning strategy ensures that API consumers can depend on stable contracts while implementers can track compliance requirements against specific specification versions.

Route Stability Levels

The specification categorizes API routes into three distinct stability levels to clarify implementation obligations:

Stability Meaning
Required Must be implemented for full compliance.
Optional May be implemented as useful extensions.
Experimental Unstable features intended for feedback only.

The route definitions, including GET /opportunities, GET /opportunities/{id}, and POST /opportunities/search, are specified in website/src/content/docs/protocol/specification/v0_1_0.md.

Canonical Data Schemas

All data exchanged through the protocol follows Zod-derived JSON schemas defined in lib/ts-sdk/src/schemas.ts. These schemas enforce type safety and generate corresponding TypeScript types exported from lib/ts-sdk/src/types.ts.

The schema architecture includes:

  • Base Types – Fundamental primitives including UUIDs, URLs, dates, and arrays.
  • Core Fields – Reusable components such as Money, Event, CustomField, and SystemMetadata.
  • Domain Models – Grant-specific entities including OpportunityBase, OppStatus, OppFunding, and OppTimeline.

TypeScript consumers can import these types directly for compile-time safety:

import { OpportunityBase, OpportunityResponse } from "@common-grants/sdk/types";

Query Capabilities

Pagination and Sorting

List endpoints SHOULD support pagination using page and pageSize query parameters, returning a paginationInfo object containing total counts and navigation links.

Sorting capabilities include sortBy, customSortBy, and sortOrder parameters, with responses including sortInfo metadata. These features allow clients to navigate large datasets efficiently while maintaining protocol compliance.

Advanced Filtering

The protocol defines a comprehensive filter language supporting operators including eq, neq, gt, lt, in, and between. Filters are submitted within a filters object in search requests (such as POST /opportunities/search) and returned in a filterInfo wrapper.

The filter schemas are enforced through Zod validation in lib/ts-sdk/src/schemas.ts, ensuring type safety across implementations.

Implementation Extensions

The specification provides four primary extension mechanisms to accommodate domain-specific requirements without breaking core compliance:

Extension Purpose Implementation
Custom fields Add arbitrary attributes to models customFields array on OpportunityBase
Custom enum values Extend standard enums custom sentinel value in enums
Custom filters Domain-specific query criteria customFilters parameter
Custom routes Non-standard endpoints Outside /common-grants/ path prefix

These mechanisms are documented in website/src/content/docs/protocol/specification/v0_1_0.md and ensure that agencies can model local business rules while maintaining interoperability with standard consumers.

Developer Tooling

Validation and Compliance

The @common-grants/cli package provides command-line tools to validate OpenAPI documents against the protocol specification. This ensures that implementations meet compliance requirements before deployment.

TypeScript SDK Integration

The reference implementation includes a TypeScript SDK (lib/ts-sdk/) that provides compile-time type safety through Zod-derived schemas. Developers can import types such as OpportunityResponse and OpportunitiesListResponse from lib/ts-sdk/src/types.ts, ensuring that client code adheres to protocol contracts.

The following example demonstrates how to interact with a compliant API using the SDK types:

import {
  OpportunityResponse,
  OpportunitiesListResponse,
  OppSearchRequest,
  OppFilters,
  OppSorting,
  PaginatedBodyParams,
} from "@common-grants/sdk/types";

/** GET a single opportunity (required route) */
async function getOpportunity(id: string): Promise<OpportunityResponse> {
  const resp = await fetch(`/common-grants/opportunities/${id}`);
  return (await resp.json()) as OpportunityResponse;
}

/** Search opportunities with filters, sorting, and pagination (optional route) */
async function searchOpportunities(req: OppSearchRequest) {
  const resp = await fetch(`/common-grants/opportunities/search`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(req),
  });
  return (await resp.json()) as OpportunitiesListResponse;
}

/* Example request payload */
const request: OppSearchRequest = {
  search: "climate",
  filters: {
    title: { value: "climate", operation: "like" },
    closedDateRange: {
      value: { min: "2024-01-01", max: "2024-12-31" },
      operation: "between",
    },
  } as OppFilters,
  sorting: { sortBy: "lastModifiedAt", sortOrder: "desc" } as OppSorting,
  pagination: { page: 1, pageSize: 20 } as PaginatedBodyParams,
};

This implementation compiles against the TypeScript types defined in lib/ts-sdk/src/types.ts, guaranteeing that request bodies and responses adhere to the protocol contracts.

OpenAPI-First Design

The protocol supports authoring APIs in TypeSpec, compiling to OpenAPI specifications, and generating SDKs automatically. This workflow provides IntelliSense support and compile-time validation throughout the development lifecycle, as implemented in the reference repository.

Summary

  • The CommonGrants protocol uses Semantic Versioning (Major.Minor.Patch) to manage breaking and non-breaking changes.
  • Routes are classified as Required, Optional, or Experimental to clarify implementation obligations.
  • Zod-derived JSON schemas in lib/ts-sdk/src/schemas.ts enforce type safety for all data exchange.
  • Rich query capabilities include pagination, sorting, and advanced filtering with operators like eq, gt, and between.
  • Implementation extensions (custom fields, enums, filters, routes) allow flexibility without sacrificing compliance.
  • Developer tooling includes a CLI validator, TypeScript SDK, and OpenAPI-first TypeSpec workflow.

Frequently Asked Questions

What versioning scheme does the CommonGrants protocol use?

The protocol follows Semantic Versioning (Major.Minor.Patch) as defined in website/src/content/docs/protocol/specification/v0_1_0.md. Major version increments indicate breaking changes such as new required routes, while minor versions add backward-compatible features like optional fields. Patch versions cover non-functional updates including documentation corrections.

How does the protocol handle custom data fields?

The specification provides a custom fields extension mechanism through the customFields array property on models like OpportunityBase. This allows implementers to add arbitrary domain-specific attributes without breaking core protocol compliance. Custom fields are defined in the canonical data schemas within lib/ts-sdk/src/schemas.ts and documented in the specification.

What filtering capabilities are available in the CommonGrants protocol?

The protocol defines a comprehensive filter language supporting operators including eq, neq, gt, lt, in, and between. These filters are submitted via the filters object in search requests (such as POST /opportunities/search) and returned in a filterInfo wrapper. The filter schemas are enforced through Zod validation in the TypeScript SDK.

How can developers validate their API implementation against the protocol?

Developers can use the @common-grants/cli package to validate OpenAPI documents against the protocol specification. Additionally, the TypeScript SDK (lib/ts-sdk/) provides compile-time type safety through Zod-derived schemas exported from lib/ts-sdk/src/types.ts. The protocol also supports an OpenAPI-first workflow using TypeSpec, enabling validation during the API design phase.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →