Integration details
Description
Instrumentl integration for nonprofits. Make Instrumentl a native part of your AI workflow – an intelligent partner that helps you find, win, and manage grants faster, directly in ChatGPT.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Pending
- Secondary Subcategories
- None listed
- Brand
- Instrumentl
- Access
- Account required
- First tracked
- 2026-09-13
- Tool count
- 21
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
ChatGPT Plugin Discovery Score
ChatGPT Plugin discovery is coming soon
ChatGPT can surface a Plugin when it matches a user's request.Your Plugin Discovery Score measures how often yours appears.
No spam. Unsubscribe any time.
What discovery looks like

Competitive lineup
21 tools agents can invoke
Delete one or more expenses by their API IDs (e.g. `exp_...`). Best-effort: critically required expenses linked to external systems (QuickBooks, Sage Intacct, etc.) cannot be hard-deleted and are returned in the `failed` array with a reason; other expenses in the same call are still deleted. The response shape is: { deleted_ids: ["exp_...", ...], failed: [{id: "exp_...", reason: "..."}, ...] } Possible failure reasons: - "not_found": the id doesn't exist or belongs to a different account - "not_authorized": the caller lacks permission to delete this expense - "linked_to_external_system": the expense is mirrored from an external integration and must be removed there first
bulk_destroy_expenses
Update one or more expenses by their API IDs (e.g. `exp_...`). Best-effort: expenses that don't exist, belong to a different account, or that the caller lacks permission to modify are returned in the `failed` array with a reason; other expenses in the same call are still updated. Currently the only supported update is toggling whether an expense is ignored. Ignored expenses are excluded from budget totals but kept on the account for reference. Pass `ignored: true` to mark expenses as ignored, or `ignored: false` to restore them. The response shape is: { updated_ids: ["exp_...", ...], failed: [{id: "exp_...", reason: "..."}, ...] } Possible failure reasons: - "not_found": the id doesn't exist or belongs to a different account - "not_authorized": the caller lacks permission to update this expense
bulk_update_expenses
Add one or more expenses to a grant's budget. Each expense attaches to a specific expense category (an `ec_...` API ID) within a saved grant (an `save_...` API ID); call `list_budgets` first to find the right category and its remaining budget. Amounts are integer cents (e.g. `12500` = $125.00). Best-effort: each expense is created independently. Items that fail (unknown or forbidden grant/category, validation errors) are returned in the `failed` array — each carries its input fields and a reason — while the rest are still created. Pass `dry_run: true` to preview the budget impact WITHOUT creating anything. The preview reports, per category, the projected remaining budget, whether it would be overspent, and any expenses that already exist in that category — useful to catch a planned expense the user may want to update rather than duplicate. Prefer a dry run first whenever an expense might exceed a budget or already exist. To update or remove existing expenses, use `bulk_update_expenses` or `bulk_destroy_expenses` instead of creating new ones. Create response shape: { created_ids: ["exp_...", ...], failed: [{index, reason, saved_grant_id, expense_category_id, amount_cents, errors?}, ...], budget_impact: [{expense_category_id, category_name, remaining_cents, overspent}, ...] } Dry-run response shape: { projected: [{saved_grant_id, expense_category_id, category_name, budgeted_cents, current_remaining_cents, added_cents, projected_remaining_cents, overspent, existing_in_category, existing_in_category_has_more}, ...], failed: [...] } Possible failure reasons: - "not_found": the grant or category doesn't exist or belongs to a different account - "not_authorized": the caller lacks permission to add to this grant - "invalid": the expense failed validation (details in `errors`)
create_expenses
Retrieve the Instrumentl account the caller is authorized to act in.
get_current_account
Hide a previously-saved grant by marking its SavedGrant as no longer saved (`saved: false, hidden: true`). Pass the SavedGrant's `id` (e.g. `save_...`). This is reversible and non-destructive: the SavedGrant and any application data attached to it (submission goals, tasks, expenses, etc.) are preserved, and the grant can be saved again later. To find the right `saved_grant_id`, list the project's saved grants (`list_project_matches` filtered by saved status, or look up via `list_project_matches`'s `saved` filter).
hide_saved_grant
List the current user's budgets — one per saved grant that has a budget set up — to decide which budget an expense belongs to. Saved grants with no expense categories are omitted (unless requested by saved_grant_ids). Optionally narrow the results (filters compose with AND; omit all to list every budget). The user usually refers to a budget by name rather than id: - grant_name: the grant's name (case-insensitive substring) — use when the user names a grant - project_name: the project's title (case-insensitive substring) — disambiguates when grant names repeat - saved_grant_ids: budget ids (saved grant ids, prefix "save_") for exact budgets - transaction_date: an expense date (YYYY-MM-DD) — returns budgets whose award period covers it Each budget's "id" is its saved grant id (prefix "save_") for use with other saved-grant tools, plus grant_name and project_title to identify it. A budget contains budget_phases (each phase is a time window such as a grant year), and each phase contains expense_categories nested as a tree (child_categories). All amounts are integer cents (amount_currency holds the currency): - amount_cents: budgeted amount - actual_cents: spent so far (excludes planned and ignored expenses) - planned_cents: planned but not yet actual - remaining_cents: amount_cents - actual_cents - planned_cents (negative means over budget) Category amounts roll up the whole subtree, so a parent category's totals include its children's. To place an expense, match it to a category by name and prefer a budget/category whose remaining_cents can cover it.
list_budgets
List the account's custom field definitions — the extra fields this organization has added to its saved grants and funders. Call this first whenever the user names a field that is not a built-in one ("Priority", "Program Area", "Internal Owner"). It is the only way to resolve such a name to a field and to learn what values that field can hold. Then pass include_custom_fields: true to list_saved_grants or list_funders to read the values themselves. Each definition returns: - name: what the user calls the field - attached_to: which record the field hangs off (SavedGrant, Funder) - value_type: one of string, text, date, amount, numeric, enum, multiselect, link - options: for enum and multiselect fields, the allowed choices, each with an option_key (stored), an option_value (shown to people) and a display_order Values read back from list_saved_grants and list_funders are option_value labels, not option_keys, so compare them against option_value. A multiselect value is those labels joined with ", ". Filters: - attached_to: SavedGrant, Funder — narrows to fields on saved grants or on funders With no filters, returns the account's custom fields a page at a time — page_size defaults to 20. If meta.has_more is true there are more definitions; page with the cursor before concluding a field does not exist.
list_custom_field_definitions
List the current user's expenses. At least one filter must be provided: - saved_grant_id: a SavedGrant api_id (prefix "sgrt_") - expense_ids: an array of Expense api_ids - project_name: a project title (case-insensitive substring); conditionally joins projects - grant_name: a grant name (case-insensitive substring); conditionally joins grants Filters compose with AND. project_name and/or grant_name resolve to the user's matching saved grants and return all expenses across them.
list_expenses
List all Funder Contacts
list_funder_contacts
List all Funders
list_funders
List all grants. This API will only return grants that match one of the following: 1. are custom for your user (created via a spreadsheet upload or custom grant form) 2. saved to a project 3. hidden from a project 4. hidden account-wide.
list_grants
List Instrumentl's recommended Grants (Matches) from the public catalog for a Project. A Match is a suggested funder/grant the user has not yet decided on; it is separate from the user's tracker, which is a view of saved grants. Before calling this tool, disambiguate with the user when the wording could go either way. Users routinely say "my grants/matches/opportunities (for my project X)" to mean entries already in their tracker (SavedGrants → list_saved_grants), and other times to mean fresh recommendations from the catalog (Matches → this tool). Ask a short clarifying question, e.g.: "Do you mean grants/matches already saved in your tracker, or new recommendations Instrumentl has surfaced for this project?" Use this tool only after confirming the user wants recommendations; otherwise call list_saved_grants (it accepts `project_name` or `project_id`). Filters: - project_id: a Project api_id (prefix "proj_") to scope recommendations to that project - match_ids: array of Match api_ids
list_project_matches
List all projects associated with the current account
list_projects
List the user's SavedGrants — entries already in their tracker. A SavedGrant is the user's record of pursuing a Grant for a specific Project; an "awarded" SavedGrant is one with status "funding_awarded" or "closed". Before calling, disambiguate when the wording is ambiguous; ask a single clarifying question rather than guessing. The most common confusion is between SavedGrants (already in the tracker) and Matches (new recommendations from the public catalog). A good clarifier: "Do you mean grants/matches already in your tracker, or new recommendations Instrumentl has surfaced for this project?" - "my grant(s)", "my match(es)", "my opportunity/opportunities", "grants for my project X", "what have I saved/tracked": almost always SavedGrants already in the tracker → THIS tool. If the phrasing could plausibly mean "new recommendations" instead, confirm with the user first; use list_project_matches only after they confirm they want recommendations. - "awards", "current grants", or bare "grants" in an award/funding context: awarded SavedGrants → THIS tool with `awarded: true` (matches both "Awarded - Active" and "Awarded - Closed"). For only currently-active awards, pass `statuses: ["funding_awarded"]` instead. - "find grants", "search grants", "what grants are available": the public Grant catalog → use list_grants. - Bare "grants" with no "my" and no award context: ambiguous — ask first. Filters (compose with AND): - saved_grant_id: a SavedGrant api_id (prefix "save_") — returns just that one - project_id / grant_id / funder_id: api_ids to scope by the related record - statuses: array of SavedGrant statuses (researching, planned, started, loi_in_progress, submitted, loi_submitted, funding_awarded, closed, declined, abandoned) - awarded: true restricts to awarded SavedGrants; false excludes them - award_year: integer fiscal year for the award period - project_name: case-insensitive substring on the project title (use when the user names a project) - grant_name: case-insensitive substring on the underlying grant's name (use when the user names a grant) Custom fields: set include_custom_fields to true to get each saved grant's custom field values. Call list_custom_field_definitions first to learn which fields the account has and what their options are. Values come back as labels, not option keys, so compare them against a definition's option_value. To list everything in the user's tracker, call with no filters.
list_saved_grants
List the user's Tasks (also called custom grant deadlines). A Task belongs to a SavedGrant in the user's tracker and can have an assignee, a nominator, a creator, and (when done) a completer. DISAMBIGUATE before filtering by a person. The tool exposes four separate people filters — `assignee`, `nominator`, `created_by`, `completed_by` — because each captures a different relationship and they AND-compose, so picking the wrong one returns wrong results. When the user names a person without a clear role ("Sarah's tasks", "tasks for Sarah", "what is Sarah working on"), ask which they mean before calling. A good single clarifier: "Do you mean tasks assigned to Sarah, tasks she created, tasks she completed, or tasks she nominated (handed off)?" Common phrasings → likely role: - "my tasks", "Sarah's tasks", "tasks for Sarah", "what is Sarah working on": almost always `assignee` — confirm and proceed. - "tasks Sarah added/made/wrote": `created_by`. - "tasks Sarah finished/completed/closed out": `completed_by` (also implies done). - "tasks Sarah handed off / reassigned / passed to someone else": `nominator`. If unclear, ask before guessing. Each people filter matches first name, last name, OR email (case-insensitive substring), so the user need not say which form they remember. Other filters (compose with AND): - saved_grant_id / project_id: api_ids — use when you already have the id (e.g. from another tool call) - project_name / grant_name / funder_name: case-insensitive substrings — use when the user names the entity - assignee_id / nominator_id: user api_ids — for an exact person rather than a name search - is_done: true returns completed tasks; false returns open tasks ("show open tasks" is the most common ask) - past_due: true returns overdue, not-done tasks; false excludes them - unassigned: true returns tasks with no assignee (use for "tasks nobody owns") - kinds: array of task kinds (full_proposal, report, general, letter_of_inquiry, cultivation) - deadline_gte / deadline_lte: ISO dates; deadline_gte INCLUDES tasks with no deadline, deadline_lte does not Call with no filters to list every task in the user's tracker.
list_tasks
List the users (teammates) on the current account. Use this when the user references a teammate by name and you need their `id` to pass into another tool — `assignee_id` / `nominator_id` on ListTasks, `user_id` on ListProjects, owner / created-by filters on saved grants, etc. All those tools key off a user api_id (`user_...`), not an email or name. Filters (compose with AND): - search: case-insensitive substring match across first_name, last_name, and email — the workhorse for resolving "John Williams", "john@", or a partial name to a user - email: exact-match email lookup — use only when you already have the full email With no filters, returns every user on the account.
list_users
Save a grant match to a project. Defaults to saving to the project the match belongs to; pass `target_project_id` to save the grant to a different project in the same account. Pass `hide: true` to instead hide ("not interested") the match, so it no longer appears in the project's matches. This is reversible in the Instrumentl app. `target_project_id` is ignored when hiding. Each call creates a new SavedGrant. To remove a grant you previously saved, use the `hide_saved_grant` tool with the SavedGrant id returned here.
save_match
Search grants by natural-language intent (for example, "youth mental health programs in rural areas"). Ranks grants by semantic similarity to the query and returns the closest matches the account can access, most relevant first. Use this when the user describes what they are looking for in prose rather than naming a specific funder or applying an explicit filter.
search_grants
Send a feedback message from the user to the Instrumentl engineering team. Call this only when one of the following is clearly true: - The user has explicitly asked to report a bug, request a feature, or send feedback to the team. - You have already attempted to help with the user's actual task, and the user is still blocked or has expressed unresolved frustration that cannot be solved inside this conversation. DO NOT call this: - Proactively, on the first sign of frustration. Try to help first. - When the user is merely unsure how to do something -- answer the question instead. - More than once per conversation, unless the user explicitly asks to send another message. Before calling, do both of these with the user (do not guess either): 1. Confirm the wording of the `message` -- the team only sees what is passed here. 2. Ask which `category` best fits (bug / feature_request / complaint / other). Do not infer the category yourself unless the user has clearly stated it. The submission is delivered asynchronously to a private Slack channel monitored by engineering and product. There is no follow-up channel here, so do not promise a reply on a specific timeline.
submit_feedback
Update fields on a saved (tracked) grant. Pass the SavedGrant's `id` (e.g. `save_...`) plus only the fields you want to change - omitted fields are left untouched. Updatable fields: - `status`: where the grant is in the pipeline. - `notes`: free-form notes about the opportunity. - `amount_requested` / `amount_awarded`: dollar amounts. - `year`: fiscal year the grant is tracked under. - `notified_at`, `award_period_start_date`, `award_period_end_date`: dates relevant once a grant is awarded. - `owner_id`: the User (`user_...`) to make responsible for the grant, or null to clear the owner. - `project_id`: move the grant to a different project (`proj_...`). Notes: - Setting `status` to `researching` clears the requested amount and submission goals, matching the app's behavior. - To stop tracking a grant, use `hide_saved_grant` instead. Use `list_saved_grants` to find the `saved_grant_id`.
update_saved_grant
Create new tasks and/or update existing tasks in a single best-effort call. Each row in `tasks` is either: - { "op": "create", "saved_grant_id": "save_...", "kind": "...", ...optional fields } - { "op": "update", "id": "task_...", ...fields to change } Rows are processed independently — a failed row does not roll back the others. Use `op: "create"` to add a task to a SavedGrant. `saved_grant_id` and `kind` are required; the calling user becomes the creator and nominator. Use `op: "update"` to change an existing task. Only `id` is required; pass any subset of mutable fields. Pass `done_at` as a timestamp to mark the task complete, or `null` to reopen it. Available kinds: full_proposal, report, general, letter_of_inquiry, cultivation. Resolving a user for `assignee_user_id` or `notify_user_ids`: these must be `user_...` API IDs. If the user names someone by first name, last name, or email, call `list_users` to resolve the API ID first. Do not try to find users via `list_tasks` people filters — those only surface users who already appear on a task, not every member of the account. The response shape is: { "results": [ { "index": 0, "op": "create", "status": "ok", "task": { ... } }, { "index": 1, "op": "update", "status": "failed", "reason": "not_found" } ], "created_count": N, "updated_count": N, "failed_count": N } Each result's `index` matches the input row at the same position. Possible failure reasons: - "not_found": task id doesn't exist or belongs to a different account (update) - "saved_grant_not_found": saved_grant_id doesn't exist or belongs to a different account (create) - "user_not_found": assignee_user_id or notify_user_ids contains a user not in this account - "not_authorized": the caller lacks permission for this row - "invalid": validation failed; see `errors`
upsert_tasks
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.