Charity Verify API
Single EIN verification
Bulk Verify API
Batch EIN verification (up to 20K)
Report API
PDF verification reports
Form 990 Data API
Base & Pro tiers — financials, comp, peer benchmarks
Support

Charity Verify API

One API call to check tax-deductible eligibility, revocation status, group exemptions, and OFAC sanctions screening for any U.S. nonprofit.

Overview

The Charity Verify API cross-references multiple IRS data sources and OFAC sanctions lists to give you a single, definitive answer on whether a nonprofit can receive tax-deductible donations.

Data sources checked on every request:

  • IRS Exempt Organizations Business Master File (EO BMF)
  • IRS Publication 78 (eligible donees)
  • IRS Auto-Revocation List (with reinstatement detection)
  • Group Exemption resolution (subordinate → parent lookup)
  • OFAC SDN & Consolidated sanctions lists (fuzzy matching)
  • Form 990 leadership screening against OFAC
BASE URL   https://api.givalgo.ai/v1

Authentication

All API requests require an API key passed in the x-api-key header.

# Include your key in every request
curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/verify?ein=53-0196605"

To get an API key, contact support@givalgo.ai. Keys are scoped to a usage plan (Free, Basic, or Pro) which determines your rate limits.

Keep your API key secure. Do not expose it in client-side code or public repositories. If compromised, contact support for a key rotation.

Quickstart

Get up and running in 60 seconds.

cURL

# Verify American Red Cross
curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/verify?ein=53-0196605"

Python

import requests

response = requests.get(
    "https://api.givalgo.ai/v1/verify",
    params={"ein": "53-0196605"},
    headers={"x-api-key": "YOUR_API_KEY"}
)
data = response.json()

if data["deductible"]:
    print(f"{data['organization']['name']} is eligible!")
else:
    print(f"Status: {data['status']} - {data['message']}")

JavaScript

const response = await fetch(
  "https://api.givalgo.ai/v1/verify?ein=53-0196605",
  { headers: { "x-api-key": "YOUR_API_KEY" } }
);
const data = await response.json();
console.log(data.status, data.organization?.name);

Verify Endpoint

GET   /v1/verify?ein={ein}&donor_state={state}&ca_entity_id={id}

Returns a complete verification of the nonprofit identified by the given EIN, including tax-deductible eligibility, revocation history, group exemption status, OFAC sanctions screening, and California state compliance (when applicable).

Parameters

ParameterTypeRequiredDescription
einstringYesEmployer Identification Number. Accepts 13-1837418, 131837418, or 13 1837418.
donor_statestringNoTwo-letter state code of the donor (e.g., CA). When set to CA, California AG + FTB compliance checks run even if the nonprofit is not CA-based. See California Compliance.
ca_entity_idstringNoCalifornia SOS/FTB entity number for direct lookup in the CA AG Registry and FTB Revocation list. Provides the highest coverage for California compliance checks.

Response Fields

FieldTypeDescription
statusstringOverall verification result (see Statuses)
deductiblebooleanWhether donations are tax-deductible. null if not found.
messagestringHuman-readable explanation
organizationobjectIRS EO BMF data (name, city, state, subsection, foundation type, assets, income, NTEE code)
pub78objectPublication 78 listing and deductibility type (PC, PF, POF, SO, etc.)
revocationobjectAuto-revocation history and reinstatement status
group_exemptionobjectPresent when ELIGIBLE via group exemption. Shows parent org details. Only applies to 501(c)(3) subordinates.
sanctions_screeningobjectOFAC screening results (see Sanctions Screening below for match object details)
state_complianceobject | absentPresent only when California compliance checks are triggered. Contains california sub-object with AG registry and FTB status. See California Compliance.
data_freshnessobjectISO dates showing when each source agency last published their data file (eo_bmf, pub78, revocation, ofac_sdn, ofac_cons)
checked_atstringISO 8601 timestamp of this verification

sanctions_screening object

FieldTypeDescription
statusstringCLEAR, POTENTIAL_MATCH, STRONG_MATCH, or NOT_SCREENED
organization_screeningobjectOrg name screened against OFAC entity entries
  .checked_namestringOrganization name that was screened
  .matches_foundintegerNumber of OFAC matches
  .matches[]arrayArray of match objects (see below)
leadership_screeningobjectForm 990 officers/directors screened against OFAC individuals
  .people_data_tax_yearinteger | nullTax year of the Form 990 people data used for screening (e.g., 2023). Null if no people data found.
  .people_checkedintegerNumber of people screened from Form 990
  .people_screened[]arrayList of officers/directors/key employees screened, each with name and title
    .namestringPerson's name as reported on Form 990
    .titlestringPerson's title/role (e.g., "EXECUTIVE DIRECTOR", "BOARD PRESIDENT")
  .matches_foundintegerNumber of OFAC matches
  .matches[]arrayArray of match objects (see below)
checked_againstarray["OFAC SDN", "OFAC Consolidated"]
screened_atstringISO 8601 timestamp of screening

Match object (within matches[])

FieldTypeDescription
sourcestring"OFAC SDN" or "OFAC Consolidated"
matched_namestringName from OFAC list that matched
matched_viastring"primary_name" or "alias (a.k.a. ...)"
primary_namestringPrimary OFAC name (only present for alias matches)
similarity_scorenumberFuzzy match score (0.7–1.0). ≥0.9 = STRONG, ≥0.7 = POTENTIAL
match_strengthstring"STRONG" or "POTENTIAL"
sdn_typestringOFAC entity type ("individual", "N" for entity/org)
programstringOFAC sanctions program (e.g., "SDGT", "IRAN")
entry_idintegerOFAC entry number
remarksstringOFAC remarks — often contains date of birth, nationality, passport numbers, and other identifying information. Key for false positive disambiguation.
addressesarrayKnown addresses for this OFAC entry. Each has address, city_state_zip, and country fields.

Verification Statuses

StatusDeductibleMeaning
ELIGIBLEtrueListed in IRS Pub 78 (directly or via group exemption for 501(c)(3) subordinates). Eligible for tax-deductible donations.
NOT_DEDUCTIBLEfalseIn IRS records but not tax-deductible (e.g., 501(c)(4), 501(c)(6)).
REVOKEDfalseTax-exempt status auto-revoked by the IRS for non-filing. May appear even if the organization has dropped off the Business Master File.
CAUTIONnullFederally eligible but flagged for review. Possible reasons: (1) In IRS master file as 501(c)(3) but not yet in Pub 78, or (2) California state compliance issue — the organization is delinquent, revoked, or suspended with the CA Attorney General or Franchise Tax Board. Check the message and state_compliance fields for specifics.
NOT_FOUNDnullNot in IRS records and not on the revocation list. Churches and self-declared orgs may not appear.

Sanctions Screening

Every verification includes an automated OFAC screening of the organization name and its leadership (officers, directors, key employees from Form 990). Matches are checked against both SDN and Consolidated lists, including primary names and aliases.

Overall status

StatusMeaning
CLEARNo OFAC matches found for the organization or its leadership.
POTENTIAL_MATCHFuzzy match with 70–89% similarity. Manual review recommended.
STRONG_MATCHFuzzy match with 90%+ similarity. Very likely the same entity.
NOT_SCREENEDOFAC screening was not performed (e.g., organization not found in IRS database). See the reason field for details.

Disambiguation fields

When matches are found, each match object includes remarks and addresses to help you distinguish true positives from false positives:

  • remarks — OFAC remarks field containing date of birth, nationality, passport numbers, and other identifying information
  • addresses — known addresses for the matched OFAC entry (street, city/state/zip, country)

Example match object

{
  "source": "OFAC SDN",
  "matched_name": "SMITH, John A.",
  "matched_via": "primary_name",
  "similarity_score": 0.912,
  "match_strength": "STRONG",
  "sdn_type": "individual",
  "program": "SDGT",
  "entry_id": 12345,
  "remarks": "DOB 15 Mar 1970; nationality Iran; Passport A1234567",
  "addresses": [
    {
      "address": "123 Example St",
      "city_state_zip": "Tehran",
      "country": "Iran"
    }
  ]
}

In this example, a board member named "John Smith" matched an OFAC entry — but the remarks show an Iranian DOB/passport, and the addresses show Tehran. If your board member is based in Ohio with a different DOB, this is a false positive you can confidently dismiss.

California Compliance

California AB 488 requires fundraising platforms to verify that nonprofits are in good standing with three authorities before facilitating donations involving a California donor or a California-based nonprofit:

  1. IRS — federal tax-exempt status (always checked)
  2. CA Attorney General — Registry of Charitable Trusts registration status
  3. CA Franchise Tax Board — state tax-exempt status (revocation check)

The API automatically runs California checks when the nonprofit is based in CA (per IRS records) or when you provide donor_state=CA. You can also provide ca_entity_id to trigger checks directly.

When do CA checks run?

Nonprofit Statedonor_stateCA Checks?
CA(blank)Yes — nonprofit is CA-based
Non-CA(blank)No
AnyCAYes — donor is in CA
AnyNon-CAOnly if nonprofit is CA-based
AnyAnyYes — if ca_entity_id is provided

Lookup cascade

The API uses a three-tier lookup to maximize coverage across the CA AG Registry (556K records):

  1. ca_entity_id — direct SOS/FTB# lookup (97% of AG records have this)
  2. FEIN — federal EIN match (covers ~58% of AG records)
  3. Name + city — fuzzy match fallback using trigram similarity (≥0.65 threshold with city filter, ≥0.80 without)

The match_method field in the response tells you which tier was used: ca_entity_id, fein, or name_match.

state_compliance.california object

FieldTypeDescription
triggerstringWhy CA checks ran: nonprofit_based_in_ca, donor_state_ca, or ca_entity_id_provided
ag_registryobjectCA Attorney General Registry result
  .statusstringREGISTERED, EXEMPT, DELINQUENT, REVOKED, SUSPENDED, CLOSED, NOT_REGISTERED, NON_COMPLIANT, or NOT_FOUND
  .registry_statusstringRaw status from CA AG (e.g., "Current", "Delinquent", "Exempt - Religious")
  .reg_numberstringState charity registration number (e.g., CT0252232)
  .match_methodstringca_entity_id, fein, or name_match
  .matched_namestringPresent for name_match — the CA AG name that matched
  .name_similaritynumberPresent for name_match — similarity score (0.65–1.0)
ftbobjectCA Franchise Tax Board revocation result
  .statusstringCLEAR or REVOKED
  .revocation_datestringDate of FTB revocation (if revoked)
state_statusstringRoll-up: COMPLIANT, NON_COMPLIANT, REVOKED, or UNKNOWN

Impact on overall status

AG RegistryFTBstate_statusOverall status
REGISTERED / EXEMPTCLEARCOMPLIANTNo change
DELINQUENT / REVOKED / SUSPENDEDCLEARNON_COMPLIANTELIGIBLE → CAUTION
AnyREVOKEDREVOKEDELIGIBLE → CAUTION
NOT_FOUNDCLEARUNKNOWNNo change

Note: UNKNOWN (organization not found in CA AG) does not penalize the overall status. This may indicate the organization is exempt from CA registration (churches, schools, hospitals, or organizations receiving under $25,000 annually).

Example response

{
  "status": "CAUTION",
  "message": "This organization is listed in IRS Publication 78 ... However, California state compliance checks indicate that the organization's California Attorney General registration status is 'Delinquent'. Under California AB 488, fundraising platforms must verify state-level good standing before facilitating donations.",
  "state_compliance": {
    "california": {
      "trigger": "nonprofit_based_in_ca",
      "ag_registry": {
        "status": "DELINQUENT",
        "registry_status": "Delinquent",
        "reg_number": "CT0252232",
        "last_renewal_date": "2018-05-01",
        "date_status_set": "2020-02-21",
        "match_method": "fein"
      },
      "ftb": {
        "status": "CLEAR"
      },
      "state_status": "NON_COMPLIANT"
    }
  }
}

Rate Limits

Rate limits are applied per API key based on your plan tier.

PlanRequests / dayBurstRate
Free52/sec1/sec
Basic1,00010/sec5/sec
Pro10,00050/sec25/sec

When you exceed your rate limit, the API returns 429 Too Many Requests. The response includes a Retry-After header indicating when you can retry.

Playground

Test the API directly from your browser. Enter your API key and an EIN to see a live response.

Try it now


                    

Bulk Verify API

Verify hundreds or thousands of EINs in a single async request. Same 5-step verification, delivered at scale.

Overview

The Bulk Verify API accepts up to 250 EINs (semicolon-separated) or 20,000 EINs (CSV upload), processes them asynchronously via background workers, and delivers results via polling endpoint, webhook callback, or CSV download.

Each EIN goes through the same verification as the single Verify endpoint — IRS data cross-referencing, group exemption resolution, and OFAC sanctions screening.

How it works

  1. Submit — POST your EINs to /v1/bulk-verify. Get back a job_id immediately (202 Accepted).
  2. Process — EINs are split into batches of 10 and verified in parallel by background workers.
  3. Retrieve — Poll GET /v1/bulk-verify/{job_id} for progress and results, or receive a webhook callback on completion.
Input MethodMax EINsFormat
JSON body (semicolon-separated)250application/json
CSV file upload20,000multipart/form-data
BASE URL   https://api.givalgo.ai/v1

Authentication

All API requests require an API key passed in the x-api-key header — the same key used for the single Verify endpoint.

# Include your key in every request
curl -X POST "https://api.givalgo.ai/v1/bulk-verify" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"eins": "13-1837418;53-0196605"}'

To get an API key, contact support@givalgo.ai. Keys are scoped to a usage plan (Free, Basic, or Pro) which determines your rate limits and max EINs per job.

Job ownership: Jobs are scoped to your API key. You can only view the status and results of jobs you created.

Quickstart

Submit a bulk job and poll for results in under a minute.

cURL — Submit + Poll

# 1. Submit a bulk job
curl -X POST "https://api.givalgo.ai/v1/bulk-verify" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "eins": "13-1837418;53-0196605;06-0646973",
    "format": "both"
  }'

# Response: {"job_id": "bulk_abc123", "status": "PROCESSING", ...}

# 2. Poll for results
curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/bulk-verify/bulk_abc123"

Python

import requests, time

# Submit bulk job
resp = requests.post(
    "https://api.givalgo.ai/v1/bulk-verify",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "eins": "13-1837418;53-0196605;06-0646973",
        "format": "both"
    }
)
job = resp.json()
job_id = job["job_id"]

# Poll until complete
while True:
    status = requests.get(
        f"https://api.givalgo.ai/v1/bulk-verify/{job_id}",
        headers={"x-api-key": "YOUR_API_KEY"}
    ).json()
    if status["status"] == "COMPLETED":
        print(f"Done! {status['summary']}")
        break
    time.sleep(2)

JavaScript

// Submit bulk job
const resp = await fetch("https://api.givalgo.ai/v1/bulk-verify", {
  method: "POST",
  headers: {
    "x-api-key": "YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    eins: "13-1837418;53-0196605;06-0646973",
    format: "both"
  })
});
const { job_id } = await resp.json();

// Poll until complete
const poll = async () => {
  const res = await fetch(
    `https://api.givalgo.ai/v1/bulk-verify/${job_id}`,
    { headers: { "x-api-key": "YOUR_API_KEY" } }
  );
  const data = await res.json();
  if (data.status === "COMPLETED") return data;
  await new Promise(r => setTimeout(r, 2000));
  return poll();
};
const results = await poll();

Submit Bulk Job

POST   /v1/bulk-verify

Submit EINs for bulk verification. Returns 202 Accepted with a job_id for tracking.

JSON body (semicolon-separated EINs)

curl -X POST "https://api.givalgo.ai/v1/bulk-verify" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "eins": "13-1837418;53-0196605;06-0646973",
    "webhook_url": "https://your-server.com/hook",
    "format": "both"
  }'

CSV file upload

curl -X POST "https://api.givalgo.ai/v1/bulk-verify" \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@organizations.csv" \
  -F "webhook_url=https://your-server.com/hook"

CSV must have an ein column header (case-insensitive). Falls back to the first column if no header match.

Request body fields

FieldTypeRequiredDescription
einsstringYes*Semicolon-separated EINs. *Not needed for CSV upload.
webhook_urlstringNoURL to POST results to on job completion.
formatstringNoResult format: "json", "csv", or "both" (default).

Query parameters

ParameterTypeDefaultDescription
skip_invalidbooleanfalseIf true, skip invalid EINs and process only valid ones. If false, return a 400 error listing all invalid EINs.

Response (202 Accepted)

{
  "job_id": "bulk_a1b2c3d4e5f6",
  "status": "PROCESSING",
  "total_eins": 247,
  "duplicates_removed": 3,
  "estimated_seconds": 8,
  "poll_url": "/v1/bulk-verify/bulk_a1b2c3d4e5f6",
  "created_at": "2026-03-25T14:30:00Z"
}

Validation error (400)

If any EINs fail validation (and skip_invalid is not set), you get a 400 with details:

{
  "error": "VALIDATION_ERROR",
  "message": "3 EINs failed validation",
  "invalid_eins": [
    { "ein": "123", "error": "EIN must be exactly 9 digits" }
  ],
  "valid_count": 247,
  "hint": "Add ?skip_invalid=true to process only valid EINs."
}

Poll Job Status

GET   /v1/bulk-verify/{job_id}

Check the progress and retrieve results of a bulk verification job. Jobs are scoped to your API key — you can only access jobs you created.

In progress

{
  "job_id": "bulk_a1b2c3d4e5f6",
  "status": "PROCESSING",
  "progress": {
    "total": 247,
    "completed": 180,
    "failed": 2,
    "percent_complete": 73.7
  }
}

Completed

For jobs with 1,000 or fewer EINs, results are included inline. Larger jobs return a csv_download_url only. Each result in the array is a full single-verify response — identical to what you'd get from the /v1/verify endpoint, including organization details, Pub78, revocation history, and OFAC sanctions screening.

{
  "job_id": "bulk_a1b2c3d4e5f6",
  "status": "COMPLETED",
  "summary": {
    "eligible": 200,
    "not_deductible": 30,
    "revoked": 5,
    "not_found": 8,
    "ofac_flags": 3
  },
  "results": [
    {
      "ein": "13-1837418",
      "ein_raw": "131837418",
      "status": "ELIGIBLE",
      "deductible": true,
      "message": "Organization is eligible to receive tax-deductible donations.",
      "organization": { /* full org details: name, city, state, NTEE, assets, ... */ },
      "pub78": { /* listed, deductibility_code, description */ },
      "revocation": { /* ever_revoked, currently_revoked, dates */ },
      "sanctions_screening": { /* status, org & leadership screening, matches */ },
      "checked_at": "2026-03-25T23:11:10Z",
      "api_version": "v1"
    },
    // ... one entry per EIN, same structure as single /v1/verify response
  ],
  "csv_download_url": "https://...presigned...",
  "completed_at": "2026-03-25T14:30:07Z"
}

CSV download

The csv_download_url (pre-signed S3 URL, valid 1 hour) contains a flattened version of the full results with 37 columns covering organization details, Pub78 status, revocation history, and OFAC screening. Column headers:

ein, status, deductible, message,
org_name, org_city, org_state, subsection_code, subsection_label,
deductibility_code, deductibility_label, foundation_code, foundation_label,
status_code, status_label, affiliation_code, affiliation_label,
group_exemption_number, ruling_date, ntee_code,
asset_amount, income_amount, revenue_amount,
pub78_listed, pub78_deductibility_code, pub78_deductibility_description,
pub78_via_group_exemption,
ever_revoked, currently_revoked, revocation_date, revocation_posting_date,
reinstatement_date,
sanctions_status, ofac_org_matches_found, ofac_leadership_matches_found,
screened_at, error_message, checked_at

Job statuses

StatusMeaning
PROCESSINGJob is actively being processed by background workers.
COMPLETEDAll EINs have been verified. Results are available.

Webhooks

If you provide a webhook_url when submitting a bulk job, we'll POST a notification when the job completes. This is the recommended approach for large jobs instead of polling.

Webhook payload

# POST to your webhook_url
# Headers:
#   Content-Type: application/json
#   User-Agent: Givalgo-Webhook/1.0
#   X-Givalgo-Event: bulk_verify.completed
#   X-Givalgo-Job-Id: bulk_a1b2c3d4e5f6

{
  "event": "bulk_verify.completed",
  "job_id": "bulk_a1b2c3d4e5f6",
  "status": "COMPLETED",
  "total_eins": 247,
  "completed": 245,
  "failed": 2,
  "summary": {
    "eligible": 200,
    "not_deductible": 30,
    "ofac_flags": 3
  },
  "csv_download_url": "https://...presigned-url...24hr-expiry...",
  "poll_url": "/v1/bulk-verify/bulk_a1b2c3d4e5f6"
}

Retry policy

Webhook delivery is attempted up to 3 times with exponential backoff (1s, 5s delays). If your endpoint returns a 2xx status, delivery is marked as successful. The csv_download_url is a pre-signed S3 URL valid for 24 hours.

Throughput

EINsEstimated Time
10~5 seconds
50~15 seconds
250~30 seconds
1,000~2 minutes
20,000~40 minutes

Job Statuses

A bulk job progresses through these statuses:

StatusMeaning
PROCESSINGJob is queued and actively being processed by background workers. Poll for progress updates.
COMPLETEDAll EINs have been verified. Results are available inline (for jobs ≤ 1,000 EINs) and via CSV download URL.

Verification Statuses

Each EIN in a bulk job receives the same verification statuses as the single Verify endpoint:

StatusDeductibleMeaning
ELIGIBLEtrueListed in IRS Pub 78 (directly or via group exemption). Eligible for tax-deductible donations.
NOT_DEDUCTIBLEfalseIn IRS records but not tax-deductible (e.g., 501(c)(4), 501(c)(6)).
REVOKEDfalseTax-exempt status auto-revoked by the IRS for non-filing. May appear even if the organization has dropped off the Business Master File.
CAUTIONnullIn IRS master file as 501(c)(3) but NOT in Pub 78. May be a data timing lag — verify via the IRS Tax Exempt Organization Search.
NOT_FOUNDnullNot in IRS records and not on the revocation list. Churches and self-declared orgs may not appear.

Limits & Throughput

Bulk job limits are applied per API key based on your plan tier.

LimitValue
Max EINs (JSON body)250
Max EINs (CSV upload)20,000
Max concurrent jobs5 per API key
Result retention30 days
CSV download URL expiry24 hours

Estimated processing times

EINsEstimated Time
10~5 seconds
50~15 seconds
250~30 seconds
1,000~2 minutes
20,000~40 minutes

Processing time depends on current load and Lambda warm-start state. For time-sensitive workloads, use a webhook for instant notification on completion.

Report API

Generate professional, branded PDF verification reports for any U.S. nonprofit — ready to share with donors, board members, or compliance teams.

Overview

The Report API takes an EIN and returns a multi-page PDF document containing the same verification data as the Verify endpoint — presented in a polished, print-ready format with Givalgo branding.

Each report includes a cover page, verification outcome with status badge, IRS data breakdown, OFAC sanctions screening results, financial snapshot, and a branded back page.

GET   /v1/report?ein={ein}  →  application/pdf

Authentication

The Report API uses the same API key authentication as the Verify and Bulk Verify endpoints. Include your key in the x-api-key header:

curl -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/pdf" \
  "https://api.givalgo.ai/v1/report?ein=13-1837418" \
  -o report.pdf

Quickstart

Generate your first PDF report in seconds:

# Download a verification report for Candid (EIN 13-1837418)
curl -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/pdf" \
  "https://api.givalgo.ai/v1/report?ein=13-1837418" \
  -o candid-verification.pdf

# Open the PDF
open candid-verification.pdf

Tip: Include the Accept: application/pdf header to receive decoded binary PDF. In Postman, use Send and Download (dropdown next to Send) to save the file.

Report Endpoint

GET   /v1/report?ein={ein}

Takes an EIN and returns a professionally formatted PDF verification report. The underlying data is identical to the /v1/verify endpoint — the Report API simply renders it into a branded, multi-page PDF document.

Parameters

ParameterTypeRequiredDescription
einstringYesEmployer Identification Number. Accepts 13-1837418, 131837418, or 13 1837418.

Headers

HeaderRequiredDescription
x-api-keyYesYour API key
AcceptRecommendedSet to application/pdf for decoded binary response

Success Response

PropertyValue
Status Code200 OK
Content-Typeapplication/pdf
Content-Dispositioninline; filename="npo-verify-{ein}.pdf"

Error Responses

Error responses are returned as JSON (not PDF):

StatusError CodeDescription
400MISSING_EINThe ein query parameter was not provided
400INVALID_EINEIN format is invalid (not 9 digits)
403ForbiddenMissing or invalid API key
500INTERNAL_ERRORServer-side error during PDF generation

Note: All valid verification statuses (ELIGIBLE, REVOKED, NOT_FOUND, CAUTION, NOT_DEDUCTIBLE) return a 200 with a PDF. Only auth or input errors return JSON.

Report Sections

Each generated PDF contains the following pages:

PageSectionContent
1Cover PageGivalgo branding, organization name, EIN, report generation date
2Outcome & DetailsLarge status badge (color-coded), deductibility verdict, organization details (city, state, subsection, NTEE code, ruling date)
3IRS Status BreakdownEO BMF status & deductibility, Pub 78 listing, group exemption details, revocation history with dates
4OFAC ScreeningOrganization & leadership sanctions screening status, match details (if any), data source year
5Financial SnapshotTotal assets, annual income, annual revenue (from IRS BMF data)
6Back PageDisclaimer, API version, generation timestamp, contact info

Verification Statuses

The report displays the same verification statuses as the Verify endpoint, rendered as color-coded badges:

StatusBadge ColorDeductibleMeaning
ELIGIBLE● GreenYesListed in IRS Pub 78. Eligible for tax-deductible donations.
NOT_DEDUCTIBLE● OrangeNoIn IRS records but not tax-deductible.
REVOKED● RedNoTax-exempt status auto-revoked by the IRS.
CAUTION● YellowUnconfirmedIn IRS master file as 501(c)(3) but not in Pub 78.
NOT_FOUND● GrayUnknownNot in IRS records. Churches and self-declared orgs may not appear.

Important Notes

Response Time

PDF generation typically takes 2–4 seconds (cold start may add 3–5 seconds on first request). The API Gateway timeout is 29 seconds.

Data Source

Reports contain the same data as the /v1/verify endpoint. The PDF is generated on-the-fly from live verification data — it is not cached. Each request produces a fresh report with the current timestamp.

File Size

Reports are typically 115–130 KB depending on the amount of data (e.g., OFAC matches increase size slightly).

Disclaimer

Each report includes a footer disclaimer: "This report is generated from publicly available IRS data and OFAC sanctions lists. It does not constitute legal or tax advice."

Form 990 Data API

Structured access to every meaningful number, ratio, and peer benchmark from U.S. nonprofit Form 990 filings — for 3.3M+ filings covering 1.9M+ unique organizations.

Overview

The Form 990 Data API turns raw IRS e-file XML into a clean JSON response covering financials, compensation, programs, governance, fundraising, liquidity, expense composition, related organizations, foreign activity, and more. Every core ratio is benchmarked against peer cohorts (NTEE major group × revenue band × state), so you see not just the number but where it sits in its sector.

Two tiers share the same endpoint family:

  • /v1/data Base — ~150 fields, all core sections, all peer benchmarks
  • /v1/data-pro Pro — base + three deep-detail attachments (~410 fields total)
BASE URL   https://api.givalgo.ai/v1

Tiers: Data vs Data Pro

Tier is determined entirely by the endpoint path — there is no public include= parameter. Both tiers accept the same query parameters (ein, tax_year) and require the same x-api-key header.

Section/v1/data Base/v1/data-pro Pro
organization — identity, NTEE, mission
financials — revenue, expenses, balance sheet
trends — 6-year annual series + CAGR + trend labels
compensation — officers, by_role, peer benchmarks
funding_sources — grantmakers received from
programs — program descriptions + expenses
governance — board + policies
fundraising — events, professional fundraisers
financial_profile — liquidity, HHI, expense composition New
related_organizations
foreign_activities, lobbying_and_political, donor_advised_funds
data_freshness
financials_detail — full Schedule A-D line items Pro
governance_detail — full board roster, policies, minutes
registration — Schedule R + B + state-level filings

New indicates fields added in the April 2026 release.

Authentication

All requests require an API key passed in the x-api-key header. Keys are scoped to a usage plan (Free, Base, Pro) which determines rate limits and tier access.

# Base tier
curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/data?ein=53-0196605"

# Pro tier
curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/data-pro?ein=53-0196605"

To upgrade to Pro or request a trial key, contact support@givalgo.ai.

Quickstart

cURL — most recent filing

curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/data?ein=53-0196605"

cURL — specific tax year

curl -H "x-api-key: YOUR_API_KEY" \
  "https://api.givalgo.ai/v1/data?ein=53-0196605&tax_year=2022"

Python

import requests

r = requests.get(
    "https://api.givalgo.ai/v1/data-pro",
    params={"ein": "53-0196605"},
    headers={"x-api-key": "YOUR_API_KEY"},
)
data = r.json()

name = data["organization"]["name"]
prog_pct = data["financial_profile"]["expense_composition"]["program_expense_ratio"]
peer_median = data["financial_profile"]["expense_composition"] \
    ["peer_benchmarks_by_metric"]["program_expense_ratio"] \
    ["by_ntee_and_revenue_band_and_state"]["median"]

print(f"{name}: program = {prog_pct:.0%}, peer median = {peer_median:.0%}")

JavaScript

const r = await fetch(
  "https://api.givalgo.ai/v1/data?ein=53-0196605",
  { headers: { "x-api-key": "YOUR_API_KEY" } }
);
const data = await r.json();
console.log(data.organization.name, data.trends.computed.revenue_trend);

Endpoints

GET   /v1/data?ein={ein}&tax_year={year}   Base

Returns base sections (~150 fields): organization, financials, trends, compensation, funding_sources, programs, governance, fundraising, financial_profile, related_organizations, foreign_activities, lobbying_and_political, contributor_summary, donor_advised_funds, data_freshness.

GET   /v1/data-pro?ein={ein}&tax_year={year}   Pro

Returns the base shape plus three detail attachments (~410 fields total): financials_detail, governance_detail, registration.

Parameters

ParameterTypeRequiredDescription
einstringYesEmployer Identification Number. Accepts 53-0196605, 530196605, or 53 0196605.
tax_yearintegerNo4-digit fiscal year (e.g. 2022). Omit to get the most recent filing. If the requested year has no filing, the response is a 404 with a years_available array.

Response Top-Level

FieldTypeDescription
einstringHyphenated EIN (e.g. "53-0196605").
tax_yearintegerFiscal year of the filing returned.
return_typestring"990", "990EZ", or "990PF".
filing_datestring (ISO date)Date IRS received the filing.
organizationobjectIdentity, address, NTEE code, mission, formation year, total employees/volunteers.
financialsobjectSummary, revenue breakdown, expenses, balance sheet, and (Pro only) detail sub-object.
trendsobjectUp to 6 years of annual data + computed CAGRs + trend labels.
compensationobjectPeople array, by-role highlights, per-employee average, peer benchmark cubes.
funding_sourcesobjectGrants received: grantmakers[], annual totals.
programsobjectProgram service accomplishments + grants made (recipients[]).
governanceobjectBoard structure, policies, meeting minutes flags.
fundraisingobjectEvents, professional fundraisers, state filings.
financial_profileobjectLiquidity, revenue concentration (HHI), operating sustainability, expense composition New. All with peer benchmarks.
related_organizationsobjectSchedule R-style related entities.
foreign_activitiesobjectSchedule F summary.
lobbying_and_politicalobjectSchedule C summary.
contributor_summaryobjectSchedule B contributor aggregates.
donor_advised_fundsobjectDAF flags + balances (if Schedule D.I present).
registration ProobjectRegistration and state-level filings detail.
data_freshnessobjectFiling source, most_recent_tax_year, last_filing_date, years_available[].

organization

FieldTypeDescription
namestringLegal name on the filing.
also_known_asstring | nullDBA, if present.
address, city, state, zipstringMailing address.
phone, websitestring | nullContact info.
formation_yearintegerYear of formation.
missionstringMission statement text.
principal_officerstring | nullName of principal officer from Form 990 header.
ntee_codestringFull NTEE code (e.g. "P210").
ntee_descriptionstringHuman-readable NTEE major group (e.g. "Human Services").
ruling_yearinteger | nullYear IRS granted tax-exempt status.
total_employees, total_volunteersintegerAs reported on the filing.

financials

FieldTypeDescription
summaryobjecttotal_revenue, total_expenses, revenue_less_expenses, total_assets_eoy, total_liabilities_eoy, net_assets_eoy.
revenueobjectcontributions_and_grants, program_service_revenue, investment_income, other_revenue, total.
expensesobjectprogram_services, management_and_general, fundraising, total, and allocation (program_pct, fundraising_pct).
balance_sheetobjectCash, investments, PP&E, assets, liabilities, net assets (with unrestricted split).
detail Proobject | nullFull Part VIII / Part IX / Schedule D line-by-line breakdown. null on base tier.

compensation

Top-level scalars are drawn from Form 990 Part VII (officers, key employees, highest-paid) and Part IX (salaries & benefits aggregate).

Top-level fields

FieldTypeDescription
tax_yearintegerFiscal year this compensation data belongs to.
people_countintegerNumber of people in the people[] array.
people[]object[]Array of Part VII persons with name, title, hours_per_week, is_officer, is_key_employee, is_director, is_highest_paid, reportable_comp_org, reportable_comp_related, other_compensation, total_compensation.
highest_paid_personstringName of the highest-paid person in the list.
highest_compensationintegerDollar amount.
comp_to_expense_pctnumberSum of Part VII compensation ÷ total expenses, as a percent.
top_officer_comp_to_revenue_pct NewnumberTop officer total comp ÷ total revenue, as a percent. Scale-normalized so small and large orgs can be compared fairly.
avg_compensation_per_employee NewintegerWhole-org payroll ÷ total employees, in dollars. Sourced from Form 990 Part IX Lines 5-10 (salaries + benefits + pension + payroll tax). Populated for ~29% of filings where both fields are non-zero.

by_role New

Highest-paid person whose title matches common patterns for each role. null per role if no match.

FieldTypeDescription
by_role.ceoobject | null{title, total_compensation}. Matches titles like Executive Director, Chief Executive, President, CEO.
by_role.cfoobject | nullMatches titles like Chief Financial Officer, CFO, Treasurer, Director of Finance, VP Finance.
by_role.development_directorobject | nullMatches Chief Development Officer, Development Director, VP Development, Chief Advancement Officer.

peer_benchmarks_by_metric New

One cube per metric — see How Cubes Work. Metrics with no peer data (e.g. small revenue bands) are omitted.

  • top_officer_comp — absolute top-officer dollar amounts
  • top_officer_comp_to_revenue_pct — scale-normalized
  • ceo_comp, cfo_comp, dev_director_comp — role-specific benchmarks
  • avg_compensation_per_employee — whole-org payroll per FTE

The legacy key peer_benchmarks (top-level, not nested) remains for backwards compatibility and mirrors peer_benchmarks_by_metric.top_officer_comp.

funding_sources

Aggregated from Schedule I of grantmakers that reported this EIN as a grant recipient.

FieldTypeDescription
grantmakers[]object[]Up to 50 most recent grantmakers: grantmaker_ein, grantmaker_name, grants_count, total_awarded, most_recent_year, most_recent_amount, purpose_summary.
annual[]object[]Per-year: tax_year, total_received, unique_grantmakers.

programs & grants

FieldTypeDescription
programs[]object[]Program service accomplishments: name, description, expenses, revenue, grants_made.
grants_made.recipients[]object[]Schedule I recipients: recipient_ein, recipient_name, amount, purpose, tax_year.
grants_made.summaryobjectTotal amount, unique recipient count, top destination type.

governance

FieldTypeDescription
voting_board_membersintegerTotal voting members.
independent_board_pctnumberPercent independent.
has_conflict_of_interest_policybooleanPart VI Line 12.
has_whistleblower_policy, has_document_retention_policybooleanPart VI Lines 13-14.
detail Proobject | nullFull board roster + minutes-kept flags + compensation review process. null on base tier.

fundraising

FieldTypeDescription
professional_fundraisers[]object[]Schedule G Part I: name, activity, gross_receipts, amount_to_org.
events[]object[]Schedule G Part II: event_name, gross_revenue, contributions, gross_income, direct_expenses, net_income.
state_filingsobjectStates where fundraising is registered (from Schedule G).

financial_profile

Our headline analytics section — every ratio here comes with a peer benchmark cube.

liquidity

FieldTypeDescription
months_of_cashnumberCash & savings ÷ monthly expenses.
months_of_liquid_assetsnumberCash + savings + publicly traded investments, over monthly expenses.
operating_reserve_months NewnumberUnrestricted net assets ÷ monthly expenses. The standard donor-facing operating-reserve figure.
peer_benchmarksobjectLegacy: 7-cut cube for months_of_cash.
peer_benchmarks_by_metric NewobjectCubes for months_of_cash and operating_reserve_months.

revenue_concentration

FieldTypeDescription
herfindahl_indexnumberHHI computed across 5 revenue buckets (contributions, program service, investment, fundraising events, other). Lower = more diversified.
diversification_levelstringDIVERSIFIED (HHI < 0.30), MODERATE (0.30–0.55), or CONCENTRATED (≥ 0.55). Thresholds rebased April 2026 to match the real HHI floor of 0.20 (5 equal buckets).
diversification_description NewstringPlain-English explanation of the bucket.
index_range Newobject{min: 0.20, max: 1.00, buckets: 5, note: ...} — so consumers know how to interpret the scalar.

operating_sustainability

FieldTypeDescription
operating_margin_pctnumber(Revenue − expenses) ÷ |revenue|, percent.
operating_reserve_monthsnumberSame as liquidity.
peer_benchmarks_by_metric NewobjectCubes for both metrics.

expense_composition New

Two views of where the dollars go — the functional split Charity Navigator uses, plus the FASB-required natural-category split from Form 990 Part IX.

Functional view (program / admin / fundraising)

FieldTypeDescription
program_expense_rationumberProgram services ÷ total expenses × 100. The traditional "how much goes to mission" ratio.
admin_expense_rationumberManagement & general ÷ total expenses × 100.
fundraising_expense_rationumberFundraising ÷ total expenses × 100.
cost_to_raise_a_dollarnumberFundraising expense ÷ contributions. Lower is more efficient.
comp_to_expense_pctnumberTop-N compensation as percent of total expenses.

Natural view (FTA — Part IX line items) New

FieldTypeDescription
salaries_benefits_rationumberPart IX lines 5–10 ÷ total expenses × 100. Labor intensity — service-delivery orgs run 60–80%; grant-makers much lower.
professional_fees_rationumberPart IX lines 11a–11g ÷ total expenses × 100. High values can flag heavy consultant / outside-fundraiser reliance.
occupancy_rationumberPart IX line 16 ÷ total expenses × 100. Real-estate-heavy orgs (museums, hospitals) run higher.
travel_rationumberPart IX line 17 ÷ total expenses × 100.
grants_paid_rationumberPart IX lines 1–3 ÷ total expenses × 100. Grant-making foundations run very high; direct-service orgs near zero.
salaries_benefits · professional_fees · occupancy · travel · grants_paidintegerRaw Part IX dollar amounts — for callers that want their own cut (e.g. $/employee, $/beneficiary).
peer_benchmarks_by_metricobjectPercentile cubes for the functional ratios + the two most universally benchmarkable FTA ratios (salaries_benefits_ratio, professional_fees_ratio). Occupancy / travel / grants_paid vary too much by org type to percentile meaningfully.

Note: absolute third-party thresholds (Charity Navigator's 70% program benchmark, BBB Wise Giving's 65%, etc.) are deliberately NOT returned. Peer percentiles already place the org in its cohort, and absolute thresholds often penalize nonprofits for legitimate sector differences.

related_organizations / foreign_activities / lobbying / DAFs

SectionSourceDescription
related_organizationsSchedule RDisregarded entities, related tax-exempt orgs, related taxable partnerships/corps. Counts + optionally names (Pro).
foreign_activitiesSchedule FRegions, activity types, revenue & expenditures abroad, foreign grants.
lobbying_and_politicalSchedule CLobbying expenditures (direct & grassroots), 501(h) election, political campaign expenditures.
contributor_summarySchedule BAggregate contributor counts + total contributions. Individual contributor names are never returned (IRS redaction).
donor_advised_fundsSchedule D.IFunds held, aggregate balance, contributions during year.

data_freshness

FieldTypeDescription
filing_sourcestringAlways "IRS TEOS e-file".
most_recent_tax_yearintegerLatest filing year ingested for this EIN.
filing_datestringFiling date of the response year.
last_filing_datestringMost recent filing date for this EIN overall.
years_availableinteger[]All tax years on file.
includes_appliedstring[]Diagnostic — which internal bundles applied to this response (empty on base).

Peer Benchmarks: How Cubes Work

Every ratio in compensation.peer_benchmarks_by_metric and financial_profile.*.peer_benchmarks_by_metric returns a cube: the same metric sliced across seven peer-group dimensions, each with the same six percentile stats.

Shape of a single cube

{
  "by_ntee":                          { ...PeerStats },
  "by_revenue_band":                  { ...PeerStats },
  "by_state":                         { ...PeerStats },
  "by_ntee_and_revenue_band":         { ...PeerStats },
  "by_ntee_and_state":                { ...PeerStats },
  "by_revenue_band_and_state":        { ...PeerStats },
  "by_ntee_and_revenue_band_and_state": { ...PeerStats }
}

PeerStats

FieldTypeDescription
peer_groupstringHuman label, e.g. "P – Human Services ∩ $100M+ ∩ DC".
peer_countintegerNumber of orgs in the cohort for that tax year.
p10, p25, median, p75, p90, meannumberDistribution statistics for the metric in that cohort.
notestring (optional)Appears when peer_count < 10: "Small peer group — interpret with caution".

Peer Benchmarks: 7 Dimensional Cuts

Each cube is the same metric sliced seven ways. The intersection cuts (triple) are the narrowest and usually most meaningful, but may have small cohorts.

NTEE major group

A–Z first letter of the IRS National Taxonomy of Exempt Entities code. Examples: A Arts & Culture, B Education, E Health, P Human Services.

Revenue band

Eight bands based on total revenue: 1 <$100K, 2 <$500K, 3 <$1M, 4 <$5M, 5 <$10M, 6 <$50M, 7 <$100M, 8 $100M+.

State

Two-letter state code from the organization's mailing address.

Intersections

4 compound cuts: ntee ∩ revenue_band, ntee ∩ state, revenue_band ∩ state, and the triple ntee ∩ revenue_band ∩ state.

Peer Benchmarks: Metrics Covered

17 metrics currently ship with peer-benchmark cubes. New metrics are added as underlying data coverage grows.

MetricSurfaced at
total_revenue(internal reference)
top_officer_compcompensation.peer_benchmarks, compensation.peer_benchmarks_by_metric
top_officer_comp_to_revenue_pct Newcompensation.peer_benchmarks_by_metric
ceo_comp Newcompensation.peer_benchmarks_by_metric
cfo_comp Newcompensation.peer_benchmarks_by_metric
dev_director_comp Newcompensation.peer_benchmarks_by_metric
avg_compensation_per_employee Newcompensation.peer_benchmarks_by_metric
program_expense_ratiofinancial_profile.expense_composition.peer_benchmarks_by_metric
admin_expense_ratio Newfinancial_profile.expense_composition.peer_benchmarks_by_metric
fundraising_expense_ratio Newfinancial_profile.expense_composition.peer_benchmarks_by_metric
cost_to_raise_a_dollar Newfinancial_profile.expense_composition.peer_benchmarks_by_metric
comp_to_expense_pctfinancial_profile.expense_composition.peer_benchmarks_by_metric
salaries_benefits_ratio Newfinancial_profile.expense_composition.peer_benchmarks_by_metric
professional_fees_ratio Newfinancial_profile.expense_composition.peer_benchmarks_by_metric
months_of_cashfinancial_profile.liquidity.peer_benchmarks, financial_profile.liquidity.peer_benchmarks_by_metric
operating_reserve_months Newfinancial_profile.liquidity + operating_sustainability
operating_margin_pctfinancial_profile.operating_sustainability.peer_benchmarks_by_metric

Pro-Only Attachments Pro

Calling /v1/data-pro attaches three extra sections on top of the base shape.

financials_detail

Line-by-line Part VIII (revenue) and Part IX (expenses) breakdowns plus Schedule A (public charity status), Schedule B (contributors summary), Schedule D (supplemental financials) highlights, Schedule O (narratives).

governance_detail

Full voting-board roster with titles, committee memberships, compensation-review process, meeting-minutes flags, and policies (conflict of interest, whistleblower, document retention, joint venture, independence).

registration

State-level registration filings (where ingested), Schedule R related-organization full roster with ownership percentages, foreign registration details.

Error Codes

StatusErrorMeaning
400MISSING_EINThe ein query param is required.
400INVALID_EINEIN is not 9 digits / not parseable.
400INVALID_TAX_YEARtax_year must be a 4-digit integer.
403IP_NOT_ALLOWEDThe calling IP is not on the allowlist for this API key.
403ForbiddenMissing or invalid x-api-key header.
404NOT_FOUNDNo filing for this EIN (or not for the requested year). Response includes years_available[].
500INTERNAL_ERRORUnexpected server error. request_id included for support tickets.

Rate Limits

PlanRequests / minuteBurstTier access
Free1020Base only
Basic60120Base only
Pro300600Base + Pro
EnterpriseCustomCustomBase + Pro + bespoke attachments

When you exceed a limit, API Gateway returns 429 Too Many Requests. Back off and retry after 30 seconds. Contact support@givalgo.ai to adjust plans.