Developer documentation · Professional plan

CauseComp API & connector docs

The same nonprofit compensation engine behind the CauseComp web tools, available as a token-authenticated REST API and as a one-click Claude connector. This page takes a non-technical reader from zero to a working call.

Overview

The CauseComp API answers the same questions as the website — executive pay from IRS Form 990 Schedule J, broad-based workforce pay from U.S. Bureau of Labor Statistics data, and the §4958 comparables set — and returns an answer identical to the site's for the same inputs, because both call one shared engine.

You need the Professional plan

API and connector access is a Professional feature. Every request checks your live plan, so access follows your subscription — a downgrade or cancellation disables your credentials automatically. See plans & pricing

Base URL

All REST endpoints live under one versioned base:

https://www.causecomp.org/api/v1

Authentication

Every request carries a bearer credential in the Authorization header. Two credential types are accepted on the same header:

  • An API key — a secret that starts with cc_live_, which you mint on your account page. Use this with your own code or with Model Context Protocol clients other than Claude and ChatGPT.
  • The OAuth token from the Claude or ChatGPT connector — issued automatically when you connect CauseComp to Claude (on claude.ai or the desktop app) or to ChatGPT in developer mode. You never see or paste it; the connector's OAuth sign-in handles it. In either assistant, the connector requires a CauseComp Professional-plan account.

Either way, the header looks like this (the connector sets it for you):

Authorization: Bearer cc_live_your_key_here
New to APIs? The fastest path to a working setup is the Claude connector below — no keys to copy, no code to write.

Claude connector quickstart

The CauseComp connector works wherever you use Claude — connect it once and it follows your Claude account: claude.ai, the Claude desktop app, and Claude's integrations inside other tools where connectors are enabled. There are no API keys to copy for the one-click path — you sign in with your CauseComp account and approve access.

1

Open Connectors

In Claude, go to Settings → Connectors, click Add, then Add custom connector.

2

Fill in two fields

Name: CauseComp

Remote MCP server URL: https://mcp.causecomp.org/mcp

Leave everything under Advanced settings — OAuth Client ID and OAuth Client Secret — blank; sign-in comes next, no keys to paste. Then click Add.

3

Sign in & allow

Click Connect on the new CauseComp row, sign in with your CauseComp account, and Allow — you're benchmarking.

Once connected, ask in plain English — Claude calls CauseComp and returns the percentile figures, the data vintage, and the standard disclaimer. Full walkthrough and example prompts on the Claude connector page.

REST reference

Thirteen endpoints: five that answer a question (POST, JSON body) and eight lookups (GET, query string). All require the Authorization: Bearer header. Each successful call to one of the five counts against your account's daily quota; the lookups are not metered. revenue accepts a dollar amount ("$5,000,000" or 5000000) or a band label.

Each endpoint below lists what it accepts, what it returns and what each returned field means. Some responses carry additional diagnostic fields; they may change without notice and should not be relied on. The example responses were produced by calling the API; long lists and long text are shortened, marked with …, and a filer's mission text is described rather than printed.

POST /executive/benchmark

Executive (officer / leadership) benchmark from 990 Schedule J.

Professional plan. Each successful call counts as one call against the daily quota.

ParameterReq?Description
rolerequiredExecutive role label (resolve fuzzy input via /meta/exec_roles).
ntee_sectorrequiredNTEE sector label (see /meta/sectors).
staterequiredTwo-letter state code, e.g. CA, or US for the national benchmark with no state adjustment (see /meta/states). An unrecognized value returns a correction listing the valid codes; it is never served as the national figure.
revenuerequiredAnnual budget size (amount or band label). A band label is accepted and is treated as that band's midpoint, so a figure near a band edge will differ from the band; prefer the exact figure when the caller knows it. A revenue of 0 is answered without a modeled figure (see modelled_figure).
org_typeoptionaloptional. IRS subsection, e.g. 501(c)(3). It is not a filter: the comparison group does not narrow to that type. For 501(c)(3), 501(c)(6), 501(c)(7), 501(c)(8) and 501(c)(9) the figure is adjusted by a factor measured for that subsection. Any other value is recorded but does not change the benchmark. The response says whether the adjustment was applied.
ntee_subsectoroptionalThree-character NTEE subsector code (e.g. P20) for finer calibration.
msaoptionalMetro code (see /meta/metros).
age_to_dateoptionalOptional. Project the figures to this exact date (YYYY-MM-DD) using CauseComp's measured nonprofit pay growth, or aging_rate if supplied; omit for as-filed figures. If the date is beyond the measured table's reach, the response says which date the figures were projected to instead (money_aging_clamped).
age_to_yearoptionalOptional. Project the figures to 31 December of this calendar year - the same as age_to_date set to that day; omit for as-filed figures. Ignored when age_to_date is given.
aging_rateoptionalOptional, and only alongside age_to_year: a yearly growth rate in percent (e.g. 3.0) to use instead of the measured growth rate. The response names it as the source (money_aging_source = user-supplied).

Example request

curl https://www.causecomp.org/api/v1/executive/benchmark \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Executive Director / CEO", "ntee_sector": "Human Services", "state": "CA", "revenue": "$5,000,000"}'

Example response

{
  "benchmark": {
    "aged_from_date": null,
    "aged_from_year": null,
    "aged_to_date": null,
    "aged_to_year": null,
    "base_median": 140832,
    "base_n_disclosed": null,
    "base_p10": 82130,
    "base_p25": 105976,
    "base_p75": 189227,
    "base_p90": 263034,
    "base_pct_nonzero": null,
    "benefits_median": 6972,
    "benefits_n_disclosed": null,
    "benefits_p10": 4066,
    "benefits_p25": 5246,
    "benefits_p75": 9368,
    "benefits_p90": 13021,
    "benefits_pct_nonzero": null,
    "bonus_label": "Of nonprofit executives paid about $155,000, across all roles and sectors, 28% received a bonus. Those who …",
    "bonus_median": 2182,
    "bonus_n_disclosed": null,
    "bonus_p10": 1272,
    "bonus_p25": 1642,
    "bonus_p75": 2932,
    "bonus_p90": 4075,
    "bonus_pct_nonzero": null,
    "bonus_prevalence_pct": 28,
    "bonus_typical_pct": 4.8,
    "components_aged": false,
    "components_basis": "modelled_share",
    "components_cohort_n": null,
    "components_under_10_filings": [],
    "confidence": "High",
    "confidence_basis": "Confidence describes the depth of filing evidence for this benchmark. It is not a statistical confidence …",
    "data_vintage": "990 data",
    "filed_titles": {
      "n_distinct_titles": 8684,
      "n_filings": 113213,
      "titles": [
        {
          "n_filings": 52581,
          "title": "Executive Director"
        },
        {
          "n_filings": 13132,
          "title": "CEO"
        },
        // … 4 more
      ]
    },
    "filings_aged": false,
    "geographic_basis": "state",
    "geographic_fallback_reason": null,
    "is_bls_primary": false,
    "median": 155118,
    "method": "base (role x revenue) + location + NTEE",
    "modelled_figure": true,
    "money_aging_clamped": null,
    "money_aging_declined": null,
    "money_aging_eci_vintage": null,
    "money_aging_factor": null,
    "money_aging_rate_pct": null,
    "money_aging_refusal": null,
    "money_aging_requested_year": null,
    "money_aging_source": null,
    "n_obs": 83173,
    "no_modelled_figure_reason": null,
    "org_type_modifier_applied": false,
    "org_type_modifier_declined": null,
    "org_type_modifier_factor": null,
    "org_type_modifier_source": null,
    "other_median": 215,
    "other_n_disclosed": null,
    "other_p10": 125,
    "other_p25": 161,
    "other_p75": 288,
    "other_p90": 401,
    "other_pct_nonzero": null,
    "p10": 90462,
    "p25": 116727,
    "p50": 155118,
    "p75": 208423,
    "p90": 289717,
    "retirement_deferred_median": 3297,
    "retirement_deferred_n_disclosed": null,
    "retirement_deferred_p10": 1923,
    "retirement_deferred_p25": 2481,
    "retirement_deferred_p75": 4431,
    "retirement_deferred_p90": 6159,
    "retirement_deferred_pct_nonzero": null,
    "revenue_band": "$5M–$10M",
    "role_filings_note": null,
    "role_filings_thin": false,
    "warning": ""
  },
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "input": {
    "msa": null,
    "ntee_sector": "Human Services",
    "ntee_subsector": null,
    "org_type": null,
    "revenue_raw": "$5,000,000",
    "role": "Executive Director / CEO",
    "state": "CA"
  }
}

What comes back

FieldWhat it means
benchmarkThe figures, described in the next table.
inputYour inputs as interpreted: the canonical role, sector and state labels, and revenue_raw as you sent it.
disclaimerThe standard disclaimer, which you must surface to end users (see Disclaimer).
Inside benchmarkWhat it means
p10, p25, median, p50, p75, p90The benchmark: percentiles of total compensation for the role, in US dollars. median and p50 are the same number (see below).
confidence, confidence_basisA depth-of-evidence label, and the statement of what it means (see below).
n_obsThe number of Form 990 filings behind the confidence label; on BLS-primary roles, the number of states reporting OEWS wage data.
low_confidence, low_confidence_reasonPresent only when the cohort has 1–9 comparable filings: true, and a sentence giving the count.
revenue_bandThe revenue band the organization's revenue falls in.
data_vintageWhich data the figure comes from.
warningA note for the user when there is one; otherwise empty.
is_bls_primarytrue when the role is served from U.S. Bureau of Labor Statistics OEWS wage data rather than from Form 990 filings.
geographic_basis, geographic_fallback_reasonWhich geography the figure rests on, and why a metro you passed was not used (see below).
modelled_figure, no_modelled_figure_reasonAt a revenue of 0 there is no modeled figure: modelled_figure is false, every percentile is null, and no_modelled_figure_reason says why.
role_filings_note, role_filings_thinWhen this role has few or no filings at this revenue, role_filings_thin is true and role_filings_note carries a sentence to report with the figures.
base_p10, base_p25, base_median, base_p75, base_p90Base compensation (see Component semantics below).
bonus_p10, bonus_p25, bonus_median, bonus_p75, bonus_p90Bonus and incentive compensation.
other_p10, other_p25, other_median, other_p75, other_p90Other reportable compensation.
retirement_deferred_p10, retirement_deferred_p25, retirement_deferred_median, retirement_deferred_p75, retirement_deferred_p90Retirement and deferred compensation.
benefits_p10, benefits_p25, benefits_median, benefits_p75, benefits_p90Nontaxable benefits.
components_basis, components_under_10_filings, components_agedWhat the component rows are, and which of them rest on fewer than 10 filings (see Component semantics below).
base_pct_nonzero, bonus_pct_nonzero, benefits_pct_nonzero, other_pct_nonzero, retirement_deferred_pct_nonzero, base_n_disclosed, bonus_n_disclosed, benefits_n_disclosed, other_n_disclosed, retirement_deferred_n_disclosed, components_cohort_nAlways null; kept so existing integrations keep their shape (see Component semantics below).
bonus_label, bonus_prevalence_pct, bonus_typical_pctOf executives paid about the served median, the share who received a bonus and the typical bonus as a share of pay (see Component semantics below).
filed_titlesThe job titles filers most often reported under this role, each with its filing count, plus the role's total filings and number of distinct titles. A help for choosing the role; it does not change the figure.
filings_agedtrue when the figures were projected to a later date, false when they are as filed.
aged_to_date, aged_to_yearThe date, and its year, the figures were projected to; null when not projected. This can be earlier than the date you asked for (see money_aging_clamped).
aged_from_date, aged_from_yearThe date the projection runs from, and its fiscal year. A projected figure starts from Form 990 filings through that fiscal year. Null when not projected.
money_aging_factorThe multiplier the projection applied to the as-filed figures; null when not projected.
money_aging_base_factorThe multiplier applied to base salary when projected; equal to money_aging_factor when you supply aging_rate.
money_aging_base_span_projectedYears of the base salary projection that use a forecast rate.
money_aging_forward_vintageThe CBO forecast edition used for forecast years, e.g. "2026-02"; otherwise null.
money_aging_source, money_aging_rate_pctWhere the growth rate came from ("corpus-measured-growth" for CauseComp's measured nonprofit pay growth, "user-supplied" for your aging_rate), and the yearly rate you supplied, if you did.
money_aging_eci_vintageThe year of the growth table used for the projection; null when not projected.
money_aging_clamped, money_aging_requested_yearWhen the date you asked for is beyond the reach of the measured growth table: a sentence saying which date the figures were projected to instead, and the year you asked for.
money_aging_declined, money_aging_refusalWhen a projection was asked for and not made: a sentence saying so, and a short code for the reason. Null otherwise.
org_type_modifier_appliedtrue when an org-type adjustment was applied to the figures, otherwise false.
org_type_modifier_factor, org_type_modifier_sourceWhen an adjustment was applied: the multiplier, and the sentence describing it that the board report prints. Null otherwise.
org_type_modifier_declinedWhen an org_type was sent and no adjustment was applied: a sentence saying why. Null otherwise.
retired_parameter_noticePresent only when the request carried a parameter that is no longer used. The request is answered without it, and this sentence names it.
Inside inputWhat it means
role, ntee_sector, state, revenue_raw, org_type, ntee_subsector, msaEach parameter as interpreted: the canonical role, sector and state labels, the subsector in capitals, and null for anything not sent.

Reading geographic_basis. Which geography the figure rests on: "metro" when the metro you passed contributed, "state" when the state layer did, "national" for a US request. When an msa was passed and is not the basis, geographic_fallback_reason says why: "unknown_msa" (not a code /meta/metros publishes) or "metro_cell_unmeasured" (a published code with no separate estimate) or "msa_not_applicable" (the role is served from BLS OEWS wage data, which has no metro layer, so the parameter was not used); otherwise it is null. The input block echoes every parameter as interpreted, including msa and ntee_subsector. Same keys and values as the workforce endpoint.

Reading confidence. It is a depth-of-evidence label, not a statistical confidence interval, and no interval is published around the figure. It is set by the number of Form 990 filings for this role within a one-third to three-times revenue window; sector and state do not enter that count, and it is counted separately from the comparables set. confidence_basis carries that statement in full on every response, in the same bytes the board PDF and the Excel workbook print, so an API consumer and a board reading the document are told the same thing. It is empty on BLS-primary roles, where confidence is set from the number of states reporting OEWS wage data rather than from a filing count.

Reading median and p50. They are the same number. p50 was added so the percentile ladder reads p10/p25/p50/p75/p90 and the middle rung can be found by position. median is not deprecated and is not going away — it is the original key, every existing integration reads it, and both will continue to be returned. Use whichever you prefer; do not write code that expects only one. The component rows (base, bonus, benefits, other, retirement_deferred) still use _median and have no _p50 form.

Projected figures. Pass age_to_date or age_to_year to project the figures forward from the filings. A projected response says so in filings_aged, names the date it was projected to and the multiplier used, and serves the component rows as null (see Component semantics below). Without either parameter the figures are as filed and filings_aged is false.

Projected request

curl https://www.causecomp.org/api/v1/executive/benchmark \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Executive Director / CEO", "ntee_sector": "Human Services", "state": "CA", "revenue": "$5,000,000", "age_to_date": "2027-06-30"}'

Projected response

{
  "benchmark": {
    "aged_from_date": "2025-09-07",
    "aged_from_year": 2025,
    "aged_to_date": "2026-12-31",
    "aged_to_year": 2026,
    "base_median": 148621,
    "base_n_disclosed": null,
    "base_p10": 86672,
    "base_p25": 111837,
    "base_p75": 199693,
    "base_p90": 277582,
    "base_pct_nonzero": null,
    "benefits_median": 7358,
    "benefits_n_disclosed": null,
    "benefits_p10": 4291,
    "benefits_p25": 5536,
    "benefits_p75": 9886,
    "benefits_p90": 13741,
    "benefits_pct_nonzero": null,
    "bonus_label": null,
    "bonus_median": 2303,
    "bonus_n_disclosed": null,
    "bonus_p10": 1342,
    "bonus_p25": 1733,
    "bonus_p75": 3094,
    "bonus_p90": 4300,
    "bonus_pct_nonzero": null,
    "bonus_prevalence_pct": null,
    "bonus_typical_pct": null,
    "components_aged": true,
    "components_basis": "modelled_share",
    "components_cohort_n": null,
    "components_under_10_filings": [],
    "confidence": "High",
    "confidence_basis": "Confidence describes the depth of filing evidence for this benchmark. It is not a statistical confidence …",
    "data_vintage": "990 data",
    "filed_titles": {
      "n_distinct_titles": 8684,
      "n_filings": 113213,
      "titles": [
        {
          "n_filings": 52581,
          "title": "Executive Director"
        },
        {
          "n_filings": 13132,
          "title": "CEO"
        },
        // … 4 more
      ]
    },
    "filings_aged": true,
    "geographic_basis": "state",
    "geographic_fallback_reason": null,
    "is_bls_primary": false,
    "median": 163697,
    "method": "base (role x revenue) + location + NTEE",
    "modelled_figure": true,
    "money_aging_clamped": "A projection to June 30, 2027 was requested. CauseComp's measured pay growth projection extends to December …",
    "money_aging_declined": null,
    "money_aging_eci_vintage": 2026,
    "money_aging_factor": 1.05530823427,
    "money_aging_rate_pct": null,
    "money_aging_refusal": null,
    "money_aging_requested_year": 2027,
    "money_aging_source": "corpus-measured-growth",
    "n_obs": 83173,
    "no_modelled_figure_reason": null,
    "org_type_modifier_applied": false,
    "org_type_modifier_declined": null,
    "org_type_modifier_factor": null,
    "org_type_modifier_source": null,
    "other_median": 227,
    "other_n_disclosed": null,
    "other_p10": 132,
    "other_p25": 170,
    "other_p75": 304,
    "other_p90": 423,
    "other_pct_nonzero": null,
    "p10": 95465,
    "p25": 123183,
    "p50": 163697,
    "p75": 219951,
    "p90": 305741,
    "retirement_deferred_median": 3479,
    "retirement_deferred_n_disclosed": null,
    "retirement_deferred_p10": 2029,
    "retirement_deferred_p25": 2618,
    "retirement_deferred_p75": 4676,
    "retirement_deferred_p90": 6500,
    "retirement_deferred_pct_nonzero": null,
    "revenue_band": "$5M–$10M",
    "role_filings_note": null,
    "role_filings_thin": false,
    "warning": ""
  },
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "input": {
    "msa": null,
    "ntee_sector": "Human Services",
    "ntee_subsector": null,
    "org_type": null,
    "revenue_raw": "$5,000,000",
    "role": "Executive Director / CEO",
    "state": "CA"
  }
}

Component semantics (September 2026). The five component rows are modeled shares of the modeled total, so each component sits at or under its total. Components may not sum exactly to the total. Figures based on fewer than 10 filings are noted. components_under_10_filings lists the component rows (by name, such as "other") whose figure rests on fewer than 10 filings; those rows still carry their figures. components_basis says what the rows are: "modelled_share" for modeled shares. When no component figures can be given, the rows are null with components_basis null. When the request is aged (age_to_year), every component figure is projected by the same factor as the total and components_aged is true; it is false when the figures are as filed. bonus_label, bonus_prevalence_pct and bonus_typical_pct: of executives paid about the served median, across all roles and sectors, the share who received a bonus and the typical bonus as a share of pay among them. null below $150,000, where too few filers disclose a split, and on aged requests. *_n_disclosed, *_pct_nonzero and components_cohort_n remain on the wire for shape stability and are always null: the rows are no longer drawn from disclosing peers. The comparables ladders (peer_set_*) are unchanged and remain the filings’ own percentiles.

POST /workforce/benchmark

Broad-based workforce benchmark from BLS OEWS/ECEC + O*NET.

Professional plan. Each successful call counts as one call against the daily quota.

ParameterReq?Description
rolerequiredWorkforce role label (see /meta/roles).
staterequiredTwo-letter state code.
revenuerequiredBudget size (amount or band label).
ntee_sectorrequired*Required in nonprofit mode; omit in private mode.
modeoptionalnonprofit (default) or private.
leveloptionalSeniority tier 1, 2 (default), or 3.
naics_codeoptionalIndustry subsector for finer calibration (private mode).
msaoptionalMetro code (see /meta/metros).
employeesoptionalHeadcount, for size-sensitive roles.

Example request

curl https://www.causecomp.org/api/v1/workforce/benchmark \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Registered Nurse", "state": "IL", "ntee_sector": "Health — Hospitals & Medical", "revenue": "$10,000,000", "level": 2, "mode": "nonprofit"}'

Example response

{
  "benchmark": {
    "benefits_load_pct": null,
    "benefits_p50_usd": null,
    "confidence": "High",
    "data_vintage": "BLS OEWS May 2025 (aged to Sep 2026)",
    "geographic_basis": "state",
    "geographic_fallback_reason": null,
    "incentive_incidence": null,
    "incentive_p25_pct": null,
    "incentive_p25_usd": null,
    "incentive_p50_pct": null,
    "incentive_p50_usd": null,
    "incentive_p75_pct": null,
    "incentive_p75_usd": null,
    "is_bls_primary": true,
    "is_national": false,
    "major_group_line": "",
    "median": 104295,
    "method": "BLS OEWS primary — BLS OEWS May 2025 US national (official) + ECI aging + state ratio + industry adjustment + …",
    "mode": "nonprofit",
    "n_obs": 51,
    "onet_attribution": {
      "license": "CC BY 4.0",
      "license_link_text": "CC BY 4.0",
      "license_url": "https://creativecommons.org/licenses/by/4.0/",
      "modification_notice": null,
      "modified": false,
      "release": "31.0",
      "text": "This page includes information from the O*NET 31.0 Database by the U.S. Department of Labor, Employment and …"
    },
    "onet_covers": [],
    "onet_reported_titles": [
      "Certified Operating Room Nurse (CNOR)",
      "Charge Nurse",
      // … 8 more
    ],
    "p10": 73707,
    "p25": 85884,
    "p50": 104295,
    "p75": 120118,
    "p90": 146975,
    "revenue_band": "$10M–$25M",
    "role_description": "Assess patient health problems and needs, develop and implement nursing care plans, and maintain medical …",
    "seniority_tier": "Mid (Tier II)",
    "total_cash_p25_usd": null,
    "total_cash_p50_usd": null,
    "total_cash_p75_usd": null,
    "total_comp_p50_usd": null,
    "warning": ""
  },
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "input": {
    "employees": null,
    "level": 2,
    "mode": "nonprofit",
    "msa": null,
    "naics_code": null,
    "ntee_sector": "Health — Hospitals & Medical",
    "revenue_raw": "$10,000,000",
    "role": "Registered Nurse",
    "state": "IL"
  }
}

This page includes information from the O*NET 31.0 Database by the U.S. Department of Labor, Employment and Training Administration (USDOL/ETA). Used under the CC BY 4.0 license. O*NET® is a trademark of USDOL/ETA. CauseComp (RB Consulting Services, LLC) has modified all or some of this information. USDOL/ETA has not approved, endorsed, or tested these modifications.

What comes back

FieldWhat it means
benchmarkThe figures, described in the next table.
inputYour inputs as interpreted.
disclaimerThe standard disclaimer, which you must surface to end users.
Inside benchmarkWhat it means
p10, p25, median, p50, p75, p90Percentiles of pay for the role, in US dollars. median and p50 are the same number.
confidence, n_obsA depth-of-evidence label, and the count behind it (for roles served from OEWS wage data, the number of states reporting).
revenue_bandThe revenue band the organization's revenue falls in.
data_vintageWhich wage data the figure comes from, and the date it has been brought forward to.
warningA sentence for the user, for example when a metro you passed did not become the basis; otherwise empty.
seniority_tierThe seniority tier the figure is for (from level).
modenonprofit or private, as served.
is_bls_primary, is_nationalWhether the role is served from OEWS wage data, and whether the figure is a national one rather than one for your state.
geographic_basis, geographic_fallback_reasonWhich geography the figure rests on, and why a metro you passed was not used. Same keys and values as the executive endpoint.
role_description, onet_reported_titles, onet_covers, major_group_lineWhat the job is: O*NET's description, the job titles O*NET reports for it, the detailed occupations a broad occupation group covers, and, for a broad group with no O*NET entry, a written line instead.
onet_attributionThe O*NET credit, present whenever the response carries O*NET text.
soc_code, soc_title, soc_codes_coveredThe BLS occupation the figures are priced on, and every detailed occupation a combined role covers.
role_notesNotes on choosing this role, when it has any; otherwise an empty list.
label_deprecationPresent only when the request named a retired label: the label sent, the current label, and a note. The figures are the current label's.
incentive_p25_pct, incentive_p50_pct, incentive_p75_pct, incentive_p25_usd, incentive_p50_usd, incentive_p75_usd, total_cash_p25_usd, total_cash_p50_usd, total_cash_p75_usd, incentive_incidence, benefits_load_pct, benefits_p50_usd, total_comp_p50_usdIncentive and benefits-load fields, populated for roles with ECEC incentive coverage and null otherwise.
Inside inputWhat it means
role, ntee_sector, state, revenue_raw, mode, msa, naics_code, level, employeesEach parameter as interpreted: level after its default, and null for anything not sent or not readable.

POST /comparables

The §4958 comparables set for the same inputs as an executive benchmark. It is drawn separately from the modeled figure and does not produce it. This is the compliance layer for a board file. You can also name the organizations yourself (organizations): the response is then what those organizations filed, not a peer set CauseComp selected.

Professional plan (the §4958 comparables fence). Each successful call counts as one call against the daily quota.

ParameterReq?Description
rolerequiredExecutive role label, as for /executive/benchmark. Officer role, a list of roles, or 'all'. Required when organizations are supplied.
ntee_sectorrequired*NTEE sector label. Required unless organizations is given.
staterequired*Two-letter state code, or US. Required unless organizations is given; with it, it sets which rows count as in-state.
revenuerequired*Annual budget size (amount or band label). Required unless organizations is given.
ntee_subsectoroptionalThree-character NTEE subsector code (e.g. P20).
peer_sectorsoptionalA sector label, a list of labels, or "all": which sectors the peers are ranked toward, and how composition.in_sector is counted. It does not change the benchmark, which stays for ntee_sector. An unrecognized label returns a correction carrying the valid sectors.
select_onoptionalWhich comparables set to return: "role" (the default) chooses organizations on their filings for this role; "ceo" chooses them on their Executive Director / CEO filings and lists each one's filing for this role where it has one, so it can list fewer. For Executive Director / CEO the two are the same. Not accepted with organizations.
organizations, einsoptionalOrganizations to report on, by name or EIN, in any mix. Supplying this returns what those organizations filed in the last five years instead of a modelled peer cohort; an organization with no filing in that window is listed as unresolved, with the reason. You can name up to 100 organizations in one request. Split a larger list into several requests. (eins is accepted as another name for the same list.)
cityoptionalOptional city, used to tell same-named organizations apart.
include_einoptionalReturn each organization's EIN on its row.

Example request

curl https://www.causecomp.org/api/v1/comparables \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Executive Director / CEO", "ntee_sector": "Human Services", "state": "CA", "revenue": "$5,000,000"}'

Example response

{
  "comparables": [
    {
      "base": null,
      "bonus": null,
      "city": "BEVERLY HILLS",
      "disclosure_basis": "Total only (Form 990 Part VII or 990-EZ)",
      "fiscal_year": 2025,
      "mission": null,
      "mission_display": null,
      "mission_display_classification": null,
      "mission_display_source": null,
      "mission_display_year": null,
      "mission_reason": null,
      "mission_source": null,
      "nontaxable": null,
      "ntee_code": "P60",
      "ntee_description": "Emergency Assistance",
      "org": "ELEVATE HOPE INC",
      "other": null,
      "placeholder_flag": null,
      "retirement_deferred": null,
      "revenue": 5007995,
      "sector": "Human Services",
      "state": "CA",
      "title": "Executive Director",
      "total_comp": 111000,
      "website_url": null
    },
    {
      "base": null,
      "bonus": null,
      "city": "WALNUT CREEK",
      "disclosure_basis": "Total only (Form 990 Part VII or 990-EZ)",
      "fiscal_year": 2024,
      "mission": "(the filer's text, 173 characters)",
      "mission_display": "(the filer's text, 173 characters)",
      "mission_display_classification": null,
      "mission_display_source": null,
      "mission_display_year": null,
      "mission_reason": "disclosed",
      "mission_source": "MissionDesc",
      "nontaxable": null,
      "ntee_code": "P73",
      "ntee_description": "Group Homes",
      "org": "FULL CIRCLE OF CHOICES",
      "other": null,
      "placeholder_flag": false,
      "retirement_deferred": null,
      "revenue": 4971927,
      "sector": "Human Services",
      "state": "CA",
      "title": "Executive Dir.",
      "total_comp": 124770,
      "website_url": null
    },
    // … 18 more
  ],
  "composition": {
    "evidence": {
      "in_sector_n": 20,
      "in_state_n": 20,
      "listed_n": 20,
      "national_pool_n": 37041
    },
    "filing_window_from": "202110",
    "filing_window_years": 3,
    "in_sector": 20,
    "in_sector_n": 20,
    "in_state": 20,
    "n": 20,
    "n_national": 37041,
    "ntee_sector": "Human Services",
    "peer_set_basis": "modelled",
    "requested": 20,
    "select_on": "role",
    "state": "CA"
  },
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "peer_set_ladders": {
    "base": {
      "field": "base",
      "n": 10,
      "peer_set_p10": 157440.0,
      "peer_set_p25": 165913.25,
      "peer_set_p50": 189926.0,
      "peer_set_p75": 199861.25,
      "peer_set_p90": 251750.89999999997
    },
    "total_comp": {
      "field": "total_comp",
      "n": 20,
      "peer_set_p10": 109961.0,
      "peer_set_p25": 119811.0,
      "peer_set_p50": 162560.5,
      "peer_set_p75": 207219.75,
      "peer_set_p90": 234709.6
    }
  }
}

What comes back

FieldWhat it means
comparablesThe organizations and what each reported (next table).
compositionHow the set is made up (see below). Always show it alongside the list.
peer_set_laddersP10 to P90 across the rows listed, for total_comp and for base, each with its own count n (a filer that reports only a total has no base). Keyed peer_set_p10 … peer_set_p90 so they are never confused with the benchmark's own percentiles. Absent on a set spanning several roles.
suppliedOnly when you named the organizations: how many you asked for, how many were found, how many rows came back, and each one not resolved (unresolved, with the reason), matched more than once (ambiguous) or without a filing for the role (role_not_held).
widenedOnly when the set has no row for the role: rows for that role from the same state and from other states, as two separate blocks beside the set. They are never merged into it.
disclaimerThe standard disclaimer, which you must surface to end users.
Each row of comparablesWhat it means
org, city, state, einThe organization as it filed (ein only with include_ein).
fiscal_year, title, roleThe filing's year, the officer's title as reported, and the role it counts under.
sector, ntee_code, ntee_descriptionThe organization's NTEE sector, its subsector code and that code's description (null when the filing carries no code).
revenue, total_compThe organization's revenue and the officer's total reported compensation, in US dollars.
base, bonus, other, retirement_deferred, nontaxableThe reported components, where the filing itemizes them; null where it reports only a total.
disclosure_basisWhich kind of report the row comes from: itemized components, or a total only.
part_yearTrue when the filing's title indicates the officer served part of the fiscal year; the compensation shown covers that period only and is not annualized.
mission, mission_display, mission_display_sourceEach row also carries the organization's mission as it filed it on its Form 990 (mission) and mission_display: that text, or, where the filer wrote only a pointer such as "See Schedule O", the text it pointed to, with mission_display_source naming where it came from.
mission_source, mission_reason, placeholder_flag, mission_display_year, mission_display_classification, website_urlMore about the mission text: the form field it came from, whether a mission was disclosed, whether the filed text is only a pointer, the tax year of text taken from another year's filing, the NTEE classification shown when no text exists (a classification, not a description), and the organization's website where one is on file.
Inside compositionWhat it means
n, requestedHow many organizations are listed, and how many were asked for; fewer listed than asked means the data held fewer.
below_threePresent, and true, only when fewer than three organizations are listed (none, one or two). The rows are still returned; a board report or workbook is not produced from a set this small.
state, in_stateThe requested state, and how many listed organizations are in it.
ntee_sector, in_sector, in_sector_n, sectorsThe benchmark's sector; how many listed organizations are in the set the peers were ranked toward (sectors, present only when you passed peer_sectors); and how many are in the benchmark's own sector.
n_nationalThe number of organizations the set can draw from nationally for this role and size. It is a count of organizations, not filings, and it does not narrow by sector. Always report it whenever you report in_state.
evidenceThe same four counts together: national_pool_n, listed_n, in_sector_n, in_state_n.
filing_window_years, filing_window_fromEach organization contributes filings from its own most recent filing_window_years years, counted back from its latest return. filing_window_from is the earliest month (YYYYMM) an organization's latest return may end and still be included.
peer_set_basis, peer_set_basis_noteWhich kind of set this is: "modelled" when CauseComp selected it, "caller-supplied" when you named the organizations (with a sentence saying so).
select_onWhich set this is, "role" or "ceo" (see the request parameter). Absent when you named the organizations.
local_mix_keptPresent, and true, only when the set was drawn by the local mix described under Reading composition.
n_orgs, n_rows, roles_requested, multi_roleOnly when you named the organizations: how many were found, how many rows came back, the roles asked for, and whether more than one role was asked for.
Inside peer_set_laddersWhat it means
total_comp, baseEach a ladder: field, n, and peer_set_p10 to peer_set_p90.
Inside suppliedWhat it means
requested, resolved_orgs, rowsHow many organizations you named, how many were found, and how many rows came back.
unresolved, ambiguous, role_not_heldThe organizations not found (each with its reason), those that matched more than one organization, and those with no filing for the role.

Reading composition. State and sector favor organizations rather than restrict the set to them, so a peer set can include organizations from other states where in-state filings are few. When local_mix_kept is true, the set was drawn up to half from the same NTEE subsector nationwide and the rest from the same NTEE major group, organizations in the requested state first. An out-of-state filing in the same role, sector and revenue band is a valid comparable. Report n_national whenever you report in_state.

Organizations you name. With organizations, role may be one role, a list of roles, or "all". A set spanning several roles returns no percentile ladder: peer_set_ladders is absent, because percentiles across different roles describe no single group.

Named-organizations request

curl https://www.causecomp.org/api/v1/comparables \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Executive Director / CEO", "state": "CA", "organizations": ["770448301", "No Such Organization Anywhere"]}'

Named-organizations response

{
  "comparables": [
    {
      "base": 355000,
      "bonus": null,
      "city": "OXNARD",
      "fiscal_year": 2024,
      "mission": "(the filer's text, 193 characters)",
      "mission_display": "(the filer's text, 193 characters)",
      "mission_display_classification": null,
      "mission_display_source": null,
      "mission_display_year": null,
      "mission_reason": "disclosed",
      "mission_source": "MissionDesc",
      "nontaxable": null,
      "ntee_code": "P29",
      "ntee_description": "Thrift Shops",
      "org": "GOODWILL INDUSTRIES OF SANTA BARBARA AND VENTURA COUNTIES",
      "other": null,
      "part_year": false,
      "placeholder_flag": false,
      "retirement_deferred": 17750,
      "revenue": 45498855,
      "role": "Executive Director / CEO",
      "sector": "Human Services",
      "state": "CA",
      "title": "President & Ceo",
      "total_comp": 372750,
      "website_url": null
    }
  ],
  "composition": {
    "below_three": true,
    "filing_window_from": "202110",
    "filing_window_years": 5,
    "in_state": 1,
    "multi_role": false,
    "n_orgs": 1,
    "n_rows": 1,
    "peer_set_basis": "caller-supplied",
    "peer_set_basis_note": "These organizations were named in the request. CauseComp reported what each one filed on its Form 990 and did …",
    "requested": 2,
    "roles_requested": [
      "Executive Director / CEO"
    ],
    "state": "CA"
  },
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "peer_set_ladders": {
    "base": {
      "field": "base",
      "n": 1,
      "peer_set_p10": 355000.0,
      "peer_set_p25": 355000.0,
      "peer_set_p50": 355000.0,
      "peer_set_p75": 355000.0,
      "peer_set_p90": 355000.0
    },
    "total_comp": {
      "field": "total_comp",
      "n": 1,
      "peer_set_p10": 372750.0,
      "peer_set_p25": 372750.0,
      "peer_set_p50": 372750.0,
      "peer_set_p75": 372750.0,
      "peer_set_p90": 372750.0
    }
  },
  "supplied": {
    "ambiguous": [],
    "requested": 2,
    "resolved_orgs": 1,
    "role_not_held": [],
    "rows": 1,
    "unresolved": [
      {
        "input": "No Such Organization Anywhere",
        "reason": "no_match"
      }
    ]
  }
}

POST /board-report

The board report as a PDF: the same document the website's board report produces for these inputs, returned inside a JSON response.

With organizations, the comparables section, its P10-P90 ladder and composition come from what those organizations filed; composition then carries no national pool, and supplied lists any organization that could not be listed, with the reason.

Professional plan (the same §4958 comparables fence as /comparables). Each successful call counts as one call against the daily quota; no report credit is used.

ParameterReq?Description
rolerequiredExecutive role label the report is for.
ntee_sectorrequiredNTEE sector label.
staterequiredTwo-letter state code, or US. An unrecognized value returns a correction listing the valid codes.
revenuerequiredAnnual budget size (amount or band label).
orgoptionalThe organization's name as it should appear on the report cover.
org_type, ntee_subsector, msaoptionalAs for /executive/benchmark; the document says whether an org-type adjustment was applied.
peer_sectorsoptionalAs for /comparables: which sectors the listed peers are ranked toward.
select_onoptionalAs for /comparables.
age_to_date, age_dateoptionalProject the report's figures to this date (YYYY-MM-DD), as for /executive/benchmark. age_date is accepted as another name.
age_to_yearoptionalProject to 31 December of this year; ignored when a date is given.
aging_rate, age_rateoptionalA yearly growth rate in percent to use instead of the measured growth rate. age_rate is accepted as another name.
deliveryoptionalSet to "link" to receive a download link instead of the PDF bytes: the response then carries download_url and download_expires_at in place of pdf_base64.
organizations, einsoptionalOrganizations to report on, by name or EIN, in any mix. Supplying this returns what those organizations filed in the last five years instead of a modelled peer cohort; an organization with no filing in that window is listed as unresolved, with the reason. You can name up to 100 organizations in one request. Split a larger list into several requests. (eins is accepted as another name for the same list.)
cityoptionalOptional city, used to tell same-named organizations apart.
include_einoptionalReturn each organization's EIN on its row.
without_comparablesoptionalSee below.

Example request

curl https://www.causecomp.org/api/v1/board-report \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Executive Director / CEO", "ntee_sector": "Human Services", "state": "CA", "revenue": "$5,000,000", "org": "Example Organization"}'

Example response

{
  "composition": {
    "evidence": {
      "in_sector_n": 20,
      "in_state_n": 20,
      "listed_n": 20,
      "national_pool_n": 37041
    },
    "filing_window_from": "202110",
    "filing_window_years": 3,
    "in_sector": 20,
    "in_sector_n": 20,
    "in_state": 20,
    "n": 20,
    "n_national": 37041,
    "ntee_sector": "Human Services",
    "requested": 20,
    "select_on": "role",
    "state": "CA"
  },
  "content_type": "application/pdf",
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "filename": "causecomp_board_report.pdf",
  "pdf_base64": "(22336 base64 characters)",
  "sha256": "67025abba2e81cc9bb1aefbed21a310484f721bf42ee427f2be4e1d9d1469418",
  "size": 16750
}

What comes back

FieldWhat it means
pdf_base64The PDF itself, base64-encoded (described, not printed, in the example above).
download_url, download_expires_atOnly with delivery "link", in place of pdf_base64: a link to the PDF, valid for 24 hours and only for the CauseComp account that ran the report, and the time it expires (UTC).
filename, content_type, size, sha256A file name to save it under, application/pdf, its size in bytes, and its SHA-256 hash.
compositionThe same composition block as /comparables, for the peers the report lists. State it alongside the report.
without_comparablesPresent, and true, only on a report produced without a comparables set (see below).
suppliedOnly when you named the organizations: how many you asked for, how many were found, how many rows came back, and each one not resolved (unresolved, with the reason), matched more than once (ambiguous) or without a filing for the role (role_not_held).
disclaimerThe standard disclaimer, which you must surface to end users.
Inside compositionWhat it means
n, requested, state, in_state, ntee_sector, in_sector, in_sector_n, sectors, n_national, evidence, filing_window_years, filing_window_from, peer_set_basis, peer_set_basis_note, select_on, below_three, n_orgs, n_rows, roles_requested, multi_roleAs for /comparables.
n_part_yearOnly when you named the organizations and at least one listed row is part year: how many are.
Inside suppliedWhat it means
requested, resolved_orgs, rows, unresolved, ambiguous, role_not_heldAs for /comparables.

A request with no comparable filings, with none in the requested sector, or with fewer than three organizations to list is refused rather than rendered: HTTP 422 with code no_comparables, no_sector_match or below_three. Each carries renderable_without_comparables and a question. An unrecognized role, sector or state returns a correction carrying the valid values.

  • without_comparables (request, boolean): set to true, after a refusal that offers it, to request a board report without a comparables section; the report then says why and omits the comparables section.
  • renderable_without_comparables (response, boolean): true when this request can produce a board report without a comparables set.

POST /filings/lookup

Return rows of Form 990 compensation filings selected by the filters you pass, 20 rows a page in a fixed order. This is a data lookup, not a comparables set: the response states which filters selected the rows. There is no minimum number of rows: a filter that matches one filing returns that filing, and one that matches none returns matched 0.

Professional plan. Each successful call counts as one call against the daily quota, and every row returned counts against a separate limit of 200 rows of filing data per account per day, reported in row_meter. A page that would pass the limit returns the rows up to it, with row_limit_message; once the limit is reached, calls are refused with row_quota_exceeded until 00:00 UTC.

ParameterReq?Description
roleoptionalFiled role label to select rows for, e.g. 'Executive Director / CEO'. An unrecognized label returns a correction listing every accepted label.
stateoptionalTwo-letter US state code; selects rows filed from that state. 'US' applies no state filter. Accepts the codes list_states returns.
metrooptionalMetro-area (CBSA) code, e.g. '16980'. Selects rows whose filed city is placed in that metro area; the response carries a note on the filings this filter cannot place.
revenue_bandoptionalOrganization revenue band label, e.g. '$5M–$10M' (the same labels get_executive_benchmark accepts).
revenue_minoptionalLowest organization revenue to include, in US dollars.
revenue_maxoptionalHighest organization revenue to include, in US dollars.
ntee_sectoroptionalNTEE sector label, one of those list_sectors returns.
ntee_subsectoroptionalThree-character NTEE subsector code, e.g. 'P20'. Filings that carry no subsector code are not selected by this filter.
fiscal_year_fromoptionalEarliest fiscal year to include.
fiscal_year_tooptionalLatest fiscal year to include.
pageoptionalPage number, starting at 1. Each page holds up to 20 rows.

A filter name not in this table, or a value the filter does not recognize, returns a correction (HTTP 422, unrecognized_filter) naming the filter and carrying the accepted values, never an empty result.

Example request

curl https://www.causecomp.org/api/v1/filings/lookup \
  -H "Authorization: Bearer cc_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"role": "Executive Director / CEO", "state": "CA", "ntee_sector": "Human Services", "revenue_band": "$5M–$10M", "fiscal_year_from": 2023}'

Example response

{
  "disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. …",
  "matched": 187,
  "page": 1,
  "page_size": 20,
  "pages": 10,
  "returned": 20,
  "row_meter": {
    "limit": 200,
    "remaining": 180,
    "used": 20
  },
  "rows": [
    {
      "base": null,
      "bonus": null,
      "city": "GROVER BEACH",
      "disclosure_basis": "Total only (Form 990 Part VII or 990-EZ)",
      "fiscal_year": 2025,
      "nontaxable": null,
      "ntee_code": "P85",
      "ntee_description": "Homeless Centers",
      "ntee_sector": "Human Services",
      "org": "5CITIES HOMELESS COALITION",
      "other": null,
      "part_year": false,
      "retirement_deferred": null,
      "revenue": 5409642,
      "role": "Executive Director / CEO",
      "state": "CA",
      "title": "Executive Director",
      "total_comp": 126684
    },
    {
      "base": 334173,
      "bonus": null,
      "city": "WHITTIER",
      "disclosure_basis": "Schedule J, Part II (components itemized)",
      "fiscal_year": 2025,
      "nontaxable": null,
      "ntee_code": "P32",
      "ntee_description": "Foster Care",
      "ntee_sector": "Human Services",
      "org": "A GREATER LOVE FOSTER FAMILY AGENCY INC",
      "other": null,
      "part_year": false,
      "retirement_deferred": null,
      "revenue": 9197695,
      "role": "Executive Director / CEO",
      "state": "CA",
      "title": "Executive Dir.",
      "total_comp": 334173
    },
    // … 18 more
  ],
  "selected_by": {
    "fiscal_year_from": 2023,
    "ntee_sector": "Human Services",
    "revenue_band": "$5M–$10M",
    "role": "Executive Director / CEO",
    "state": "CA"
  },
  "withheld": 0
}

What comes back

FieldWhat it means
rowsThis page's filings (next table).
matched, page, page_size, pagesHow many filings the filters matched in all, this page's number, the page size, and the number of pages.
returned, withheldHow many rows this response carries, and how many of this page's rows were held back by the daily row limit.
selected_byThe filters that selected the rows, as interpreted.
metro_noticeOnly with metro: a note on the filings the metro filter cannot place.
row_meterThe account's row limit for the day, rows used and rows remaining.
row_limit_messagePresent when this response reached the daily row limit.
disclaimerThe standard disclaimer, for any answer built from these rows.
Each row of rowsWhat it means
org, city, state, fiscal_yearThe organization and the filing's year.
role, titleThe role the row counts under, and the officer's title as reported.
ntee_sector, ntee_code, ntee_descriptionThe organization's NTEE sector, subsector code and that code's description.
revenue, total_comp, base, bonus, other, retirement_deferred, nontaxableThe organization's revenue and the officer's reported compensation, in US dollars; components are null where the filing reports only a total.
disclosure_basisWhich kind of report the row comes from: itemized components, or a total only.
part_yearTrue when the filing's title indicates the officer served part of the fiscal year; the compensation shown covers that period only and is not annualized.
Inside selected_byWhat it means
role, state, metro, revenue_band, revenue_min, revenue_max, ntee_sector, ntee_subsector, fiscal_year_from, fiscal_year_toEach filter you passed, as interpreted. Filters you did not pass are absent.
Inside row_meterWhat it means
limit, used, remainingThe day's row limit, rows returned to the account today including this response, and rows left.

GET /organizations/find

Find nonprofit organizations by name in the comparables index (IRS Form 990 filers with officer compensation on record in the last five years) and get each one's EIN, to pass as organizations to /comparables. Returns up to 20 matches in alphabetical order, with no ranking.

Professional plan (the §4958 comparables fence). Not metered: lookups do not count against the daily quota.

ParameterReq?Description
namerequiredThe organization's name. Every word of three or more letters in it appears in each match's indexed name; case does not matter.
stateoptionalTwo-letter state code to narrow a common name. An unrecognized value returns the valid codes.

Example request

GET /api/v1/organizations/find?name=goodwill+industries&state=CA

Example response

{
  "n": 8,
  "organizations": [
    {
      "city": "SANTA ANA",
      "ein": "951644018",
      "latest_filing_year": 2024,
      "mission": "(the filer's text, 113 characters)",
      "mission_display": "(the filer's text, 113 characters)",
      "mission_display_classification": null,
      "mission_display_source": null,
      "mission_display_year": null,
      "mission_reason": "disclosed",
      "mission_source": "MissionDesc",
      "name": "GOODWILL INDUSTRIES OF ORANGE COUNTY CA",
      "ntee_sector": "Employment",
      "placeholder_flag": false,
      "revenue_band": "$100M–$500M",
      "state": "CA",
      "website_url": null
    },
    {
      "city": "SANTA ROSA",
      "ein": "942237862",
      "latest_filing_year": 2025,
      "mission": "(the filer's text, 83 characters)",
      "mission_display": "(the filer's text, 83 characters)",
      "mission_display_classification": null,
      "mission_display_source": null,
      "mission_display_year": null,
      "mission_reason": "disclosed",
      "mission_source": "MissionDesc",
      "name": "GOODWILL INDUSTRIES OF REDWOOD EMPIRE",
      "ntee_sector": "Employment",
      "placeholder_flag": false,
      "revenue_band": "$25M–$50M",
      "state": "CA",
      "website_url": null
    },
    // … 6 more
  ],
  "truncated": false
}

What comes back

FieldWhat it means
organizations, nThe matches (next table) and how many there are.
truncatedtrue when more than 20 matched; a longer name or a state narrows the list.
messageOnly when nothing matched: a sentence saying so.
unclassified_sector_noteOnly when a listed organization has no NTEE code on file: a sentence saying the user should be asked which sector their organization works in.
Each matchWhat it means
name, ein, city, stateThe organization and its EIN.
ntee_sector, revenue_band, latest_filing_yearIts NTEE sector, its revenue band and the year of its latest filing.
sector_unclassifiedOnly on an organization with no NTEE code on file: true, and its ntee_sector is null. Ask the user which sector it works in; there is no benchmark for an unclassified sector.
mission, mission_display, mission_display_source, mission_source, mission_reason, placeholder_flag, mission_display_year, mission_display_classification, website_urlThe mission fields, as on a /comparables row.

GET /meta/exec_roles

Valid executive role labels. Optional ?search= matches role labels and the officer titles filers report on Form 990, best match first, and resolves fuzzy input to a canonical label before you benchmark (avoids an unrecognized_role error). Professional plan. Not metered: lookups do not count against the daily quota.

ParameterReq?Description
searchoptionalCase-insensitive search. Matches role labels and the officer titles filers report on Form 990, best match first.
FieldWhat it means
rolesThe matching labels.
role_detailsOn a search: one row per label in roles, in the same order, saying what matched.
FieldWhat it means
roleThe label to pass to the benchmark.
matched_on, matched_termOn a search: what matched (label or filed_title, a title filers report on Form 990) and the text that matched.

Example request

GET /api/v1/meta/exec_roles?search=chief

Example response

{
  "roles": [
    "Chief Administrative Officer",
    "Chief Compliance Officer",
    // … 15 more
  ]
}

GET /meta/roles

Valid workforce role labels, with the same optional ?search= filter. Professional plan. Not metered: lookups do not count against the daily quota.

ParameterReq?Description
searchoptionalCase-insensitive search. Matches the role label, the BLS SOC code and title, common job titles and O*NET reported titles, then O*NET alternate titles, best match first.
FieldWhat it means
rolesThe matching labels.
role_detailsOne row per label in roles, in the same order: the role's BLS occupation and, on a search, what matched.
FieldWhat it means
roleThe label to pass to the benchmark.
soc_code, soc_titleThe BLS occupation code and title the role is priced on.
soc_codes_coveredOn a search: every detailed BLS occupation the role covers (more than one for a combined role).
matched_on, matched_termOn a search: what matched (label, soc_code, soc_title, alias, legacy_label, onet_reported_title or onet_alternate_title) and the text that matched.
label_deprecationOn a search for a retired label: the label sent, the current label, and a note.

Example request

GET /api/v1/meta/roles?search=nurse

Example response

{
  "roles": [
    "Nurse Practitioner",
    "Registered Nurse",
    // … 4 more
  ]
}

GET /meta/metros

Metro areas (MSAs) for a state, largest employment first — the valid msa codes a benchmark call can pass. ?state= is required.

Professional plan. Not metered: lookups do not count against the daily quota.

ParameterReq?Description
staterequiredTwo-letter state code. An empty or unrecognized value returns an empty list.
FieldWhat it means
metrosThe metro areas, largest employment first.
Each metroWhat it means
code, nameThe code to pass as msa, and the metro's name.

Example request

GET /api/v1/meta/metros?state=IL

Example response

{
  "metros": [
    {
      "code": "16980",
      "name": "Chicago-Naperville-Elgin, IL-IN"
    },
    {
      "code": "37900",
      "name": "Peoria, IL"
    },
    // … 6 more
  ]
}

GET /meta/states

Valid state codes for a benchmark call. US is a member of the list: it means the national benchmark with no state adjustment. No parameters. Professional plan. Not metered: lookups do not count against the daily quota.

FieldWhat it means
statesThe valid codes.

Example request

GET /api/v1/meta/states

Example response

{
  "states": [
    "US",
    "AL",
    // … 50 more
  ]
}

GET /meta/sectors

Valid NTEE sector labels for the ntee_sector input. No parameters. sectors_detail pairs each label with its NTEE major-group letter (sorted by code); pass the bare label as the ntee_sector input.

Professional plan. Not metered: lookups do not count against the daily quota.

FieldWhat it means
sectorsThe valid labels.
sectors_detailEach label with its NTEE major-group letter.
Each entryWhat it means
code, labelThe major-group letter and the label.

Example request

GET /api/v1/meta/sectors

Example response

{
  "sectors": [
    "Arts, Culture & Humanities",
    "Civil Rights",
    // … 24 more
  ],
  "sectors_detail": [
    {
      "code": "A",
      "label": "Arts, Culture & Humanities"
    },
    {
      "code": "B",
      "label": "Education"
    },
    // … 24 more
  ]
}

GET /meta/methodology

The published methodology: the site's own Methodology page, split into its sections. Professional plan. Not metered: lookups do not count against the daily quota.

Its Data source section names the fiscal years of the Form 990 filings the executive model is built from.

ParameterReq?Description
sectionoptionalReturn only the sections whose heading contains this text (case does not matter). A heading with no text of its own returns the sections beneath it. An unknown section returns an empty list, the available headings and a message, not an error.
FieldWhat it means
sourceThe page the sections come from: /methodology.
sectionsThe sections (next table).
available, messageOnly with section: every heading on the page, and a sentence when the match needs one.
Each sectionWhat it means
heading, level, textThe section's heading, its heading level and its text.

Example request

GET /api/v1/meta/methodology?section=Reading+the+numbers

Example response

{
  "available": [
    "Executive Compensation 990",
    "Data source",
    // … 9 more
  ],
  "message": "",
  "sections": [
    {
      "heading": "Reading the numbers",
      "level": 2,
      "text": "P25 / Median / P75 describe where pay falls across comparable organizations — a market range, not a …"
    }
  ],
  "source": "/methodology"
}

GET /meta/role_about

The role description CauseComp shows beside a benchmark: the same text as the About this role panel on the site, as data.

Professional plan. Not metered: lookups do not count against the daily quota.

ParameterReq?Description
productrequiredexecutive or workforce.
rolerequiredan exact label from /meta/exec_roles or /meta/roles.

Errors & limits

Every failure returns the same envelope — never an HTML page or a stack trace:

{ "error": { "code": "...", "message": "...", /* optional hints */ } }
HTTPcodeWhen
400bad_requestA request the endpoint cannot read, such as named organizations with no role, or board-report inputs that are missing.
401unauthorizedMissing, invalid, expired, or revoked credential.
403forbiddenOwner lacks the Professional plan (carries an upgrade_url); comparables also need the Professional §4958 fence.
422validation_errorBad or missing input (unparseable revenue, absent required field).
422unrecognized_roleRole not recognized; carries suggestions.
422unrecognized_sectorSector label not recognized; carries the valid sectors.
422unrecognized_stateState code not recognized; carries the valid codes (see /meta/states).
422too_many_peer_sectorsMore peer_sectors than are allowed; carries the limit and the valid sectors.
422unrecognized_filter/filings/lookup only: a filter or value not recognized; carries the accepted values.
422insufficient_comparablesRecognized cohort with zero comparable filings; carries data-backed suggested_fallback_roles.
422no_dataNo figure is available for this request, for example a workforce role that is not benchmarked or has been renamed (a renamed role carries suggestions).
422select_on_with_organizationsselect_on was sent with organizations; the set choice applies only to a set CauseComp selects.
422role_matched_reference_retired/comparables only: role_matched_reference is no longer offered. The comparables set is now chosen on this role's filings by default; select_on "ceo" returns the set chosen on Executive Director / CEO filings.
422no_comparables, no_sector_match, below_three, no_named_organization_listed/board-report only: the report is refused (see that section).
429rate_limitedBurst limit exceeded (120 requests per minute per credential).
429quota_exceededDaily account quota reached (carries limit).
429row_quota_exceeded/filings/lookup only: the daily row limit is reached (carries limit).
500forecast_error, internal_errorSomething failed on our side; the request can be retried.

"Unknown" is no longer a sector label. A request that sends it gets the unrecognized_sector correction with the valid sectors, plus retired_sector: true and a message saying why.

Daily quota

Each account may make 250 calls per day, across all of its API keys and connector sign-ins together; the meter resets at 00:00 UTC. The POST endpoints count; the lookups (/meta/* and /organizations/find) do not. Only successful calls count: a request refused for bad input or by a plan fence does not. On the call after the limit:

{ "error": { "code": "quota_exceeded",
             "message": "Daily query limit of 250 reached for this account. It resets at 00:00 UTC.",
             "limit": 250 } }

On a Consultant subscription the limit is 1,000 calls per day instead of 250. Everything else above applies the same way.

/filings/lookup also has a row limit: 200 rows of filing data per account per day, beside the call quota (see that section).

Structured 422s you can branch on

An unrecognized role comes back with "did you mean" suggestions:

{
  "error": {
    "code": "unrecognized_role",
    "message": "Unrecognized role 'Chief Finance Officer'. Choose a listed executive role.",
    "requested_role": "Chief Finance Officer",
    "suggestions": [
      "Chief Administrative Officer",
      "Chief Compliance Officer",
      // … 3 more
    ]
  }
}

A recognized cohort with no comparable filings returns data-backed fallback roles (with their observation counts) instead of an ungrounded number:

{
  "error": {
    "code": "insufficient_comparables",
    "low_confidence_below": 10,
    "message": "No comparable Schedule-J filings for 'Chief Data Officer' in Human Services at <$500K. Try a broader officer …",
    "n_obs": 0,
    "requested": {
      "ntee_sector": "Human Services",
      "revenue_band": "<$500K",
      "role": "Chief Data Officer",
      "state": "CA"
    },
    "suggested_fallback_roles": [
      {
        "n_obs": 63997,
        "role": "Executive Director / CEO"
      },
      {
        "n_obs": 902,
        "role": "COO"
      },
      // … 2 more
    ],
    "threshold": 1
  }
}

Key management

Mint and revoke API keys on your account page, in the API & Claude Connector section.

  • Mint: name a key and create it. The full secret (cc_live_…) is shown once, at creation — copy it then; it is never displayed again and never stored in a recoverable form.
  • Keys are secrets. Treat a key like a password. Anyone holding it can benchmark against your plan (subject to the daily quota). Don't commit keys to source control or paste them into shared documents.
  • Revoke: revoking a key takes effect immediately — the very next request with it returns 401 unauthorized. Rotate by minting a new key and revoking the old.
  • Connector: the one-click Claude connector uses OAuth, not a key you paste; disconnect it from Claude, or revoke access from your account page, at any time.

Disclaimer

Every benchmark and comparables response carries this text, which you must surface to end users:

CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. Data like this supports — but does not by itself establish — a board's rebuttable presumption of reasonableness under IRC §4958 (intermediate sanctions), which also requires advance approval by an independent board body and contemporaneous documentation. See https://www.causecomp.org.

Questions? Contact us or read the Claude connector page.