---
title: "List individual grants"
method: GET
path: "/api/v1/grants/transactions"
tags: ["Grants"]
---

# List individual grants

`GET /api/v1/grants/transactions`

## Request

- Base URL: `https://data.useplinth.com`
- URL: `https://data.useplinth.com/api/v1/grants/transactions`
- Auth: API key in header `X-API-Key`

Individual grant rows — funder, recipient, amount, fiscal year, cause and the purpose text as filed. The graph traverses both ways: `funder_id` for everything a foundation funded, `recip_id` for every funder behind a nonprofit.

## Query parameters

- `funder_id` string, nullable
- `recip_id` string, nullable
- `id_type` 'ein', nullable
- `year` string, nullable
- `min_year` string, nullable
- `max_year` string, nullable
- `subject` string, nullable
- `location` string, nullable
- `geo_id_type` 'state' | 'zip' | 'city' | 'county_fips' | 'country', nullable
- `location_type` 'recipient' | 'funder' | 'area_served', nullable
- `country` string, nullable
- `query` string, nullable
- `support` string, nullable
- `funder_type` 'private_foundation' | 'public_charity' | 'daf_or_passthrough', nullable
- `exclude` string, nullable
- `exclude_daf` string, nullable
- `min_amt` string, nullable
- `max_amt` string, nullable
- `min_match_prob` string, nullable
- `ein_source` string, nullable
- `jurisdiction` string, nullable
- `strict` string, nullable
- `format` 'json' | 'xml', nullable
- `population` string, nullable
- `transaction` string, nullable
- `include_gov` string, nullable
- `last_updated` string, nullable
- `profile_levels` string, nullable
- `page` string, nullable
- `limit` string, nullable
- `sort_by` string, nullable
- `sort_order` 'asc' | 'desc', nullable
- `example` '1' | 'strict' | 'subject_pcs' | 'unsupported' | 'xml' | 'list'

## Response `200`

Grant lines matching the filter.

- TransactionsResponse
  - `code` integer
  - `message` string, required
  - `x_plinth` XPlinth: Non-Candid metadata. Safe to ignore for compatibility; `unsupported` is the one to assert on.
    - `warnings` ResponseWarning[], nullable
      - `parameter` string, required
      - `severity` string, required: `caveat` informs; anything else means a filter did NOT apply.
      - `reason` string, required
    - `unsupported` string[], nullable: Parameters that did not apply. Non-empty means the answer is not the question asked.
    - `dataset` DatasetStamp: Provenance of the slice that answered. `version` is the sync signal — poll it, re-pull when it moves.
      - `source` string, nullable
      - `refresh` string, nullable
      - `polled` string, nullable: How often we LOOK for a new IRS release, as distinct from how often the IRS publishes one.
      - `reporting_lag` string, nullable: Why a figure is dated to a fiscal year rather than to today.
      - `basis` string, nullable: Grants PAID versus grants approved — the reconciliation that catches people comparing a total here to a funder's own published giving figure. Read it before filing a discrepancy.
      - `version` string, nullable: Opaque build stamp of the data slice. Changes only when the data does.
      - `generated_at` string, nullable: ISO 8601 timestamp the slice was built.
      - `license` string, nullable: Licence the source data is published under, where it carries one. Absent for public-domain sources.
      - `attribution` string, nullable: Attribution the source licence obliges you to reproduce. Present it verbatim wherever you show figures from this jurisdiction.
      - `currency` string, nullable: Currency of every amount in the response, when it is not US dollars. Amounts are never converted — they are the filing's own figures.
    - `datasets` DatasetStamp[], nullable: Every corpus this response could have drawn on, each with its own licence terms. /sql only: you write the query, so which corpus answered is not knowable per response — honour every licence listed.
      - `source` string, nullable
      - `refresh` string, nullable
      - `polled` string, nullable: How often we LOOK for a new IRS release, as distinct from how often the IRS publishes one.
      - `reporting_lag` string, nullable: Why a figure is dated to a fiscal year rather than to today.
      - `basis` string, nullable: Grants PAID versus grants approved — the reconciliation that catches people comparing a total here to a funder's own published giving figure. Read it before filing a discrepancy.
      - `version` string, nullable: Opaque build stamp of the data slice. Changes only when the data does.
      - `generated_at` string, nullable: ISO 8601 timestamp the slice was built.
      - `license` string, nullable: Licence the source data is published under, where it carries one. Absent for public-domain sources.
      - `attribution` string, nullable: Attribution the source licence obliges you to reproduce. Present it verbatim wherever you show figures from this jurisdiction.
      - `currency` string, nullable: Currency of every amount in the response, when it is not US dollars. Amounts are never converted — they are the filing's own figures.
    - `excluded` object, nullable: Per-class cost of `?exclude=`, keyed by class name, plus `overlapping` — true when classes were counted independently and therefore sum to more than the whole. /grants/summary only.
    - `unidentified` Unidentified: Grants held OUT of a recipient ranking because their recipient is not an organization.
      - `grants` integer, nullable
      - `dollars` integer, nullable
      - `note` string, nullable
      - `unavailable` string, nullable: Present only when the size could not be computed. The ranking above is unaffected.
  - `hits` integer, required: Total matching rows, not the number returned.
  - `page` integer, required
  - `limit` integer, required
  - `results_count` integer, required: Rows in THIS response.
  - `total_pages` integer, required
  - `results` GrantTransaction[], required
    - `funder_ein` string, required
    - `funder_name` string, nullable
    - `recip_ein` string, nullable
    - `recip_name` string, nullable
    - `recip_city` string, nullable
    - `recip_state` string, nullable
    - `recip_zip` string, nullable
    - `recip_country` string, nullable
    - `amount` integer, nullable
    - `fiscal_year` integer, nullable: Fiscal year of the FILING, not the payment date.
    - `subject` string, nullable
    - `description` string, nullable
    - `x_plinth` GrantProvenance: `match_prob` IS NOW POPULATED ON EVERY RESOLVED ROW, and `ein_source` says what it means. This previously read "match_prob is null on every row", because it was only ever written on the `grant_line` tier, which is empty in the published slice. It is now written across the universe: every row with a recipient EIN carries a probability, and every row without one carries null. `ein_source` remains the field to filter on when you want a specific provenance rather than a threshold — `ein_source = 'filed'` is the filer-stated subset. WHERE THE NUMBER COMES FROM. Rows resolved by a RULE carry that rule's measured held-out precision — a per-rule estimate applied to its rows, not a posterior. Rows resolved by the MODEL (`ein_source='model'`) carry a genuine per-row calibrated probability, isotonic-fitted on a held-out validation split and measured to track observed rates within a few tenths of a point. An earlier version of this docstring said a calibrated posterior "needs Splink, which is not wired". That is no longer true: pipeline/match_model.py fits a gradient-boosted matcher on the residual the rules decline, using filer-stated EINs as free ground truth. THE CAVEAT THAT TRAVELS WITH IT. Those labels come from 990/990-EZ Schedule I filers, whose recipients skew larger and better-registered than the 990-PF names the resolver mostly works on, so the figures are an optimistic estimate of deployed precision. An off-corpus 990-PF grantee list scored 0.9876 on the same rules, so the gap is not large — but it is one funder.
      - `match_prob` number, nullable: P(this recipient EIN is correct), on every resolved row. The GRANULARITY differs and `ein_source` says which: rows resolved by the model carry a per-row calibrated posterior (isotonic-fitted on held-out validation); rows resolved by a rule carry that rule's measured held-out precision — a per-rule estimate, not a posterior. Null means the row is unresolved, or its provenance predates the field. Filter on it and you keep the rule-resolved majority as well as the model's rows. ⚠️ THE MODEL'S VALUES TOP OUT BELOW 1. Isotonic calibration can only emit values it observed on validation, so model rows span roughly 0.95-0.965 and NOTHING carries a model probability above ~0.965. A filter of `match_prob > 0.97` therefore returns zero model rows while still returning `filed` (0.995) and `name` (0.970) — it reads as a confidence threshold and acts as a provenance filter. Use `ein_source` if that is what you meant.
      - `source_tier` string, nullable: Which extraction tier produced the row: `universe` (lean, from the filing index) or `matched` (rich, with a confidence). **Currently `universe` on every row.**
      - `ein_source` string, nullable: How the recipient EIN was arrived at, with the measured precision each carries in `match_prob`. Ordered strongest first; the resolver applies them in this order and a later rule only ever sees what the earlier ones declined. `filed` (0.995) the filer stated it on the return. `override_human` (0.99) an adjudicated correction. `override_keyerror` (0.98) a filer-stated EIN that exists in no register and is one identifiable keying slip from the EIN of the organisation the name resolves to — a correction of the filer, not of us. `name` (0.970) exact normalised name, unique within state. `registry-dominant` (0.970) an ambiguous alias where one EIN holds >=90% of the distinct funders who file that name. `fuzzy` (0.961) one edit from a registered name, with the ZIP agreeing. `override_llm` (0.95) an LLM adjudication of an ambiguous string. `registry` (0.944) the Schedule I alias registry, gated at 2+ distinct funders. `address` (0.944) address-as-key with a 2-edit name gate. `zip` (0.934) same name, disambiguated by recipient ZIP. `street` (0.834) same name, disambiguated by street — the weakest rule; exclude it if precision matters more than reach. `model` a per-row calibrated posterior, see `match_prob`. `null`: no recipient EIN, or provenance predating this field. Filter to `filed` for anything load-bearing.

## Other responses

- `400`: A parameter we understood the name of but not the value of.
- `401`: No API key, or a key we do not recognize.
- `402`: The call allowance is spent, the account is inactive, or the endpoint needs a paid plan — the message says which, and names the period it resets on (daily on free and non-profit plans, monthly on Pro).
- `422`: Validation Error

---

[API](https://skmtc.dev/useplinth/apis/plinth-grants-api.md) · [All operations](https://skmtc.dev/useplinth/apis/plinth-grants-api/llms.txt) · [OpenAPI document](https://skmtc.dev/useplinth/apis/plinth-grants-api/revisions/15273cd72ecf?raw)
