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 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 outside Claude. - The Claude connector's OAuth token — issued automatically when you connect CauseComp to Claude (on claude.ai or the desktop app). You never see or paste it; the one-click connector handles it.
Either way, the header looks like this (the connector sets it for you):
Authorization: Bearer cc_live_your_key_here
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.
Open Connectors
In Claude, go to Settings → Connectors, click Add, then Add custom connector.
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.
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
Seven endpoints: three benchmark/data endpoints (POST, JSON body) and four registry lookups
(GET, query string). All require the Authorization: Bearer header. The three
data endpoints count against your daily quota; the lookups are
unmetered. revenue accepts a dollar amount
("$5,000,000" or 5000000) or a band label.
POST /executive/benchmark
Executive (officer / leadership) benchmark from 990 Schedule J.
| Parameter | Req? | Description |
|---|---|---|
| role | required | Executive role label (resolve fuzzy input via /meta/exec_roles). |
| ntee_sector | required | NTEE sector label (see /meta/sectors). |
| state | required | Two-letter state code, e.g. CA. |
| revenue | required | Annual budget size (amount or band label). |
| org_type | optional | optional. Applied for 501(c)(3), 501(c)(6), 501(c)(7), 501(c)(8) and 501(c)(9). For every other subsection the benchmark is computed across all nonprofit filers. |
| ntee_subsector | optional | Three-character NTEE subsector code (e.g. P20) for finer calibration. |
| msa | optional | Metro code (see /meta/metros). |
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": {
"p10": 97714, "p25": 121425, "median": 156421, "p75": 199200, "p90": 243426,
"confidence": "Medium", "n_obs": 6070,
"revenue_band": "$5M-$10M", "col_tier": "Tier 1 - Very High",
"data_vintage": "990 data + trend projection (projected 2025 to 2026)",
"method": "990 gradient-boosted quantiles + peer-cohort anchor + ECI aging",
"base_median": 159464, "bonus_median": 0, "benefits_median": 9600, "other_median": 0,
"retirement_deferred_median": 4703, "retirement_deferred_pct_nonzero": 0.668,
"base_n_disclosed": 1219, "bonus_n_disclosed": 897, "benefits_n_disclosed": 1050,
"other_n_disclosed": 870, "retirement_deferred_n_disclosed": 989,
"components_cohort_n": 2025,
"is_bls_primary": false
},
"input": { "role": "Executive Director / CEO", "ntee_sector": "Human Services",
"state": "CA", "revenue_raw": "$5,000,000", "org_type": null },
"disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. ..."
}
Also returned:
n_obs_typed, org_type_cohort_used,
warning, pct_nonzero ratios for every pay component, and
p10/p25/p75/p90
for each pay component (base, bonus, benefits, other, retirement_deferred). When a cohort has 1–9 comparable filings the
benchmark is served with a low_confidence flag.
Component semantics (July 2026).
Component percentiles are computed across the peers that itemize that component on
Schedule J: a reported $0 is included, an undisclosed amount is excluded, and the
*_pct_nonzero denominator is the disclosing peers. Each component
carries an additive *_n_disclosed count alongside
components_cohort_n. When fewer than 20 peers disclose a component,
or under 20% of the component cohort discloses it, that component's percentile and
pct_nonzero keys are served as null
(insufficient disclosure) — key names and positions are unchanged.
POST /workforce/benchmark
Broad-based staff benchmark from BLS OEWS/ECEC + O*NET.
| Parameter | Req? | Description |
|---|---|---|
| role | required | Workforce role label (see /meta/roles). |
| state | required | Two-letter state code. |
| revenue | required | Budget size (amount or band label). |
| ntee_sector | required* | Required in nonprofit mode; omit in private mode. |
| mode | optional | nonprofit (default) or private. |
| level | optional | Seniority tier 1, 2 (default), or 3. |
| naics_code | optional | Industry subsector for finer calibration (private mode). |
| msa | optional | Metro code (see /meta/metros). |
| employees | optional | Headcount, 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",
"revenue": "$10,000,000", "level": 2, "mode": "nonprofit"}'
Example response
{
"benchmark": {
"p10": 77153, "p25": 89900, "median": 109172, "p75": 125735, "p90": 153848,
"confidence": "High", "n_obs": 51,
"revenue_band": "$10M-$25M",
"data_vintage": "BLS OEWS May 2025 (aged to Jul 2026)",
"method": "BLS OEWS primary + ECI aging + state ratio + industry adjustment",
"seniority_tier": "Mid (Tier II)", "is_bls_primary": true, "mode": "nonprofit",
"role_description": "Direct nursing staff in the provision of patient care ..."
},
"input": { "role": "Registered Nurse", "ntee_sector": "Health", "state": "IL",
"revenue_raw": "$10,000,000", "mode": "nonprofit" },
"disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. ..."
}
Incentive and benefits-load fields
(incentive_p50_pct, total_cash_p50_usd,
benefits_load_pct, …) are populated for roles with ECEC incentive
coverage and null otherwise.
POST /comparables
The §4958 comparable organizations behind an executive benchmark. Same inputs as
/executive/benchmark (role, ntee_sector, state, revenue; optional
ntee_subsector). This is the compliance layer for a board file.
Example response (20 organizations)
{
"comparables": [
{ "org": "CREATIVE SUPPORT", "city": "HUNTINGTN BCH", "state": "CA",
"fiscal_year": 2023, "title": "Executive Director", "sector": "Human Services",
"ntee_code": "P20", "ntee_description": "Human Service Organizations",
"total_comp": 200000, "revenue": 4976979 },
{ "org": "YOUNG WOMENS FREEDOM CENTER", "city": "SAN FRANCISCO", "state": "CA",
"fiscal_year": 2020, "title": "Executive Director", "sector": "Human Services",
"ntee_code": null, "ntee_description": null,
"total_comp": 162885, "revenue": 5028928 }
// ... 20 organizations total
],
"disclaimer": "CauseComp provides comparability data for informational purposes and does not provide legal or tax advice. ..."
}
GET /meta/exec_roles · GET /meta/roles
Valid executive role labels / workforce role labels. Optional
?search= substring filter resolves fuzzy input to a canonical label
before you benchmark (avoids an unrecognized_role error).
GET /api/v1/meta/exec_roles?search=chief
{ "roles": ["Chief Administrative Officer", "Chief Compliance Officer",
"Chief Data Officer", "Chief Development Officer", "..."] }
GET /api/v1/meta/roles?search=nurse
{ "roles": ["Nurse Practitioner", "Registered Nurse",
"Licensed Vocational Nurse (LVN)", "Nurse Anesthetist (CRNA)", "..."] }
GET /meta/metros
Metro areas (MSAs) for a state, largest employment first — the valid
msa codes a benchmark call can pass.
?state= is required.
GET /api/v1/meta/metros?state=IL
{ "metros": [ { "code": "16980", "name": "Chicago-Naperville-Elgin, IL-IN" },
{ "code": "37900", "name": "Peoria, IL" },
{ "code": "40420", "name": "Rockford, IL" } ] }
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.
GET /api/v1/meta/sectors
{ "sectors": ["Arts, Culture & Humanities", "Civil Rights",
"Community Improvement", "Education", "..."],
"sectors_detail": [
{ "code": "A", "label": "Arts, Culture & Humanities" },
{ "code": "B", "label": "Education" }
// ... 26 NTEE major groups, A–Z
] }
Errors & limits
Every failure returns the same envelope — never an HTML page or a stack trace:
{ "error": { "code": "...", "message": "...", /* optional hints */ } }
| HTTP | code | When |
|---|---|---|
| 401 | unauthorized | Missing, invalid, expired, or revoked credential. |
| 403 | forbidden | Owner lacks the Professional plan (carries an upgrade_url); comparables also need the Professional §4958 fence. |
| 422 | validation_error | Bad or missing input (unparseable revenue, absent required field). |
| 422 | unrecognized_role | Role not recognized; carries suggestions. |
| 422 | insufficient_comparables | Recognized cohort with zero comparable filings; carries data-backed suggested_fallback_roles. |
| 429 | rate_limited | Burst limit exceeded (120 requests per minute per credential). |
| 429 | quota_exceeded | Daily per-key quota reached (carries limit). |
Daily quota
Each credential may make 250 benchmark/data requests per day; the meter resets at
00:00 UTC. Registry lookups (/meta/*) are unmetered. On the 251st data call:
{ "error": { "code": "quota_exceeded",
"message": "Daily query limit of 250 reached for this credential. It resets at 00:00 UTC.",
"limit": 250 } }
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",
"Chief Data Officer", "Chief Development Officer", "..."] } }
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",
"message": "No comparable Schedule-J filings for 'Chief Human Resources' in Human Services at $1M-$2.5M. Try a broader officer role or a wider revenue band.",
"n_obs": 0, "threshold": 10,
"requested": { "role": "Chief Human Resources", "ntee_sector": "Human Services",
"state": "CA", "revenue_band": "$1M-$2.5M" },
"suggested_fallback_roles": [ { "role": "Executive Director / CEO", "n_obs": 7295 },
{ "role": "CFO / Head of Finance", "n_obs": 530 },
{ "role": "COO", "n_obs": 288 } ] } }
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.