{"openapi":"3.1.0","info":{"title":"Virtuous (BYOK) API","version":"0.1.0","description":"Virtuous (BYOK) lets an AI assistant read your own Virtuous data through the Virtuous API with a key you supply (Virtuous API key). Read-only: 12 tools (get_current_organization, list_tags, get_campaign, list_campaign_communications, get_segment, get_project, get_project_by_code, get_gift, list_events, find_events, list_volunteer_opportunities, get_grant). The BYOK key travels with each request,...\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://byok-virtuous.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"agent@connectorbay.com","url":"https://connectorbay.com/byok-virtuous/docs"},"termsOfService":"https://connectorbay.com/byok-virtuous/terms"},"servers":[{"url":"https://byok-virtuous.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/byok-virtuous/docs"},"security":[{"upstreamKey":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."},"upstreamKey":{"type":"apiKey","in":"header","name":"X-Upstream-Key","description":"Your own key for the service this connector wraps (bring your own key). Used for that one call only; never stored, logged or cached."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/get_current_organization":{"post":{"operationId":"get_current_organization","summary":"Show the Virtuous organization the API key works in: name, time zone, culture and whether the key's user is an administr","description":"Show the Virtuous organization the API key works in: name, time zone, culture and whether the key's user is an administrator. Use for \"Which Virtuous organization is my API key connected to\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{},"title":"get_current_organizationArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_tags":{"post":{"operationId":"list_tags","summary":"List the contact tags defined in Virtuous with their tag group name, paged. Use for \"Which tags do we use in Virtuous\".","description":"List the contact tags defined in Virtuous with their tag group name, paged. Use for \"Which tags do we use in Virtuous\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"skip":{"anyOf":[{"maximum":1000000,"minimum":0,"type":"integer"},{"type":"null"}],"default":0,"description":"How many records to skip (for paging, default 0).","title":"Skip"},"take":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":20,"description":"How many records to return (1 to 100, default 20).","title":"Take"}},"title":"list_tagsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_campaign":{"post":{"operationId":"get_campaign","summary":"Get one campaign by ID: name, start and end dates, giving goal, new giver goal, gift count goal and archived flag. Use f","description":"Get one campaign by ID: name, start and end dates, giving goal, new giver goal, gift count goal and archived flag. Use for \"What is the giving goal of Virtuous campaign 12\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"campaign_id":{"description":"Numeric Virtuous campaign ID.","title":"Campaign Id","type":"integer"}},"required":["campaign_id"],"title":"get_campaignArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_campaign_communications":{"post":{"operationId":"list_campaign_communications","summary":"List the communications (mailings, emails, calls) of one campaign with channel type, start date, giving goal and linked ","description":"List the communications (mailings, emails, calls) of one campaign with channel type, start date, giving goal and linked project. Use for \"What communications belong to Virtuous campaign 12\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"campaign_id":{"description":"Numeric Virtuous campaign ID.","title":"Campaign Id","type":"integer"},"filter":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Optional text to filter communications by name.","title":"Filter"},"skip":{"anyOf":[{"maximum":1000000,"minimum":0,"type":"integer"},{"type":"null"}],"default":0,"description":"How many records to skip (for paging, default 0).","title":"Skip"},"take":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":20,"description":"How many records to return (1 to 100, default 20).","title":"Take"}},"required":["campaign_id"],"title":"list_campaign_communicationsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_segment":{"post":{"operationId":"get_segment","summary":"Get one segment by ID: name, code, description and the communication and campaign it belongs to. Use for \"What campaign ","description":"Get one segment by ID: name, code, description and the communication and campaign it belongs to. Use for \"What campaign does Virtuous segment 40 belong to\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"segment_id":{"description":"Numeric Virtuous segment ID.","title":"Segment Id","type":"integer"}},"required":["segment_id"],"title":"get_segmentArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_project":{"post":{"operationId":"get_project","summary":"Get one project (fund or designation) by ID: code, type, active and public flags, balance, and life-to-date and calendar","description":"Get one project (fund or designation) by ID: code, type, active and public flags, balance, and life-to-date and calendar-year-to-date giving, gift and giver counts. Use for \"How much has Virtuous project 7 raised this calendar year\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"project_id":{"description":"Numeric Virtuous project ID.","title":"Project Id","type":"integer"}},"required":["project_id"],"title":"get_projectArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_project_by_code":{"post":{"operationId":"get_project_by_code","summary":"Get one project (fund or designation) by its unique project code, with the same totals as get_project. Use for \"Show the","description":"Get one project (fund or designation) by its unique project code, with the same totals as get_project. Use for \"Show the Virtuous project with code GEN\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"project_code":{"description":"Unique project code, for example 'GEN'.","maxLength":200,"title":"Project Code","type":"string"}},"required":["project_code"],"title":"get_project_by_codeArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_gift":{"post":{"operationId":"get_gift","summary":"Get one gift by ID: contact name, type, date, amount, currency, batch, segment, grant and the designations (projects) it","description":"Get one gift by ID: contact name, type, date, amount, currency, batch, segment, grant and the designations (projects) it was applied to. Use for \"Show Virtuous gift 5001\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"gift_id":{"description":"Numeric Virtuous gift ID.","title":"Gift Id","type":"integer"}},"required":["gift_id"],"title":"get_giftArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_events":{"post":{"operationId":"list_events","summary":"List events with type, location, start and end time, RSVP and invite settings, and invite, RSVP, attendance and giving t","description":"List events with type, location, start and end time, RSVP and invite settings, and invite, RSVP, attendance and giving totals. Contact lists of the events are not returned. Use for \"Which Virtuous events are coming up and how many have RSVPed\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"skip":{"anyOf":[{"maximum":1000000,"minimum":0,"type":"integer"},{"type":"null"}],"default":0,"description":"How many records to skip (for paging, default 0).","title":"Skip"},"take":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":20,"description":"How many records to return (1 to 100, default 20).","title":"Take"}},"title":"list_eventsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/find_events":{"post":{"operationId":"find_events","summary":"Search events by a text filter and return matching events with the same fields as list_events. Use for \"Find Virtuous ev","description":"Search events by a text filter and return matching events with the same fields as list_events. Use for \"Find Virtuous events named gala\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"filter":{"description":"Text to search for in event names.","maxLength":100,"title":"Filter","type":"string"}},"required":["filter"],"title":"find_eventsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/list_volunteer_opportunities":{"post":{"operationId":"list_volunteer_opportunities","summary":"List volunteer opportunities with dates, priority, how many volunteers are needed, how many signed up, hours, and the ci","description":"List volunteer opportunities with dates, priority, how many volunteers are needed, how many signed up, hours, and the city of the location. Use for \"Which volunteer opportunities still need people in Virtuous\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"filter":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":null,"description":"Optional text to filter opportunities by name.","title":"Filter"},"skip":{"anyOf":[{"maximum":1000000,"minimum":0,"type":"integer"},{"type":"null"}],"default":0,"description":"How many records to skip (for paging, default 0).","title":"Skip"},"take":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":20,"description":"How many records to return (1 to 100, default 20).","title":"Take"}},"title":"list_volunteer_opportunitiesArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/get_grant":{"post":{"operationId":"get_grant","summary":"Get one grant by ID: title, status, linked project, anticipated and awarded amounts and dates, grant type and website. C","description":"Get one grant by ID: title, status, linked project, anticipated and awarded amounts and dates, grant type and website. Contact details of the grantor are not returned. Use for \"What is the status of Virtuous grant 15\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"grant_id":{"description":"Numeric Virtuous grant ID.","title":"Grant Id","type":"integer"}},"required":["grant_id"],"title":"get_grantArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}