diff --git a/README.md b/README.md index 28af423..735fcc0 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,5 @@ Visit the [Carta Developer Platform website here](https://docs.carta.com/api-pla | Plugin | Description | |--------|-------------| | [carta-cap-table](plugins/carta-cap-table) | Skills and MCP server for querying Carta cap tables, grants, SAFEs, 409A valuations, waterfall scenarios, and more | -| [carta-fund-admin](plugins/carta-fund-admin) | Skills and MCP server for querying Carta fund admin data, including NAV, performance, allocations, and regulatory reporting | +| [carta-crm](plugins/carta-crm) | Manage the Carta CRM conversationally — search, add, update, and enrich investors, companies, contacts, deals, notes, and fundraisings via the public API | +| [carta-investors](plugins/carta-investors) | Skills and MCP server for querying Carta fund admin data, including NAV, performance, allocations, and regulatory reporting | diff --git a/plugins/carta-crm/.claude-plugin/plugin.json b/plugins/carta-crm/.claude-plugin/plugin.json index eae001e..232fc83 100644 --- a/plugins/carta-crm/.claude-plugin/plugin.json +++ b/plugins/carta-crm/.claude-plugin/plugin.json @@ -1,11 +1,11 @@ { "name": "carta-crm", "displayName": "Carta CRM", - "version": "0.5.1", - "description": "Add investors, companies, contacts, deals, and notes to the Carta CRM via the public API", + "version": "0.6.0", + "description": "Manage the Carta CRM conversationally — search, add, update, and enrich investors, companies, contacts, deals, notes, and fundraisings via the public API", "author": { "name": "Ihar Valodzin", "email": "ihar.valodzin@carta.com" }, - "keywords": ["carta", "crm", "investors", "companies", "contacts", "deals", "notes"] + "keywords": ["carta", "crm", "investors", "companies", "contacts", "deals", "notes", "fundraisings", "search", "enrich"] } diff --git a/plugins/carta-crm/README.md b/plugins/carta-crm/README.md index f1a7487..15bdf94 100644 --- a/plugins/carta-crm/README.md +++ b/plugins/carta-crm/README.md @@ -1,6 +1,6 @@ # Carta CRM Plugin -Add investors, companies, contacts, deals, and notes to the Carta CRM via the public API — conversationally. +Manage the Carta CRM conversationally — search, add, update, and enrich investors, companies, contacts, deals, notes, and fundraisings via the public API. ## Setup @@ -26,10 +26,38 @@ Claude will collect any missing required information, then create the record(s) ## Skills +### Add records | Skill | Trigger phrases | |-------|----------------| -| `add-investor` | "/add-investor", "add investor", "add investor to Carta CRM", "create investor record", "add VC fund to CRM" | -| `add-company` | "/add-company", "add a company", "create company record", "add company to CRM", "upload company to Carta CRM" | -| `add-contact` | "/add-contact", "add a contact", "create contact record", "add contact to CRM", "save a contact", "upload contact to Carta CRM" | -| `add-deal` | "/add-deal", "add a deal", "create a deal", "log a deal", "add deal to CRM", "add deal to Carta CRM" | -| `add-note` | "/add-note", "add a note", "create a note", "log a note", "add note to CRM", "add note to Carta CRM" | +| `add-investor` | "add investor", "add investor to Carta CRM", "create investor record", "add VC fund to CRM" | +| `add-company` | "add a company", "create company record", "add company to CRM" | +| `add-contact` | "add a contact", "create contact record", "add contact to CRM", "save a contact" | +| `add-deal` | "add a deal", "create a deal", "log a deal", "add deal to CRM" | +| `add-note` | "add a note", "create a note", "log a note", "add note to CRM" | +| `add-fundraising` | "add a fundraising", "create a fundraising", "log a fundraising round" | + +### Search & retrieve +| Skill | Trigger phrases | +|-------|----------------| +| `search-investors` | "find an investor", "search investors", "look up an investor" | +| `search-companies` | "find a company", "search companies", "look up a company" | +| `search-contacts` | "find a contact", "search contacts", "look up a person" | +| `search-deals` | "find a deal", "search deals", "show me deals for [company]" | +| `search-notes` | "find a note", "search notes", "look up a note" | +| `search-fundraisings` | "find a fundraising", "search fundraisings", "show fundraising pipeline" | + +### Update records +| Skill | Trigger phrases | +|-------|----------------| +| `update-investor` | "update an investor", "edit investor", "update investor details" | +| `update-company` | "update a company", "edit company", "update company details" | +| `update-contact` | "update a contact", "edit contact", "update contact details" | +| `update-deal` | "update a deal", "move deal to [stage]", "change deal stage" | +| `update-note` | "update a note", "edit note", "update note content" | +| `update-fundraising` | "update a fundraising", "edit fundraising", "update fundraising details" | + +### Research & enrichment +| Skill | Trigger phrases | +|-------|----------------| +| `enrich-company` | "enrich this company", "look up company info", "research this company" | +| `lookup-fund-portfolio` | "look up portfolio of [fund]", "get portfolio companies for [fund website]" | diff --git a/plugins/carta-crm/skills/add-fundraising/SKILL.md b/plugins/carta-crm/skills/add-fundraising/SKILL.md new file mode 100644 index 0000000..a78f0dc --- /dev/null +++ b/plugins/carta-crm/skills/add-fundraising/SKILL.md @@ -0,0 +1,91 @@ +--- +name: add-fundraising +description: > + Creates one or more fundraising records in the Carta CRM via the public API. + Use this skill when the user says things like "add a fundraising", "create a fundraising", + "log a fundraising round", "add fundraising to CRM", "create fundraising record", + or "/add-fundraising". Collects fundraising information conversationally, then POSTs + it to the Carta CRM API. +allowed-tools: + - Bash +--- + +## Overview + +Help the user create one or more fundraising records in the Carta CRM by calling +`POST /v1/fundraisings`. Collect the fundraising details conversationally, validate the +required fields, then make the API call using curl. + +## Step 1 — Check credentials + +Check that the required environment variables are set: + +```bash +echo "API_KEY=${LISTALPHA_API_KEY:+set}" +``` + +If `LISTALPHA_API_KEY` is missing, tell the user: +> "You need to set the `LISTALPHA_API_KEY` environment variable to your Carta CRM API key before using this skill. You can add it in Claude's environment settings." + +## Step 2 — Discover available custom fields (optional but recommended) + +Call the custom fields endpoint to see what fields the tenant has configured for fundraisings: + +```bash +curl -s -X GET "https://api.listalpha.com/v1/fundraisings/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Use the returned field names as hints when collecting fundraising data. If the call +fails, proceed without it — custom fields are optional. + +## Step 3 — Collect fundraising information + +Ask the user for: +- **Name** (required) — the fundraising round name (e.g., "Acme Corp Series B", "Project Atlas Seed Round") +- **Additional fields** (optional) — any custom fields returned in Step 2 + +If the user has already provided details in their message, extract them directly +without re-asking. + +## Step 4 — Create the fundraising via API + +Build the request body: +```json +{ + "name": "", + "fields": { + "": "" + } +} +``` + +Omit `fields` entirely if no field data was provided. + +Make the API call: +```bash +curl -s -X POST "https://api.listalpha.com/v1/fundraisings" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '' +``` + +## Step 5 — Report result + +On success (HTTP 200), respond with: +> "Fundraising **{name}** created successfully (ID: `{id}`)." + +On error, show the status code and error message from the response, and suggest fixes: +- **401** — API key is invalid or missing +- **400** — Check that `name` is provided and `fields` contains valid keys +- **500** — Server error; try again or contact support + +## Adding multiple fundraisings + +If the user wants to add multiple fundraisings at once, repeat Steps 3–5 for each +one. After all are done, summarize: +> "Created N fundraisings: [list of names with IDs]" + +## Reference + +See `references/api-reference.md` for endpoint details and field schema. diff --git a/plugins/carta-crm/skills/add-fundraising/references/api-reference.md b/plugins/carta-crm/skills/add-fundraising/references/api-reference.md new file mode 100644 index 0000000..59167ad --- /dev/null +++ b/plugins/carta-crm/skills/add-fundraising/references/api-reference.md @@ -0,0 +1,103 @@ +# Carta CRM Fundraising API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: +``` + +## Environment Variables + +| Variable | Required | Description | +|----------|----------|-------------| +| `LISTALPHA_API_KEY` | Yes | Your Carta CRM API key | + +--- + +## Endpoints + +### GET /v1/fundraisings/custom-fields + +Returns the custom field schema configured for your tenant's fundraising records. +Use this to discover which field keys are valid before creating fundraisings. + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/fundraisings/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response:** +```json +{ + "fields": [ + { "key": "amount", "label": "Amount", "type": "string" }, + { "key": "stage", "label": "Stage", "type": "string" }, + { "key": "status", "label": "Status", "type": "string" }, + { "key": "closeDate", "label": "Close Date", "type": "date" }, + { "key": "tags", "label": "Tags", "type": "array" } + ] +} +``` + +> The actual fields returned depend on your tenant's configuration. + +--- + +### POST /v1/fundraisings + +Creates a new fundraising record. + +**Request body:** +```json +{ + "name": "Acme Corp Series B", + "fields": { + "amount": "50000000", + "stage": "Series B", + "status": "open", + "closeDate": "2026-06-30" + } +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | **Yes** | Fundraising round name | +| `fields` | object | No | Key/value map of custom fields | + +**Success response (200):** +```json +{ + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "name": "Acme Corp Series B", + "fields": { + "amount": "50000000", + "stage": "Series B" + } +} +``` + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Bad request — `name` missing or invalid field keys | +| 401 | Unauthorized — invalid or missing API key | +| 500 | Internal server error | + +--- + +### GET /v1/fundraisings + +List or search existing fundraisings. + +**Query params:** `search` (string), `limit` (number), `offset` (number) + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/fundraisings?search=acme&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` diff --git a/plugins/carta-crm/skills/enrich-company/SKILL.md b/plugins/carta-crm/skills/enrich-company/SKILL.md new file mode 100644 index 0000000..bb9f47d --- /dev/null +++ b/plugins/carta-crm/skills/enrich-company/SKILL.md @@ -0,0 +1,106 @@ +--- +name: enrich-company +description: > + Researches a company by fetching its website and returning structured profile data. + Use this skill when the user says things like "enrich this company", "look up company info", + "research this company", "what does [domain] do", "get company details for [url]", + "find info on [company]", or "/enrich-company". + Input: target (domain name or website URL). + Output: structured JSON with name, industry, tags, description, and website. + Saves the result locally at ~/.carta-crm/enriched-companies/ for auditing. +user-invocable: false +allowed-tools: + - WebFetch + - WebSearch + - Bash +--- + +## Overview + +Enrich a company profile by fetching its website and extracting key business information. +The result is returned as structured JSON and saved locally for auditing. + +## Step 1 — Normalize the target URL + +Take the `target` input and produce a clean `https://` URL: +- If it already starts with `http://` or `https://`, use it as-is. +- If it looks like a bare domain (e.g., `acme.com`), prepend `https://`. +- Strip any trailing paths — use only the root URL (e.g., `https://acme.com`). + +Also extract the bare domain (e.g., `acme.com`) — you'll need it for the output filename. + +## Step 2 — Fetch the company website + +Use WebFetch to retrieve the homepage. Look for: +- Page `` and `<meta name="description">` content +- `<h1>` / `<h2>` headings and hero/tagline text +- Any "About", "What we do", or "Our mission" sections + +If the homepage returns insufficient content (e.g., a login wall, placeholder, or very sparse text), +also try fetching `[root-url]/about` as a fallback. + +## Step 3 — Supplement with web search if needed + +If the website alone doesn't clearly reveal the company's industry or what it does, +run a WebSearch for: + +``` +"[company name]" company what does it do +``` + +Use the top 2–3 results to fill in gaps — especially for `industry` and `description`. + +## Step 4 — Extract structured data + +From the gathered content, produce the following fields: + +| Field | Type | Notes | +|-------|------|-------| +| `name` | string | Official company name (not the domain) | +| `industry` | string | Primary industry, e.g. "FinTech", "SaaS", "Healthcare IT", "Climate Tech" | +| `tags` | array of strings | 3–6 short topic tags, e.g. `["payments", "B2B", "API", "embedded finance"]` | +| `description` | string | 1–2 sentence plain-English summary of what the company does | +| `website` | string | Canonical root URL, e.g. `https://acme.com` | + +Use specific, meaningful tags — avoid generic ones like "technology" or "software" on their own. + +## Step 5 — Save the enrichment record + +Write the JSON to a local audit file: + +```bash +mkdir -p ~/.carta-crm/enriched-companies +cat > ~/.carta-crm/enriched-companies/[domain].json << 'ENDJSON' +{ + "name": "...", + "industry": "...", + "tags": [...], + "description": "...", + "website": "..." +} +ENDJSON +``` + +Replace `[domain]` with the bare domain (e.g., `acme.com`). +Confirm the file was written with `echo $?` (should be 0). + +## Step 6 — Return the result + +Return the enrichment record as a JSON block, followed by the save path: + +```json +{ + "name": "...", + "industry": "...", + "tags": [...], + "description": "...", + "website": "..." +} +``` + +State: `Saved to ~/.carta-crm/enriched-companies/[domain].json` + +## Handling multiple companies + +If the user provides multiple targets, repeat Steps 1–5 for each one, then return all +results together and summarize: `Enriched N companies — saved to ~/.carta-crm/enriched-companies/` diff --git a/plugins/carta-crm/skills/lookup-fund-portfolio/SKILL.md b/plugins/carta-crm/skills/lookup-fund-portfolio/SKILL.md new file mode 100644 index 0000000..2e3afaf --- /dev/null +++ b/plugins/carta-crm/skills/lookup-fund-portfolio/SKILL.md @@ -0,0 +1,105 @@ +--- +name: lookup-fund-portfolio +description: > + Finds and returns the portfolio companies listed on a VC or investment fund's website. + Use this skill when the user says things like "look up portfolio of [fund]", + "get portfolio companies for [fund website]", "what companies does [fund] invest in", + "find portfolio page for [url]", "list investments of [fund]", or "/lookup-fund-portfolio". + Input: fund website URL or domain. Output: structured JSON list of portfolio company names. + Saves the result locally at ~/.carta-crm/fund-portfolios/ for auditing. +user-invocable: false +allowed-tools: + - WebFetch + - WebSearch + - Bash +--- + +## Overview + +Find and extract the portfolio company list from an investment fund's website. +The result is saved locally as a JSON file and returned to the caller. + +## Step 1 — Normalize the target URL + +Take the input and produce a clean root URL: +- If it starts with `http://` or `https://`, use as-is. +- If it's a bare domain (e.g., `sequoiacap.com`), prepend `https://`. +- Strip any path — use the root only (e.g., `https://sequoiacap.com`). + +Also extract the bare domain (e.g., `sequoiacap.com`) for the output filename. + +## Step 2 — Discover the portfolio page + +Try fetching these paths in order, stopping at the first one that returns meaningful company data: + +1. `[root-url]/portfolio` +2. `[root-url]/companies` +3. `[root-url]/investments` +4. `[root-url]/portfolio-companies` +5. `[root-url]/our-portfolio` +6. `[root-url]/founders` + +For each fetch, use this prompt: "List every company name mentioned on this page. Also return the page title so I can identify which fund this is." + +If none of the above return a clear company list, fetch the homepage and look for any navigation links that suggest a portfolio or companies section. Then follow those links. + +## Step 3 — Fallback: web search + +If WebFetch fails to find a usable portfolio page (e.g., JavaScript-heavy SPA, login wall, empty results), run a WebSearch: + +``` +[fund name] portfolio companies site:[domain] +``` + +Or if the fund name is unknown: + +``` +[domain] investment fund portfolio companies list +``` + +Use the search results to either find the direct portfolio URL to retry with WebFetch, or extract company names directly from search snippets. + +## Step 4 — Extract company names + +From the fetched content, extract a clean list of portfolio company names: +- Include only company/startup names — not fund names, investor names, or team members +- Remove duplicates +- Normalize capitalization (use the company's own capitalization where visible) +- Do not include descriptions, sectors, or URLs — names only at this stage +- If the page is paginated or has "Load more", note how many companies were retrieved vs. total shown + +Aim for completeness — capture every visible company name on the page. + +## Step 5 — Save the portfolio record + +Write the result to a local audit file: + +```bash +mkdir -p ~/.carta-crm/fund-portfolios +cat > ~/.carta-crm/fund-portfolios/[domain].json << 'ENDJSON' +{ + "fund": "[fund name]", + "website": "[root url]", + "portfolio_page": "[url used to retrieve data]", + "retrieved_at": "[today's date as YYYY-MM-DD]", + "company_count": [N], + "companies": [ + "Company A", + "Company B", + "Company C" + ] +} +ENDJSON +``` + +Confirm the file was written with `echo $?` (should be 0). + +## Step 6 — Return the result + +Return the full JSON record to the caller. Then summarize: + +> "Found **N portfolio companies** for **[Fund Name]** from [portfolio_page]. Saved to `~/.carta-crm/fund-portfolios/[domain].json`." + +If the list appears incomplete (e.g., page was paginated, or only logos were shown without text names), add a note: + +> "Note: page may be incomplete — only N companies were visible as text. The fund may have more investments not listed." diff --git a/plugins/carta-crm/skills/search-companies/SKILL.md b/plugins/carta-crm/skills/search-companies/SKILL.md new file mode 100644 index 0000000..02108a5 --- /dev/null +++ b/plugins/carta-crm/skills/search-companies/SKILL.md @@ -0,0 +1,85 @@ +--- +name: search-companies +description: > + Searches for and retrieves company records from the Carta CRM. + Use this skill when the user says things like "find a company", "search companies", + "look up a company", "show me company details for [name]", "get company by ID", + "list companies", "what companies do we have", or "/search-companies". + Returns company details including ID, name, and custom fields. + The company ID returned can be used with the update-company skill. +allowed-tools: + - Bash +--- + +## Overview + +Search for companies in the Carta CRM using `GET /v1/companies` (filtered list) or +`GET /v1/companies/{id}` (single company by ID). Return results in a readable summary +and always include the company ID so the user can reference it for updates. + +## Step 1 — Determine search mode + +Based on the user's request, choose one of two modes: + +- **By ID** — user provided a company ID (a hex string like `64f1a2b3c4d5e6f7a8b9c0d1`) → use `GET /v1/companies/{id}` +- **By search / filter** — user provided a name or keyword → use `GET /v1/companies` with query params + +If it's unclear, default to **By search / filter** and ask the user for a search term. + +## Step 2 — Execute the search + +**By ID:** +```bash +curl -s "https://api.listalpha.com/v1/companies/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**By search / filter:** + +```bash +curl -s "https://api.listalpha.com/v1/companies?search=<term>&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Available query parameters: + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Company name or keyword | +| `limit` | integer | Max results (default to 20 unless user specifies) | +| `offset` | integer | Skip N results for pagination | + +Omit any params the user did not specify. + +## Step 3 — Present results + +For each company returned, display: + +``` +Company: <name> (ID: `<id>`) + Website: <website> + Location: <location> + Industry: <industry> + About: <about> + Tags: <tags> + Added: <createdAt> +``` + +Omit any fields that are blank or not present. + +If no companies are found: +> "No companies found matching your search. Try a different name or keyword." + +If multiple results are returned, list them all and note the total count. + +Always surface the company ID prominently — the user will need it to run `/update-company`. + +## Error handling + +- **401** — API key is invalid or missing +- **404** — No company found with that ID +- **400 / 500** — Show the error message from the response + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/search-companies/references/api-reference.md b/plugins/carta-crm/skills/search-companies/references/api-reference.md new file mode 100644 index 0000000..bc84968 --- /dev/null +++ b/plugins/carta-crm/skills/search-companies/references/api-reference.md @@ -0,0 +1,80 @@ +# Carta CRM Search Companies API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### GET /v1/companies + +List or search companies with pagination. + +**Query parameters:** + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Company name or keyword | +| `limit` | integer | Max results per request | +| `offset` | integer | Results to skip (for pagination) | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/companies?search=stripe&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** +```json +{ + "companies": [ + { + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "name": "Stripe", + "fields": { + "website": "https://stripe.com", + "location": "San Francisco, CA", + "industry": "Fintech", + "about": "Global payments infrastructure company", + "tags": ["fintech", "series-a"] + }, + "createdAt": "2026-01-15T00:00:00Z", + "updatedAt": "2026-03-01T00:00:00Z" + } + ] +} +``` + +--- + +### GET /v1/companies/{id} + +Returns a single company by its unique identifier. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Company identifier | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/companies/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** Same shape as a single company object in the list response above. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 401 | Unauthorized — invalid or missing API key | +| 404 | No company found with that ID | +| 500 | Internal server error | diff --git a/plugins/carta-crm/skills/search-contacts/SKILL.md b/plugins/carta-crm/skills/search-contacts/SKILL.md new file mode 100644 index 0000000..0ea19b3 --- /dev/null +++ b/plugins/carta-crm/skills/search-contacts/SKILL.md @@ -0,0 +1,86 @@ +--- +name: search-contacts +description: > + Searches for and retrieves contact (people) records from the Carta CRM. + Use this skill when the user says things like "find a contact", "search contacts", + "look up a person", "show me contact details for [name]", "get contact by ID", + "list contacts", "find people at [company]", "search people", or "/search-contacts". + Returns contact details including ID, name, email, title, company, and tags. + The contact ID returned can be used with the update-contact skill. +allowed-tools: + - Bash +--- + +## Overview + +Search for contacts in the Carta CRM using `GET /v1/contacts` (filtered list) or +`GET /v1/contacts/{id}` (single contact by ID). Return results in a readable summary +and always include the contact ID so the user can reference it for updates. + +## Step 1 — Determine search mode + +Based on the user's request, choose one of two modes: + +- **By ID** — user provided a contact ID (a hex string like `64f1a2b3c4d5e6f7a8b9c0d1`) → use `GET /v1/contacts/{id}` +- **By search / filter** — user provided a name, email, or keyword → use `GET /v1/contacts` with query params + +If it's unclear, default to **By search / filter** and ask the user for a search term. + +## Step 2 — Execute the search + +**By ID:** +```bash +curl -s "https://api.listalpha.com/v1/contacts/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**By search / filter:** + +```bash +curl -s "https://api.listalpha.com/v1/contacts?search=<term>&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Available query parameters: + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Contact name, email, or keyword | +| `listId` | string | Filter by list ID | +| `limit` | integer | Max results (default to 20 unless user specifies) | +| `offset` | integer | Skip N results for pagination | + +Omit any params the user did not specify. + +## Step 3 — Present results + +For each contact returned, display: + +``` +Contact: <name> (ID: `<id>`) + Title: <title> at <company> + Email: <emailDetail> + Phone: <phone> + LinkedIn: <linkedIn> + Tags: <tags> + Notes: <notes> +``` + +Omit any fields that are blank or not present. + +If no contacts are found: +> "No contacts found matching your search. Try a different name, email, or keyword." + +If multiple results are returned, list them all and note the total count. + +Always surface the contact ID prominently — the user will need it to run `/update-contact`. + +## Error handling + +- **401** — API key is invalid or missing +- **404** — No contact found with that ID +- **400 / 500** — Show the error message from the response + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/search-contacts/references/api-reference.md b/plugins/carta-crm/skills/search-contacts/references/api-reference.md new file mode 100644 index 0000000..71b0d27 --- /dev/null +++ b/plugins/carta-crm/skills/search-contacts/references/api-reference.md @@ -0,0 +1,84 @@ +# Carta CRM Search Contacts API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### GET /v1/contacts + +List or search contacts with pagination. + +**Query parameters:** + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Contact name, email, or keyword | +| `listId` | string | Filter by list ID | +| `limit` | integer | Max results per request | +| `offset` | integer | Results to skip (for pagination) | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/contacts?search=jane+smith&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** +```json +{ + "contacts": [ + { + "id": "64f1a2b3c4d5e6f7a8b9c0d2", + "name": "Jane Smith", + "firstName": "Jane", + "lastName": "Smith", + "emailDetail": "jane@example.com", + "phone": "+1 415 555 0100", + "title": "Partner", + "company": "Acme Ventures", + "linkedIn": "https://linkedin.com/in/janesmith", + "tags": ["investor", "partner"], + "notes": "Met at SaaStr 2026", + "listId": "64f1a2b3c4d5e6f7a8b9c0d1", + "createdAt": "2026-01-15T00:00:00Z", + "updatedAt": "2026-03-01T00:00:00Z" + } + ] +} +``` + +--- + +### GET /v1/contacts/{id} + +Returns a single contact by its unique identifier. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Contact identifier | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/contacts/64f1a2b3c4d5e6f7a8b9c0d2" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** Same shape as a single contact object in the list response above. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 401 | Unauthorized — invalid or missing API key | +| 404 | No contact found with that ID | +| 500 | Internal server error | diff --git a/plugins/carta-crm/skills/search-deals/SKILL.md b/plugins/carta-crm/skills/search-deals/SKILL.md new file mode 100644 index 0000000..558126f --- /dev/null +++ b/plugins/carta-crm/skills/search-deals/SKILL.md @@ -0,0 +1,97 @@ +--- +name: search-deals +description: > + Searches for and retrieves deal records from the Carta CRM. + Use this skill when the user says things like "find a deal", "search deals", + "look up a deal", "show me deals for [company]", "get deal by ID", "find deal in [pipeline/stage]", + "list deals", "what deals do we have for [company]", or "/search-deals". + Returns deal details including ID, company, stage, pipeline, tags, and custom fields. + The deal ID returned can be used with the update-deal skill. +allowed-tools: + - Bash +--- + +## Overview + +Search for deals in the Carta CRM using `GET /v1/deals` (filtered list) or +`GET /v1/deals/{id}` (single deal by ID). Return results in a readable summary +and always include the deal ID so the user can reference it for updates. + +## Step 1 — Determine search mode + +Based on the user's request, choose one of two modes: + +- **By ID** — user provided a deal ID (a hex string like `64f1a2b3c4d5e6f7a8b9c0d1`) → use `GET /v1/deals/{id}` +- **By search / filter** — user provided a company name, keyword, stage, or pipeline → use `GET /v1/deals` with query params + +If it's unclear, default to **By search / filter** and ask the user for a search term. + +## Step 2 — Fetch pipeline context (for filter mode) + +If the user mentioned a pipeline or stage by name, fetch pipelines first to resolve names to IDs: + +```bash +curl -s "https://api.listalpha.com/v1/deals/pipelines" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Match the user's pipeline/stage name to the corresponding `id`. Skip this step if the user didn't specify a pipeline or stage, or if they provided IDs directly. + +## Step 3 — Execute the search + +**By ID:** +```bash +curl -s "https://api.listalpha.com/v1/deals/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**By search / filter:** + +Build a query string from the available parameters and call: + +```bash +curl -s "https://api.listalpha.com/v1/deals?search=<term>&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Available query parameters: + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Company name or keyword | +| `pipelines` | array | Filter by pipeline ID(s) — repeat param for multiple: `?pipelines=id1&pipelines=id2` | +| `stages` | array | Filter by stage ID(s) — repeat param for multiple | +| `limit` | integer | Max results (default to 20 unless user specifies) | +| `offset` | integer | Skip N results for pagination | + +Omit any params the user did not specify. + +## Step 4 — Present results + +For each deal returned, display: + +``` +Deal: <company name> (ID: `<id>`) + Pipeline: <pipelineId> | Stage: <stageId> + Tags: <tags> + Comment: <comment> + Added: <addedAt> + Custom fields: <fields> +``` + +If no deals are found: +> "No deals found matching your search. Try a different company name or check the pipeline filter." + +If multiple results are returned, list them all and note the total count. + +Always surface the deal ID prominently — the user will need it to run `/update-deal`. + +## Error handling + +- **401** — API key is invalid or missing +- **404** — No deal found with that ID +- **400 / 500** — Show the error message from the response + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/search-deals/references/api-reference.md b/plugins/carta-crm/skills/search-deals/references/api-reference.md new file mode 100644 index 0000000..6094aae --- /dev/null +++ b/plugins/carta-crm/skills/search-deals/references/api-reference.md @@ -0,0 +1,101 @@ +# Carta CRM Search Deals API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### GET /v1/deals + +List or filter deals with pagination. + +**Query parameters:** + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Company name or keyword | +| `pipelines` | array | Filter by pipeline ID(s) — repeat for multiple: `?pipelines=id1&pipelines=id2` | +| `stages` | array | Filter by stage ID(s) — repeat for multiple | +| `limit` | integer | Max results per request | +| `offset` | integer | Results to skip (for pagination) | + +If `pipelineId` is not specified, the default pipeline is used. To search across other pipelines, pass `pipelines` explicitly. + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/deals?search=stripe&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** +```json +{ + "deals": [ + { + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "company": { "name": "Stripe", "url": "https://stripe.com" }, + "comment": "Warm intro from partner", + "tags": ["fintech"], + "creatorId": "...", + "pipelineId": "...", + "stageId": "...", + "addedAt": "2026-01-15T00:00:00Z", + "createdAt": "2026-01-15T00:00:00Z", + "updatedAt": "2026-03-01T00:00:00Z", + "dealLead": "...", + "fields": {}, + "people": { + "advisers": [], + "introducer": [], + "management": [] + } + } + ] +} +``` + +--- + +### GET /v1/deals/{id} + +Returns a single deal by its unique identifier. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Deal identifier | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/deals/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** Same shape as a single deal object in the list response above. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 401 | Unauthorized — invalid or missing API key | +| 404 | No deal found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/deals/pipelines + +Returns all pipelines and their stages — use this to resolve stage/pipeline names to IDs. + +```bash +curl -s "https://api.listalpha.com/v1/deals/pipelines" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` diff --git a/plugins/carta-crm/skills/search-fundraisings/SKILL.md b/plugins/carta-crm/skills/search-fundraisings/SKILL.md new file mode 100644 index 0000000..7a9b853 --- /dev/null +++ b/plugins/carta-crm/skills/search-fundraisings/SKILL.md @@ -0,0 +1,73 @@ +--- +name: search-fundraisings +description: > + Searches for and retrieves fundraising records from the Carta CRM. + Use this skill when the user says things like "find a fundraising", "search fundraisings", + "look up a fundraising round", "show fundraising details for [company]", "get fundraising by ID", + "list fundraisings", "what fundraisings do we have", or "/search-fundraisings". + Returns fundraising details including ID, name, amount, stage, and associated company. + The fundraising ID returned can be used with the update-fundraising skill. +allowed-tools: + - Bash +--- + +## Overview + +Search for fundraisings in the Carta CRM using `GET /v1/fundraisings` (filtered list) or +`GET /v1/fundraisings/{id}` (single record by ID). Return results in a readable summary +and always include the fundraising ID so the user can reference it for updates. + +## Step 1 — Determine search mode + +Based on the user's request, choose one of two modes: + +- **By ID** — user provided a fundraising ID (a hex string like `64f1a2b3c4d5e6f7a8b9c0d1`) → use `GET /v1/fundraisings/{id}` +- **By search / filter** — user provided a company name, round type, or keyword → use `GET /v1/fundraisings` with query params + +If it's unclear, default to **By search / filter** and ask the user for a search term. + +## Step 2 — Execute the search + +**By ID:** +```bash +curl -s "https://api.listalpha.com/v1/fundraisings/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**By search / filter:** + +```bash +curl -s "https://api.listalpha.com/v1/fundraisings?search=<term>&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Available query parameters: + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Company name or keyword | +| `limit` | integer | Max results (default to 20 unless user specifies) | +| `offset` | integer | Skip N results for pagination | + +Omit any params the user did not specify. + +## Step 3 — Present results + +For each fundraising returned, display all non-empty fields in a readable summary, including the ID prominently. The exact field shape depends on the tenant's custom field configuration — display whatever the API returns. + +If no fundraisings are found: +> "No fundraisings found matching your search. Try a different company name or keyword." + +If multiple results are returned, list them all and note the total count. + +Always surface the fundraising ID prominently — the user will need it to run `/update-fundraising`. + +## Error handling + +- **401** — API key is invalid or missing +- **404** — No fundraising found with that ID +- **400 / 500** — Show the error message from the response + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/search-fundraisings/references/api-reference.md b/plugins/carta-crm/skills/search-fundraisings/references/api-reference.md new file mode 100644 index 0000000..c43d7ea --- /dev/null +++ b/plugins/carta-crm/skills/search-fundraisings/references/api-reference.md @@ -0,0 +1,87 @@ +# Carta CRM Search Fundraisings API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### GET /v1/fundraisings + +List or search fundraisings with pagination. + +**Query parameters:** + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Company name or keyword | +| `limit` | integer | Max results per request | +| `offset` | integer | Results to skip (for pagination) | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/fundraisings?search=acme&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** +```json +{ + "fundraisings": [ + { + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "name": "Acme Corp Series B", + "fields": {}, + "createdAt": "2026-01-15T00:00:00Z", + "updatedAt": "2026-03-01T00:00:00Z" + } + ] +} +``` + +> **Note:** The exact field shape for fundraising records depends on the tenant's custom field configuration. Inspect the actual API response for the full schema. + +--- + +### GET /v1/fundraisings/{id} + +Returns a single fundraising record by its unique identifier. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Fundraising identifier | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/fundraisings/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** Same shape as a single fundraising object in the list response above. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 401 | Unauthorized — invalid or missing API key | +| 404 | No fundraising found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/fundraisings/custom-fields + +Returns the custom field schema configured for your tenant's fundraising records. + +```bash +curl -s "https://api.listalpha.com/v1/fundraisings/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` diff --git a/plugins/carta-crm/skills/search-investors/SKILL.md b/plugins/carta-crm/skills/search-investors/SKILL.md new file mode 100644 index 0000000..f7e036b --- /dev/null +++ b/plugins/carta-crm/skills/search-investors/SKILL.md @@ -0,0 +1,87 @@ +--- +name: search-investors +description: > + Searches for and retrieves investor records from the Carta CRM. + Use this skill when the user says things like "find an investor", "search investors", + "look up an investor", "show me investor details for [name]", "get investor by ID", + "list investors", "what investors do we have", or "/search-investors". + Returns investor details including ID, name, and custom fields. + The investor ID returned can be used with the update-investor skill. +allowed-tools: + - Bash +--- + +## Overview + +Search for investors in the Carta CRM using `GET /v1/investors` (filtered list) or +`GET /v1/investors/{id}` (single investor by ID). Return results in a readable summary +and always include the investor ID so the user can reference it for updates. + +## Step 1 — Determine search mode + +Based on the user's request, choose one of two modes: + +- **By ID** — user provided an investor ID (a hex string like `64f1a2b3c4d5e6f7a8b9c0d1`) → use `GET /v1/investors/{id}` +- **By search / filter** — user provided a name or keyword → use `GET /v1/investors` with query params + +If it's unclear, default to **By search / filter** and ask the user for a search term. + +## Step 2 — Execute the search + +**By ID:** +```bash +curl -s "https://api.listalpha.com/v1/investors/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**By search / filter:** + +Build a query string from the available parameters and call: + +```bash +curl -s "https://api.listalpha.com/v1/investors?search=<term>&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Available query parameters: + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Investor name or keyword | +| `limit` | integer | Max results (default to 20 unless user specifies) | +| `offset` | integer | Skip N results for pagination | + +Omit any params the user did not specify. + +## Step 3 — Present results + +For each investor returned, display: + +``` +Investor: <name> (ID: `<id>`) + Website: <website> + Location: <location> + Industry: <industry> + About: <about> + Tags: <tags> + Added: <createdAt> +``` + +Omit any fields that are blank or not present. + +If no investors are found: +> "No investors found matching your search. Try a different name or keyword." + +If multiple results are returned, list them all and note the total count. + +Always surface the investor ID prominently — the user will need it to run `/update-investor`. + +## Error handling + +- **401** — API key is invalid or missing +- **404** — No investor found with that ID +- **400 / 500** — Show the error message from the response + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/search-investors/references/api-reference.md b/plugins/carta-crm/skills/search-investors/references/api-reference.md new file mode 100644 index 0000000..3779999 --- /dev/null +++ b/plugins/carta-crm/skills/search-investors/references/api-reference.md @@ -0,0 +1,80 @@ +# Carta CRM Search Investors API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### GET /v1/investors + +List or search investors with pagination. + +**Query parameters:** + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Investor name or keyword | +| `limit` | integer | Max results per request | +| `offset` | integer | Results to skip (for pagination) | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/investors?search=sequoia&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** +```json +{ + "investors": [ + { + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "name": "Sequoia Capital", + "fields": { + "website": "https://sequoiacap.com", + "location": "Menlo Park, CA", + "industry": "Venture Capital", + "about": "Global venture capital firm", + "tags": ["tier-1", "series-a"] + }, + "createdAt": "2026-01-15T00:00:00Z", + "updatedAt": "2026-03-01T00:00:00Z" + } + ] +} +``` + +--- + +### GET /v1/investors/{id} + +Returns a single investor by its unique identifier. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Investor identifier | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/investors/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** Same shape as a single investor object in the list response above. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 401 | Unauthorized — invalid or missing API key | +| 404 | No investor found with that ID | +| 500 | Internal server error | diff --git a/plugins/carta-crm/skills/search-notes/SKILL.md b/plugins/carta-crm/skills/search-notes/SKILL.md new file mode 100644 index 0000000..944702c --- /dev/null +++ b/plugins/carta-crm/skills/search-notes/SKILL.md @@ -0,0 +1,84 @@ +--- +name: search-notes +description: > + Searches for and retrieves note records from the Carta CRM. + Use this skill when the user says things like "find a note", "search notes", + "look up a note", "show me notes about [topic]", "get note by ID", + "list notes", "find notes in [folder]", or "/search-notes". + Returns note details including ID, title, text, folder, and owner. + The note ID returned can be used with the update-note skill. +allowed-tools: + - Bash +--- + +## Overview + +Search for notes in the Carta CRM using `GET /v1/notes` (filtered list) or +`GET /v1/notes/{id}` (single note by ID). Return results in a readable summary +and always include the note ID so the user can reference it for updates. + +## Step 1 — Determine search mode + +Based on the user's request, choose one of two modes: + +- **By ID** — user provided a note ID (a hex string like `64f1a2b3c4d5e6f7a8b9c0d1`) → use `GET /v1/notes/{id}` +- **By search / filter** — user provided a title, keyword, or folder → use `GET /v1/notes` with query params + +If it's unclear, default to **By search / filter** and ask the user for a search term. + +## Step 2 — Execute the search + +**By ID:** +```bash +curl -s "https://api.listalpha.com/v1/notes/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**By search / filter:** + +```bash +curl -s "https://api.listalpha.com/v1/notes?search=<term>&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Available query parameters: + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Note title or keyword | +| `folderId` | string | Filter by folder ID | +| `limit` | integer | Max results (default to 20 unless user specifies) | +| `offset` | integer | Skip N results for pagination | + +Omit any params the user did not specify. + +## Step 3 — Present results + +For each note returned, display: + +``` +Note: <title> (ID: `<id>`) + Owner: <owner> + Folder: <folderId> + Created: <creationDate> + Text: <text (truncated to ~200 chars if long)> +``` + +Omit any fields that are blank or not present. + +If no notes are found: +> "No notes found matching your search. Try a different title or keyword." + +If multiple results are returned, list them all and note the total count. + +Always surface the note ID prominently — the user will need it to run `/update-note`. + +## Error handling + +- **401** — API key is invalid or missing +- **404** — No note found with that ID +- **400 / 500** — Show the error message from the response + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/search-notes/references/api-reference.md b/plugins/carta-crm/skills/search-notes/references/api-reference.md new file mode 100644 index 0000000..442b3c1 --- /dev/null +++ b/plugins/carta-crm/skills/search-notes/references/api-reference.md @@ -0,0 +1,79 @@ +# Carta CRM Search Notes API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### GET /v1/notes + +List or search notes with pagination. + +**Query parameters:** + +| Param | Type | Description | +|-------|------|-------------| +| `search` | string | Note title or keyword | +| `folderId` | string | Filter by folder ID | +| `limit` | integer | Max results per request | +| `offset` | integer | Results to skip (for pagination) | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/notes?search=investor+call&limit=20" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** +```json +{ + "notes": [ + { + "id": "64f1a2b3c4d5e6f7a8b9c0d2", + "title": "Q1 Investor Call", + "text": "Discussed Series B timeline and product roadmap.", + "folderId": "64f1a2b3c4d5e6f7a8b9c0d1", + "owner": "analyst@fund.com", + "creationDate": "2026-04-07T10:00:00Z", + "uid": "ext-system-id-123", + "createdAt": "2026-04-07T10:00:00Z", + "updatedAt": "2026-04-07T10:00:00Z" + } + ] +} +``` + +--- + +### GET /v1/notes/{id} + +Returns a single note by its unique identifier. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Note identifier | + +**Example:** +```bash +curl -s "https://api.listalpha.com/v1/notes/64f1a2b3c4d5e6f7a8b9c0d2" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +**Response (200):** Same shape as a single note object in the list response above. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 401 | Unauthorized — invalid or missing API key | +| 404 | No note found with that ID | +| 500 | Internal server error | diff --git a/plugins/carta-crm/skills/update-company/SKILL.md b/plugins/carta-crm/skills/update-company/SKILL.md new file mode 100644 index 0000000..c80b73a --- /dev/null +++ b/plugins/carta-crm/skills/update-company/SKILL.md @@ -0,0 +1,104 @@ +--- +name: update-company +description: > + Updates an existing company record in the Carta CRM. + Use this skill when the user says things like "update a company", "edit company", + "update company details", "change company name", "update company website", + "update company fields", "add a tag to company", or "/update-company". + Accepts a company ID or name (will search if no ID provided). + Only the fields explicitly provided are changed — all other fields are left untouched. +allowed-tools: + - Bash +--- + +## Overview + +Partially update an existing company using `PATCH /v1/companies/{id}`. +Only fields provided in the request body are modified — this is a partial update, +not a replacement. First resolve the company ID, then collect what to change, +then make the API call. + +## Step 1 — Resolve the company ID + +If the user provided a company ID directly, use it and skip to Step 3. + +If only a name or description was given, search for the company first: + +```bash +curl -s "https://api.listalpha.com/v1/companies?search=<name>&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +If multiple companies match, present the list to the user and ask them to confirm which one to update (show name and ID for each). + +## Step 2 — Collect what to update + +Ask the user what they want to change. Any combination of the following fields can be updated: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Company name | +| `fields` | object | Custom field values — keyed by field name (e.g. `website`, `location`, `industry`, `about`, `tags`) | + +If the user has already specified what to change in their message, extract it directly without re-asking. + +**Important:** Only include fields that are explicitly being changed. Omit everything else. + +## Step 3 — Fetch custom fields (if updating custom fields) + +If the user wants to update custom fields but didn't specify field keys, fetch the schema first: + +```bash +curl -s "https://api.listalpha.com/v1/companies/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Use the returned field keys and labels to map the user's input to the correct `fields` object. + +## Step 4 — Update the company via API + +Build the request body with only the fields being changed: + +```json +{ + "name": "<updated name>", + "fields": { + "website": "<url>", + "location": "<location>", + "industry": "<industry>", + "about": "<description>", + "tags": ["<tag1>", "<tag2>"] + } +} +``` + +Omit `name` if it is not being changed. Omit `fields` entirely if no custom fields are being changed. Only include the specific keys within `fields` that are being updated. + +Make the API call: + +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/companies/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '<json_body>' +``` + +## Step 5 — Report result + +On success (HTTP 200), respond with a summary of what changed: +> "Company **{name}** updated (ID: `{id}`). {Changed: website updated, tags added, etc.}" + +On error: +- **401** — API key is invalid or missing +- **400** — Check that field keys are valid +- **404** — No company found with that ID — suggest running `/search-companies` first +- **500** — Server error; try again or contact support + +## Updating multiple companies + +If the user wants to apply the same change to multiple companies, repeat Steps 1 and 4–5 for each. Summarize at the end: +> "Updated N companies: [list of names]" + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/update-company/references/api-reference.md b/plugins/carta-crm/skills/update-company/references/api-reference.md new file mode 100644 index 0000000..561ecef --- /dev/null +++ b/plugins/carta-crm/skills/update-company/references/api-reference.md @@ -0,0 +1,94 @@ +# Carta CRM Update Company API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### PATCH /v1/companies/{id} + +Partially updates an existing company. Only fields provided in the request body are modified — all other fields remain unchanged. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Company identifier | + +**Request body (all fields optional):** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Company name | +| `fields` | object | Custom field values keyed by field name | + +**Common custom field keys:** + +| Key | Type | Description | +|-----|------|-------------| +| `website` | string | Company website URL | +| `location` | string | Geographic location | +| `industry` | string | Industry sector | +| `about` | string | Description or notes | +| `tags` | array | List of tag strings | + +**Example — update website:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/companies/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"fields": {"website": "https://stripe.com"}}' +``` + +**Example — update name and tags:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/companies/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"name": "Stripe Inc.", "fields": {"tags": ["fintech", "payments"]}}' +``` + +**Response (200):** Returns the full updated company object: +```json +{ + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "name": "Stripe Inc.", + "fields": { + "website": "https://stripe.com", + "location": "San Francisco, CA", + "industry": "Fintech", + "tags": ["fintech", "payments"] + } +} +``` + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Validation error — invalid field keys | +| 401 | Unauthorized — invalid or missing API key | +| 404 | No company found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/companies + +Use this to find a company ID before updating. See `search-companies` skill for full details. + +### GET /v1/companies/custom-fields + +Use this to discover available custom field keys before updating `fields`. + +```bash +curl -s "https://api.listalpha.com/v1/companies/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` diff --git a/plugins/carta-crm/skills/update-contact/SKILL.md b/plugins/carta-crm/skills/update-contact/SKILL.md new file mode 100644 index 0000000..289e1c2 --- /dev/null +++ b/plugins/carta-crm/skills/update-contact/SKILL.md @@ -0,0 +1,103 @@ +--- +name: update-contact +description: > + Updates an existing contact (person) record in the Carta CRM. + Use this skill when the user says things like "update a contact", "edit contact", + "update contact details", "change contact email", "update person's title", + "update contact company", "add a tag to contact", or "/update-contact". + Accepts a contact ID or name (will search if no ID provided). + Only the fields explicitly provided are changed — all other fields are left untouched. +allowed-tools: + - Bash +--- + +## Overview + +Partially update an existing contact using `PATCH /v1/contacts/{id}`. +Only fields provided in the request body are modified — this is a partial update, +not a replacement. First resolve the contact ID, then collect what to change, +then make the API call. + +## Step 1 — Resolve the contact ID + +If the user provided a contact ID directly, use it and skip to Step 3. + +If only a name or description was given, search for the contact first: + +```bash +curl -s "https://api.listalpha.com/v1/contacts?search=<name>&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +If multiple contacts match, present the list to the user and ask them to confirm which one to update (show name, title, company, and ID for each). + +## Step 2 — Collect what to update + +Ask the user what they want to change. Any combination of the following fields can be updated: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Contact's full name | +| `firstName` | string | First name | +| `middleName` | string | Middle name | +| `lastName` | string | Last name | +| `emailDetail` | string | Primary email address | +| `emailDetailSecond` | string | Second email address | +| `emailDetailThird` | string | Third email address | +| `emailDetailFourth` | string | Fourth email address | +| `phone` | string | Primary phone number | +| `businessPhone` | string | Business phone number | +| `title` | string | Job title | +| `company` | string | Employer/company name | +| `linkedIn` | string | LinkedIn profile URL | +| `tags` | array | Replace the full tags array | +| `notes` | string | Free-text notes | + +If the user has already specified what to change in their message, extract it directly without re-asking. + +**Important:** Only include fields that are explicitly being changed. Omit everything else. + +## Step 3 — Update the contact via API + +Build the request body with only the fields being changed: + +```json +{ + "name": "<full name>", + "title": "<job title>", + "company": "<employer>", + "emailDetail": "<email>", + "phone": "<phone>", + "tags": ["<tag1>", "<tag2>"], + "notes": "<notes>" +} +``` + +Make the API call: + +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/contacts/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '<json_body>' +``` + +## Step 4 — Report result + +On success (HTTP 200), respond with a summary of what changed: +> "Contact **{name}** updated (ID: `{id}`). {Changed: title updated, email added, etc.}" + +On error: +- **401** — API key is invalid or missing +- **400** — Check that field keys are valid +- **404** — No contact found with that ID — suggest running `/search-contacts` first +- **500** — Server error; try again or contact support + +## Updating multiple contacts + +If the user wants to apply the same change to multiple contacts, repeat Steps 1 and 3–4 for each. Summarize at the end: +> "Updated N contacts: [list of names]" + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/update-contact/references/api-reference.md b/plugins/carta-crm/skills/update-contact/references/api-reference.md new file mode 100644 index 0000000..47c6680 --- /dev/null +++ b/plugins/carta-crm/skills/update-contact/references/api-reference.md @@ -0,0 +1,86 @@ +# Carta CRM Update Contact API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### PATCH /v1/contacts/{id} + +Partially updates an existing contact. Only fields provided in the request body are modified — all other fields remain unchanged. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Contact identifier | + +**Request body (all fields optional):** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Contact's full name | +| `firstName` | string | First name | +| `middleName` | string | Middle name | +| `lastName` | string | Last name | +| `emailDetail` | string | Primary email address | +| `emailDetailSecond` | string | Second email address | +| `emailDetailThird` | string | Third email address | +| `emailDetailFourth` | string | Fourth email address | +| `phone` | string | Primary phone number | +| `businessPhone` | string | Business phone number | +| `title` | string | Job title | +| `company` | string | Employer/company name | +| `linkedIn` | string | LinkedIn profile URL | +| `tags` | array | Replace the full tags array | +| `notes` | string | Free-text notes | + +**Example — update title and company:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/contacts/64f1a2b3c4d5e6f7a8b9c0d2" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"title": "Managing Partner", "company": "Acme Ventures"}' +``` + +**Example — update email and tags:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/contacts/64f1a2b3c4d5e6f7a8b9c0d2" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"emailDetail": "jane.smith@acme.com", "tags": ["investor", "warm"]}' +``` + +**Response (200):** Returns the full updated contact object: +```json +{ + "id": "64f1a2b3c4d5e6f7a8b9c0d2", + "name": "Jane Smith", + "title": "Managing Partner", + "company": "Acme Ventures", + "emailDetail": "jane.smith@acme.com", + "tags": ["investor", "warm"] +} +``` + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Validation error — invalid field keys | +| 401 | Unauthorized — invalid or missing API key | +| 404 | No contact found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/contacts + +Use this to find a contact ID before updating. See `search-contacts` skill for full details. diff --git a/plugins/carta-crm/skills/update-deal/SKILL.md b/plugins/carta-crm/skills/update-deal/SKILL.md new file mode 100644 index 0000000..be8ced8 --- /dev/null +++ b/plugins/carta-crm/skills/update-deal/SKILL.md @@ -0,0 +1,134 @@ +--- +name: update-deal +description: > + Updates an existing deal record in the Carta CRM. + Use this skill when the user says things like "update a deal", "move deal to [stage]", + "change deal stage", "edit deal", "update deal fields", "add a tag to deal", + "assign deal lead", "update company info on deal", "link contacts to deal", + or "/update-deal". + Accepts a deal ID or company name (will search if no ID provided). + Only the fields explicitly provided are changed — all other fields are left untouched. +allowed-tools: + - Bash +--- + +## Overview + +Partially update an existing deal using `PATCH /v1/deals/{id}`. +Only fields provided in the request body are modified — this is a partial update, +not a replacement. First resolve the deal ID, then collect what to change, +then make the API call. + +## Step 1 — Resolve the deal ID + +If the user provided a deal ID directly, use it and skip to Step 3. + +If only a company name or description was given, search for the deal first: + +```bash +curl -s "https://api.listalpha.com/v1/deals?search=<company name>&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +If multiple deals match, present the list to the user and ask them to confirm which one to update (show company name, stage, and ID for each). + +## Step 2 — Fetch pipeline context (if moving stages) + +If the user wants to move the deal to a different stage or pipeline, fetch pipelines to resolve names to IDs: + +```bash +curl -s "https://api.listalpha.com/v1/deals/pipelines" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Present the available pipelines and stages by name. Skip this step if the user already provided a `stageId` directly. + +## Step 3 — Collect what to update + +Ask the user what they want to change. Any combination of the following fields can be updated: + +| Field | Type | Description | +|-------|------|-------------| +| `stageId` | string | Move deal to a different stage | +| `company.name` | string | Update the associated company name | +| `company.url` | string | Update company URL — triggers auto-enrichment | +| `comment` | string | Replace the deal comment/notes | +| `tags` | array | Replace the full tags array | +| `dealLead` | string | User ID to assign as deal lead | +| `addedAt` | date-time | ISO 8601 date the deal was added | +| `fields` | object | Custom field values keyed by field ID | +| `people.advisers` | array | Contact IDs linked as advisers | +| `people.introducer` | array | Contact IDs linked as introducers | +| `people.management` | array | Contact IDs linked as management | + +If the user has already specified what to change in their message, extract it directly without re-asking. + +**Important:** Only include fields that are explicitly being changed. Omit everything else. + +## Step 4 — Fetch custom fields (if updating custom fields) + +If the user wants to update custom fields but didn't specify field keys, fetch the schema first: + +```bash +curl -s "https://api.listalpha.com/v1/deals/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Use the returned field keys and labels to map the user's input to the correct `fields` object. + +## Step 5 — Update the deal via API + +Build the request body with only the fields being changed: + +```json +{ + "stageId": "<stage id>", + "company": { + "name": "<company name>", + "url": "<company url>" + }, + "comment": "<updated comment>", + "tags": ["<tag1>", "<tag2>"], + "dealLead": "<user id>", + "addedAt": "<ISO 8601 date>", + "fields": { + "<field_key>": "<value>" + }, + "people": { + "advisers": ["<contact id>"], + "introducer": ["<contact id>"], + "management": ["<contact id>"] + } +} +``` + +Omit any top-level key that is not being updated. Omit `company` if neither name nor URL is changing. Omit `people` if no contact links are changing. + +Make the API call: + +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/deals/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '<json_body>' +``` + +## Step 6 — Report result + +On success (HTTP 200), respond with a summary of what changed: +> "Deal for **{company name}** updated (ID: `{id}`). {Changed: stage → Diligence, tags updated, etc.}" + +On error: +- **401** — API key is invalid or missing +- **400** — Check that field keys, stage IDs, and contact IDs are valid +- **404** — No deal found with that ID — suggest running `/search-deals` first +- **500** — Server error; try again or contact support + +## Updating multiple deals + +If the user wants to apply the same change to multiple deals, repeat Steps 1 and 5–6 for each. Summarize at the end: +> "Updated N deals: [list of company names]" + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/update-deal/references/api-reference.md b/plugins/carta-crm/skills/update-deal/references/api-reference.md new file mode 100644 index 0000000..53ee4b5 --- /dev/null +++ b/plugins/carta-crm/skills/update-deal/references/api-reference.md @@ -0,0 +1,89 @@ +# Carta CRM Update Deal API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### PATCH /v1/deals/{id} + +Partially updates an existing deal. Only fields provided in the request body are modified — all other fields remain unchanged. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Deal identifier | + +**Request body (all fields optional):** + +| Field | Type | Description | +|-------|------|-------------| +| `stageId` | string | Move deal to a different stage | +| `company.name` | string | Update the associated company name | +| `company.url` | string | Update company URL — triggers auto-enrichment | +| `comment` | string | Replace the deal comment/notes | +| `tags` | array | Replace the full tags array | +| `dealLead` | string | User ID to assign as deal lead | +| `addedAt` | date-time | ISO 8601 date the deal was added | +| `fields` | object | Custom field values keyed by field ID | +| `people.advisers` | array | Contact IDs linked as advisers | +| `people.introducer` | array | Contact IDs linked as introducers | +| `people.management` | array | Contact IDs linked as management | + +**Example — move stage:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/deals/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"stageId": "64f1a2b3c4d5e6f7a8b9c0d3"}' +``` + +**Example — update comment and tags:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/deals/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"comment": "Met founder at SaaStr", "tags": ["saas", "series-a"]}' +``` + +**Response (200):** Returns the full updated deal object: +```json +{ + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "company": { "name": "Stripe", "url": "https://stripe.com" }, + "comment": "Met founder at SaaStr", + "tags": ["saas", "series-a"], + "pipelineId": "...", + "stageId": "64f1a2b3c4d5e6f7a8b9c0d3", + "dealLead": "...", + "fields": {}, + "people": { "advisers": [], "introducer": [], "management": [] } +} +``` + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Validation error — invalid field keys, stage ID, or contact IDs | +| 401 | Unauthorized — invalid or missing API key | +| 404 | No deal found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/deals + +Use this to find a deal ID before updating. See `search-deals` skill for full details. + +### GET /v1/deals/pipelines + +Use this to resolve stage/pipeline names to IDs before updating `stageId`. diff --git a/plugins/carta-crm/skills/update-fundraising/SKILL.md b/plugins/carta-crm/skills/update-fundraising/SKILL.md new file mode 100644 index 0000000..0840517 --- /dev/null +++ b/plugins/carta-crm/skills/update-fundraising/SKILL.md @@ -0,0 +1,98 @@ +--- +name: update-fundraising +description: > + Updates an existing fundraising record in the Carta CRM. + Use this skill when the user says things like "update a fundraising", "edit fundraising", + "update fundraising details", "change fundraising amount", "update fundraising stage", + "update fundraising fields", or "/update-fundraising". + Accepts a fundraising ID or company name (will search if no ID provided). + Only the fields explicitly provided are changed — all other fields are left untouched. +allowed-tools: + - Bash +--- + +## Overview + +Partially update an existing fundraising using `PATCH /v1/fundraisings/{id}`. +Only fields provided in the request body are modified — this is a partial update, +not a replacement. First resolve the fundraising ID, then collect what to change, +then make the API call. + +## Step 1 — Resolve the fundraising ID + +If the user provided a fundraising ID directly, use it and skip to Step 3. + +If only a company name or keyword was given, search for the fundraising first: + +```bash +curl -s "https://api.listalpha.com/v1/fundraisings?search=<name>&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +If multiple fundraisings match, present the list to the user and ask them to confirm which one to update (show name, key fields, and ID for each). + +## Step 2 — Fetch custom fields (if needed) + +If the user wants to update custom fields but didn't specify field keys, fetch the schema first: + +```bash +curl -s "https://api.listalpha.com/v1/fundraisings/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Use the returned field keys and labels to map the user's input to the correct `fields` object. + +## Step 3 — Collect what to update + +Ask the user what they want to change. The fundraising record supports: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Fundraising round name or title | +| `fields` | object | Custom field values keyed by field name | + +If the user has already specified what to change in their message, extract it directly without re-asking. + +**Important:** Only include fields that are explicitly being changed. Omit everything else. + +## Step 4 — Update the fundraising via API + +Build the request body with only the fields being changed: + +```json +{ + "name": "<updated name>", + "fields": { + "<field_key>": "<value>" + } +} +``` + +Make the API call: + +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/fundraisings/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '<json_body>' +``` + +## Step 5 — Report result + +On success (HTTP 200), respond with a summary of what changed: +> "Fundraising **{name}** updated (ID: `{id}`). {Changed: amount updated, stage changed, etc.}" + +On error: +- **401** — API key is invalid or missing +- **400** — Check that field keys are valid +- **404** — No fundraising found with that ID — suggest running `/search-fundraisings` first +- **500** — Server error; try again or contact support + +## Updating multiple fundraisings + +If the user wants to apply the same change to multiple fundraisings, repeat Steps 1 and 4–5 for each. Summarize at the end: +> "Updated N fundraisings: [list of names]" + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/update-fundraising/references/api-reference.md b/plugins/carta-crm/skills/update-fundraising/references/api-reference.md new file mode 100644 index 0000000..cb5c6ae --- /dev/null +++ b/plugins/carta-crm/skills/update-fundraising/references/api-reference.md @@ -0,0 +1,74 @@ +# Carta CRM Update Fundraising API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### PATCH /v1/fundraisings/{id} + +Partially updates an existing fundraising record. Only fields provided in the request body are modified — all other fields remain unchanged. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Fundraising identifier | + +**Request body (all fields optional):** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Fundraising round name or title | +| `fields` | object | Custom field values keyed by field name | + +> **Note:** The available custom fields depend on the tenant's configuration. Call `GET /v1/fundraisings/custom-fields` to discover valid field keys. + +**Example — update name:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/fundraisings/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"name": "Acme Corp Series B (Revised)"}' +``` + +**Example — update custom fields:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/fundraisings/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"fields": {"status": "closed", "amount": "50000000"}}' +``` + +**Response (200):** Returns the full updated fundraising object. + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Validation error — invalid field keys | +| 401 | Unauthorized — invalid or missing API key | +| 404 | No fundraising found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/fundraisings + +Use this to find a fundraising ID before updating. See `search-fundraisings` skill for full details. + +### GET /v1/fundraisings/custom-fields + +Use this to discover available custom field keys before updating `fields`. + +```bash +curl -s "https://api.listalpha.com/v1/fundraisings/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` diff --git a/plugins/carta-crm/skills/update-investor/SKILL.md b/plugins/carta-crm/skills/update-investor/SKILL.md new file mode 100644 index 0000000..07ad67f --- /dev/null +++ b/plugins/carta-crm/skills/update-investor/SKILL.md @@ -0,0 +1,104 @@ +--- +name: update-investor +description: > + Updates an existing investor record in the Carta CRM. + Use this skill when the user says things like "update an investor", "edit investor", + "update investor details", "change investor name", "update investor website", + "update investor fields", "add a tag to investor", or "/update-investor". + Accepts an investor ID or name (will search if no ID provided). + Only the fields explicitly provided are changed — all other fields are left untouched. +allowed-tools: + - Bash +--- + +## Overview + +Partially update an existing investor using `PATCH /v1/investors/{id}`. +Only fields provided in the request body are modified — this is a partial update, +not a replacement. First resolve the investor ID, then collect what to change, +then make the API call. + +## Step 1 — Resolve the investor ID + +If the user provided an investor ID directly, use it and skip to Step 3. + +If only a name or description was given, search for the investor first: + +```bash +curl -s "https://api.listalpha.com/v1/investors?search=<name>&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +If multiple investors match, present the list to the user and ask them to confirm which one to update (show name and ID for each). + +## Step 2 — Collect what to update + +Ask the user what they want to change. Any combination of the following fields can be updated: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Investor firm name | +| `fields` | object | Custom field values — keyed by field name (e.g. `website`, `location`, `industry`, `about`, `tags`) | + +If the user has already specified what to change in their message, extract it directly without re-asking. + +**Important:** Only include fields that are explicitly being changed. Omit everything else. + +## Step 3 — Fetch custom fields (if updating custom fields) + +If the user wants to update custom fields but didn't specify field keys, fetch the schema first: + +```bash +curl -s "https://api.listalpha.com/v1/investors/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +Use the returned field keys and labels to map the user's input to the correct `fields` object. + +## Step 4 — Update the investor via API + +Build the request body with only the fields being changed: + +```json +{ + "name": "<updated name>", + "fields": { + "website": "<url>", + "location": "<location>", + "industry": "<industry>", + "about": "<description>", + "tags": ["<tag1>", "<tag2>"] + } +} +``` + +Omit `name` if it is not being changed. Omit `fields` entirely if no custom fields are being changed. Only include the specific keys within `fields` that are being updated. + +Make the API call: + +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/investors/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '<json_body>' +``` + +## Step 5 — Report result + +On success (HTTP 200), respond with a summary of what changed: +> "Investor **{name}** updated (ID: `{id}`). {Changed: website updated, tags added, etc.}" + +On error: +- **401** — API key is invalid or missing +- **400** — Check that field keys are valid +- **404** — No investor found with that ID — suggest running `/search-investors` first +- **500** — Server error; try again or contact support + +## Updating multiple investors + +If the user wants to apply the same change to multiple investors, repeat Steps 1 and 4–5 for each. Summarize at the end: +> "Updated N investors: [list of names]" + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/update-investor/references/api-reference.md b/plugins/carta-crm/skills/update-investor/references/api-reference.md new file mode 100644 index 0000000..0d2b7cf --- /dev/null +++ b/plugins/carta-crm/skills/update-investor/references/api-reference.md @@ -0,0 +1,95 @@ +# Carta CRM Update Investor API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### PATCH /v1/investors/{id} + +Partially updates an existing investor. Only fields provided in the request body are modified — all other fields remain unchanged. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Investor identifier | + +**Request body (all fields optional):** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Investor firm name | +| `fields` | object | Custom field values keyed by field name | + +**Common custom field keys:** + +| Key | Type | Description | +|-----|------|-------------| +| `website` | string | Investor website URL | +| `location` | string | Geographic location | +| `industry` | string | Industry focus | +| `about` | string | Description or notes | +| `tags` | array | List of tag strings | + +**Example — update website:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/investors/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"fields": {"website": "https://sequoiacap.com"}}' +``` + +**Example — update name and tags:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/investors/64f1a2b3c4d5e6f7a8b9c0d1" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"name": "Sequoia Capital (US)", "fields": {"tags": ["tier-1", "series-a"]}}' +``` + +**Response (200):** Returns the full updated investor object: +```json +{ + "id": "64f1a2b3c4d5e6f7a8b9c0d1", + "name": "Sequoia Capital (US)", + "fields": { + "website": "https://sequoiacap.com", + "location": "Menlo Park, CA", + "industry": "Venture Capital", + "about": "Global venture capital firm", + "tags": ["tier-1", "series-a"] + } +} +``` + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Validation error — invalid field keys | +| 401 | Unauthorized — invalid or missing API key | +| 404 | No investor found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/investors + +Use this to find an investor ID before updating. See `search-investors` skill for full details. + +### GET /v1/investors/custom-fields + +Use this to discover available custom field keys before updating `fields`. + +```bash +curl -s "https://api.listalpha.com/v1/investors/custom-fields" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` diff --git a/plugins/carta-crm/skills/update-note/SKILL.md b/plugins/carta-crm/skills/update-note/SKILL.md new file mode 100644 index 0000000..3a79e6c --- /dev/null +++ b/plugins/carta-crm/skills/update-note/SKILL.md @@ -0,0 +1,89 @@ +--- +name: update-note +description: > + Updates an existing note record in the Carta CRM. + Use this skill when the user says things like "update a note", "edit note", + "update note content", "change note title", "update note text", + "move note to folder", or "/update-note". + Accepts a note ID or title keyword (will search if no ID provided). + Only the fields explicitly provided are changed — all other fields are left untouched. +allowed-tools: + - Bash +--- + +## Overview + +Partially update an existing note using `PATCH /v1/notes/{id}`. +Only fields provided in the request body are modified — this is a partial update, +not a replacement. First resolve the note ID, then collect what to change, +then make the API call. + +## Step 1 — Resolve the note ID + +If the user provided a note ID directly, use it and skip to Step 3. + +If only a title or keyword was given, search for the note first: + +```bash +curl -s "https://api.listalpha.com/v1/notes?search=<title>&limit=10" \ + -H "Authorization: ${LISTALPHA_API_KEY}" +``` + +If multiple notes match, present the list to the user and ask them to confirm which one to update (show title, owner, and ID for each). + +## Step 2 — Collect what to update + +Ask the user what they want to change. Any combination of the following fields can be updated: + +| Field | Type | Description | +|-------|------|-------------| +| `title` | string | Display name of the note | +| `text` | string | Note body content | +| `folderId` | string | ID of the parent folder | +| `owner` | string | Email of the note owner | + +If the user has already specified what to change in their message, extract it directly without re-asking. + +**Important:** Only include fields that are explicitly being changed. Omit everything else. + +## Step 3 — Update the note via API + +Build the request body with only the fields being changed: + +```json +{ + "title": "<updated title>", + "text": "<updated body>", + "folderId": "<folder id>", + "owner": "<owner email>" +} +``` + +Make the API call: + +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/notes/<id>" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '<json_body>' +``` + +## Step 4 — Report result + +On success (HTTP 200), respond with a summary of what changed: +> "Note **{title}** updated (ID: `{id}`). {Changed: text updated, moved to folder, etc.}" + +On error: +- **401** — API key is invalid or missing +- **400** — Check that `title` is non-empty if provided, and `folderId` is valid +- **404** — No note found with that ID — suggest running `/search-notes` first +- **500** — Server error; try again or contact support + +## Updating multiple notes + +If the user wants to apply the same change to multiple notes, repeat Steps 1 and 3–4 for each. Summarize at the end: +> "Updated N notes: [list of titles]" + +## Reference + +See `references/api-reference.md` for full endpoint details. diff --git a/plugins/carta-crm/skills/update-note/references/api-reference.md b/plugins/carta-crm/skills/update-note/references/api-reference.md new file mode 100644 index 0000000..c085c9d --- /dev/null +++ b/plugins/carta-crm/skills/update-note/references/api-reference.md @@ -0,0 +1,74 @@ +# Carta CRM Update Note API Reference + +## Authentication + +All requests require an API key in the `Authorization` header (no `Bearer` prefix): + +``` +Authorization: <your-api-key> +``` + +--- + +## Endpoints + +### PATCH /v1/notes/{id} + +Partially updates an existing note. Only fields provided in the request body are modified — all other fields remain unchanged. + +**Path parameters:** + +| Param | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Note identifier | + +**Request body (all fields optional):** + +| Field | Type | Description | +|-------|------|-------------| +| `title` | string | Display name of the note (minLength: 1) | +| `text` | string | Note body content | +| `folderId` | string | ID of the parent folder | +| `owner` | string | Email of the note owner | + +**Example — update note text:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/notes/64f1a2b3c4d5e6f7a8b9c0d2" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"text": "Updated: follow-up call scheduled for next week."}' +``` + +**Example — rename and move to folder:** +```bash +curl -s -X PATCH "https://api.listalpha.com/v1/notes/64f1a2b3c4d5e6f7a8b9c0d2" \ + -H "Authorization: ${LISTALPHA_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"title": "Q2 Investor Call", "folderId": "64f1a2b3c4d5e6f7a8b9c0d9"}' +``` + +**Response (200):** Returns the full updated note object: +```json +{ + "id": "64f1a2b3c4d5e6f7a8b9c0d2", + "title": "Q2 Investor Call", + "text": "Updated: follow-up call scheduled for next week.", + "folderId": "64f1a2b3c4d5e6f7a8b9c0d9", + "owner": "analyst@fund.com" +} +``` + +**Error responses:** + +| Status | Meaning | +|--------|---------| +| 400 | Validation error — title is empty, or folderId does not exist | +| 401 | Unauthorized — invalid or missing API key | +| 404 | No note found with that ID | +| 500 | Internal server error | + +--- + +### GET /v1/notes + +Use this to find a note ID before updating. See `search-notes` skill for full details.