mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(hubspot): add notes, emails, properties & associations tools (#5037)
* feat(hubspot): add notes, emails, properties & associations tools - Add 11 tools: get_properties (read property/enum options), notes (create/get/list/search), email engagements (create/get/list/search), and v4 associations (list/create) - Add scopes: crm.objects.notes.read/write, crm.objects.emails.read/write, sales-email-read (required for email engagement content) - Wire new operations into the HubSpot block (subBlocks, conditions, tool mapping, outputs, BlockMeta templates/skills) - Fix pre-existing bugs found in validation: list_marketing_events list URL (/marketing/marketing-events/v3), appointment property names (hs_appointment_*), get_users output shape (CRM envelope), create_list response unwrap, and stringified-associations parsing in create tools - Regenerate integration docs * fix(hubspot): drop non-grantable notes/emails scopes; remove inline comments - crm.objects.notes.*/crm.objects.emails.* are not grantable HubSpot scopes (would break the OAuth authorize flow). Notes/emails engagement and association endpoints are authorized by crm.objects.contacts.*; sales-email-read remains for email-engagement content - Remove non-TSDoc inline comments from new tool files * fix(hubspot): address review comments - Forward the properties param for the Get Users operation (block param mapping + Properties-to-Return field now include get_users) - Use Record<string, unknown> for create_note/create_email request bodies - Only send Content-Type on create_association when a body is sent (default-association PUT has no body) - Remove stray duplicate JSDoc opener in types.ts
This commit is contained in:
@@ -3704,44 +3704,23 @@ export function QdrantIcon(props: SVGProps<SVGSVGElement>) {
|
||||
|
||||
export function QuartrIcon(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg {...props} viewBox='0 0 151 40' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path
|
||||
d='M11.5483 29.9995C11.5483 35.5222 19.8031 39.9995 26.1809 39.9995C29.574 39.9995 32.6254 38.7323 34.7384 36.7144L26.1809 29.9995H11.5483Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M0 29.9996C0 35.5222 5.17047 39.9995 11.5483 39.9995V19.9998C5.17047 19.9998 0 24.4768 0 29.9996Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M26.1808 9.99989V27.5075H37.7292V10.0249C37.7173 4.46985 32.552 -0.0135841 26.1808 2.98331e-05H11.4362V0.00114226C5.11012 0.0536532 0 4.50986 0 9.99989V19.9998H11.5483V9.99989H26.1808'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path d='M28.1898 29.3275L40.7827 38.9295V29.3275H28.1898Z' fill='currentColor' />
|
||||
<path
|
||||
d='M88.7938 25.1089H88.7527C87.927 29.0309 85.4089 30.806 82.0238 30.806C77.0289 30.806 75.2949 27.5033 75.2949 23.3752V11.0324H78.8865V22.4671C78.8865 25.1089 80.0423 27.5033 83.5102 27.5033C86.8123 27.5033 88.7938 25.6872 88.7938 22.4671V11.0324H92.3854V30.3106H88.7938V25.1089Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M107.351 23.1277V22.2193H101.613C99.1774 22.2193 97.8563 23.1277 97.8563 24.82C97.8563 26.3063 98.8062 27.7095 101.613 27.7095C105.163 27.7095 107.351 25.7697 107.351 23.1277ZM107.351 25.3982H107.31C106.443 28.948 103.842 30.7235 100.499 30.7235C96.7419 30.7235 94.3067 28.907 94.3067 25.2742C94.3067 21.8892 96.4529 19.371 101.118 19.371H107.351V18.3389C107.351 15.3254 106.196 13.6742 103.14 13.6742C100.375 13.6742 98.8473 14.9538 98.3108 18.1324L94.8843 17.6371C95.5447 13.1375 98.1869 10.6193 103.264 10.6193C108.631 10.6193 110.943 13.3438 110.943 18.2976V30.3106H107.351V25.3982'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M112.909 30.3106V11.0324H116.5V16.9767H116.583C117.367 12.477 119.184 11.0324 122.28 11.0324H123.477V14.995H121.743C118.111 14.995 116.5 16.3988 116.5 20.1141V30.3106H112.909'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M128.24 14.1166L125.391 15.0444V11.0205H128.24V5.69549H131.832V11.0205H137.982V15.0146L131.832 14.1166V24.0654C131.832 26.2122 132.657 27.3266 134.804 27.3266C135.836 27.3266 136.703 27.1203 137.735 26.8313L138.189 30.1339C136.868 30.5465 135.836 30.7944 134.06 30.7944C130.015 30.7944 128.24 28.1524 128.24 24.5609V14.1166'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M140.129 30.3106V11.0324H143.72V16.9767H143.803C144.587 12.477 146.403 11.0324 149.499 11.0324H150.697V14.995H148.963C145.33 14.995 143.72 16.3988 143.72 20.1141V30.3106H140.129'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<path
|
||||
d='M70.4206 19.1212C70.4206 14.0209 66.7718 10.045 61.8913 10.045C57.0108 10.045 53.0603 14.0209 53.0603 19.1212C53.0603 24.5028 56.9397 27.7175 61.8913 27.7175C66.8429 27.7175 70.4206 24.5028 70.4206 19.1212V19.1212ZM49.7827 19.1615C49.7827 11.9726 55.2655 6.67151 61.8913 6.67151C68.553 6.67151 73.6979 11.9726 73.6979 19.1615C73.6979 23.4184 71.6333 26.3923 68.9972 28.6411L72.0609 34.2237V34.304H68.4629L66.3614 30.2878C65.1145 30.7696 63.423 31.051 61.8913 31.051C55.1227 31.051 49.7827 26.3098 49.7827 19.1615'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<svg {...props} viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<rect width='32' height='32' rx='6' fill='white' />
|
||||
<g transform='translate(6 6.19) scale(0.16624)'>
|
||||
<path
|
||||
d='M34.0674 88.4993C34.0674 104.791 58.4191 117.999 77.2336 117.999C87.2434 117.999 96.2453 114.261 102.478 108.308L77.2336 88.4993H34.0674Z'
|
||||
fill='black'
|
||||
/>
|
||||
<path
|
||||
d='M0 88.4993C0 104.791 15.253 117.999 34.0677 117.999V58.9997C15.253 58.9997 0 72.2071 0 88.4993Z'
|
||||
fill='black'
|
||||
/>
|
||||
<path
|
||||
d='M77.2339 29.4999V81.1477H111.302V29.5736C111.267 13.1861 96.0292 -0.0400894 77.2339 7.20269e-05H33.737V0.00335371C15.075 0.158262 0 13.3042 0 29.4999V58.9997H34.0677V29.4999H77.2339'
|
||||
fill='black'
|
||||
/>
|
||||
<path d='M83.1602 86.5171L120.31 114.843V86.5171H83.1602Z' fill='black' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -42,20 +42,21 @@ Retrieve all users from HubSpot account
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `limit` | string | No | Number of results to return \(default: 100, max: 100\) |
|
||||
| `limit` | string | No | Number of results to return \(default: 10, max: 100\) |
|
||||
| `after` | string | No | Pagination cursor for next page of results \(from previous response\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot user property names to return \(e.g., "hs_email,hs_given_name,hs_family_name"\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `users` | array | Array of HubSpot user objects |
|
||||
| ↳ `id` | string | User ID |
|
||||
| ↳ `email` | string | User email address |
|
||||
| ↳ `roleId` | string | User role ID |
|
||||
| ↳ `primaryTeamId` | string | Primary team ID |
|
||||
| ↳ `secondaryTeamIds` | array | Secondary team IDs |
|
||||
| ↳ `superAdmin` | boolean | Whether user is a super admin |
|
||||
| `users` | array | Array of HubSpot CRM records |
|
||||
| ↳ `id` | string | Unique record ID \(hs_object_id\) |
|
||||
| ↳ `createdAt` | string | Record creation timestamp \(ISO 8601\) |
|
||||
| ↳ `updatedAt` | string | Record last updated timestamp \(ISO 8601\) |
|
||||
| ↳ `archived` | boolean | Whether the record is archived |
|
||||
| ↳ `properties` | object | Record properties |
|
||||
| ↳ `associations` | object | Associated records |
|
||||
| `paging` | object | Pagination information for fetching more results |
|
||||
| ↳ `after` | string | Cursor for next page of results |
|
||||
| ↳ `link` | string | Link to next page |
|
||||
@@ -70,7 +71,7 @@ Retrieve all contacts from HubSpot account with pagination support
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 100\) |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 10\) |
|
||||
| `after` | string | No | Pagination cursor for next page of results \(from previous response\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "email,firstname,lastname,phone"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "companies,deals"\) |
|
||||
@@ -285,7 +286,7 @@ Retrieve all companies from HubSpot account with pagination support
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 100\) |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 10\) |
|
||||
| `after` | string | No | Pagination cursor for next page of results \(from previous response\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "name,domain,industry"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,deals"\) |
|
||||
@@ -570,7 +571,7 @@ Retrieve a single deal by ID from HubSpot
|
||||
|
||||
### `hubspot_create_deal`
|
||||
|
||||
Create a new deal in HubSpot. Requires at least a dealname property
|
||||
Create a new deal in HubSpot with the given properties (e.g., dealname, amount, dealstage)
|
||||
|
||||
#### Input
|
||||
|
||||
@@ -837,6 +838,357 @@ Search for tickets in HubSpot using filters, sorting, and queries
|
||||
| `total` | number | Total number of matching tickets |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_list_notes`
|
||||
|
||||
Retrieve all notes from HubSpot account with pagination support
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 10\) |
|
||||
| `after` | string | No | Pagination cursor for next page of results \(from previous response\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_note_body,hs_timestamp,hubspot_owner_id"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies,deals"\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `notes` | array | Array of HubSpot note records |
|
||||
| ↳ `hs_note_body` | string | Note text/body \(supports rich text/HTML\) |
|
||||
| ↳ `hs_timestamp` | string | Note activity time \(ISO 8601\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_attachment_ids` | string | Semicolon-separated IDs of files attached to the note |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Note creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `paging` | object | Pagination information for fetching more results |
|
||||
| ↳ `after` | string | Cursor for next page of results |
|
||||
| ↳ `link` | string | Link to next page |
|
||||
| `metadata` | object | Response metadata |
|
||||
| ↳ `totalReturned` | number | Number of records returned in this response |
|
||||
| ↳ `hasMore` | boolean | Whether more records are available |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_get_note`
|
||||
|
||||
Retrieve a single note by ID from HubSpot
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `noteId` | string | Yes | The HubSpot note ID to retrieve |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_note_body,hs_timestamp,hubspot_owner_id"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies,deals"\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `note` | object | HubSpot note record |
|
||||
| ↳ `hs_note_body` | string | Note text/body \(supports rich text/HTML\) |
|
||||
| ↳ `hs_timestamp` | string | Note activity time \(ISO 8601\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_attachment_ids` | string | Semicolon-separated IDs of files attached to the note |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Note creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `noteId` | string | The retrieved note ID |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_create_note`
|
||||
|
||||
Log a note in HubSpot and optionally associate it with contacts, companies, or deals. Requires hs_timestamp and hs_note_body properties
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `properties` | object | Yes | Note properties as JSON object. Must include "hs_timestamp" \(ISO 8601 activity time\) and "hs_note_body" \(the note text\). e.g., \{"hs_timestamp": "2026-06-13T00:00:00Z", "hs_note_body": "Followed up via phone"\} |
|
||||
| `associations` | array | No | Array of associations as JSON. Each object has "to.id" \(record ID\) and "types" array with "associationCategory" \("HUBSPOT_DEFINED"\) and "associationTypeId" \(202 = note→contact, 190 = note→company, 214 = note→deal\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `note` | object | HubSpot note record |
|
||||
| ↳ `hs_note_body` | string | Note text/body \(supports rich text/HTML\) |
|
||||
| ↳ `hs_timestamp` | string | Note activity time \(ISO 8601\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_attachment_ids` | string | Semicolon-separated IDs of files attached to the note |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Note creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `noteId` | string | The created note ID |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_search_notes`
|
||||
|
||||
Search for notes in HubSpot using filters, sorting, and queries
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `filterGroups` | array | No | Array of filter groups as JSON. Each group contains "filters" array with objects having "propertyName", "operator" \(e.g., "EQ", "CONTAINS_TOKEN", "GT"\), and "value" |
|
||||
| `sorts` | array | No | Array of sort objects as JSON with "propertyName" and "direction" \("ASCENDING" or "DESCENDING"\) |
|
||||
| `query` | string | No | Search query string to match against note text fields |
|
||||
| `properties` | array | No | Array of HubSpot property names to return \(e.g., \["hs_note_body", "hs_timestamp", "hubspot_owner_id"\]\) |
|
||||
| `limit` | number | No | Maximum number of results to return \(max 100\) |
|
||||
| `after` | string | No | Pagination cursor for next page \(from previous response\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `notes` | array | Array of HubSpot note records |
|
||||
| ↳ `hs_note_body` | string | Note text/body \(supports rich text/HTML\) |
|
||||
| ↳ `hs_timestamp` | string | Note activity time \(ISO 8601\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_attachment_ids` | string | Semicolon-separated IDs of files attached to the note |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Note creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `paging` | object | Pagination information for fetching more results |
|
||||
| ↳ `after` | string | Cursor for next page of results |
|
||||
| ↳ `link` | string | Link to next page |
|
||||
| `metadata` | object | Response metadata |
|
||||
| ↳ `totalReturned` | number | Number of records returned in this response |
|
||||
| ↳ `hasMore` | boolean | Whether more records are available |
|
||||
| `total` | number | Total number of matching notes |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_list_emails`
|
||||
|
||||
Retrieve all email engagements from HubSpot account with pagination support
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 10\) |
|
||||
| `after` | string | No | Pagination cursor for next page of results \(from previous response\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_email_subject,hs_email_text,hs_timestamp"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies,deals"\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `emails` | array | Array of HubSpot email engagement records |
|
||||
| ↳ `hs_timestamp` | string | Email activity time \(ISO 8601\) |
|
||||
| ↳ `hs_email_direction` | string | Direction \(EMAIL = outgoing, INCOMING_EMAIL, FORWARDED_EMAIL\) |
|
||||
| ↳ `hs_email_status` | string | Send status \(SENT, SENDING, SCHEDULED, FAILED, BOUNCED\) |
|
||||
| ↳ `hs_email_subject` | string | Email subject line |
|
||||
| ↳ `hs_email_text` | string | Plain-text email body |
|
||||
| ↳ `hs_email_html` | string | HTML email body |
|
||||
| ↳ `hs_email_headers` | string | JSON-encoded from/to/cc/bcc headers |
|
||||
| ↳ `hs_email_from_email` | string | Sender email address |
|
||||
| ↳ `hs_email_to_email` | string | Recipient email address\(es\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Email creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `paging` | object | Pagination information for fetching more results |
|
||||
| ↳ `after` | string | Cursor for next page of results |
|
||||
| ↳ `link` | string | Link to next page |
|
||||
| `metadata` | object | Response metadata |
|
||||
| ↳ `totalReturned` | number | Number of records returned in this response |
|
||||
| ↳ `hasMore` | boolean | Whether more records are available |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_get_email`
|
||||
|
||||
Retrieve a single email engagement by ID from HubSpot (content requires the sales-email-read scope)
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `emailId` | string | Yes | The HubSpot email engagement ID to retrieve |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_email_subject,hs_email_text,hs_timestamp"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies,deals"\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `email` | object | HubSpot email engagement record |
|
||||
| ↳ `hs_timestamp` | string | Email activity time \(ISO 8601\) |
|
||||
| ↳ `hs_email_direction` | string | Direction \(EMAIL = outgoing, INCOMING_EMAIL, FORWARDED_EMAIL\) |
|
||||
| ↳ `hs_email_status` | string | Send status \(SENT, SENDING, SCHEDULED, FAILED, BOUNCED\) |
|
||||
| ↳ `hs_email_subject` | string | Email subject line |
|
||||
| ↳ `hs_email_text` | string | Plain-text email body |
|
||||
| ↳ `hs_email_html` | string | HTML email body |
|
||||
| ↳ `hs_email_headers` | string | JSON-encoded from/to/cc/bcc headers |
|
||||
| ↳ `hs_email_from_email` | string | Sender email address |
|
||||
| ↳ `hs_email_to_email` | string | Recipient email address\(es\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Email creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `emailId` | string | The retrieved email engagement ID |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_create_email`
|
||||
|
||||
Log an email engagement in HubSpot and optionally associate it with contacts. Requires the hs_timestamp property
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `properties` | object | Yes | Email properties as JSON object. Must include "hs_timestamp" \(ISO 8601\). Common fields: "hs_email_direction" \(EMAIL, INCOMING_EMAIL, FORWARDED_EMAIL\), "hs_email_status" \(SENT, SENDING, SCHEDULED, FAILED, BOUNCED\), "hs_email_subject", "hs_email_text", "hs_email_html", "hs_email_headers" \(JSON string\) |
|
||||
| `associations` | array | No | Array of associations as JSON. Each object has "to.id" \(record ID\) and "types" array with "associationCategory" \("HUBSPOT_DEFINED"\) and "associationTypeId" \(198 = email→contact\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `email` | object | HubSpot email engagement record |
|
||||
| ↳ `hs_timestamp` | string | Email activity time \(ISO 8601\) |
|
||||
| ↳ `hs_email_direction` | string | Direction \(EMAIL = outgoing, INCOMING_EMAIL, FORWARDED_EMAIL\) |
|
||||
| ↳ `hs_email_status` | string | Send status \(SENT, SENDING, SCHEDULED, FAILED, BOUNCED\) |
|
||||
| ↳ `hs_email_subject` | string | Email subject line |
|
||||
| ↳ `hs_email_text` | string | Plain-text email body |
|
||||
| ↳ `hs_email_html` | string | HTML email body |
|
||||
| ↳ `hs_email_headers` | string | JSON-encoded from/to/cc/bcc headers |
|
||||
| ↳ `hs_email_from_email` | string | Sender email address |
|
||||
| ↳ `hs_email_to_email` | string | Recipient email address\(es\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Email creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `emailId` | string | The created email engagement ID |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_search_emails`
|
||||
|
||||
Search for email engagements in HubSpot using filters, sorting, and queries
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `filterGroups` | array | No | Array of filter groups as JSON. Each group contains "filters" array with objects having "propertyName", "operator" \(e.g., "EQ", "CONTAINS_TOKEN", "GT"\), and "value" |
|
||||
| `sorts` | array | No | Array of sort objects as JSON with "propertyName" and "direction" \("ASCENDING" or "DESCENDING"\) |
|
||||
| `query` | string | No | Search query string to match against email text fields |
|
||||
| `properties` | array | No | Array of HubSpot property names to return \(e.g., \["hs_email_subject", "hs_email_text", "hs_timestamp"\]\) |
|
||||
| `limit` | number | No | Maximum number of results to return \(max 100\) |
|
||||
| `after` | string | No | Pagination cursor for next page \(from previous response\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `emails` | array | Array of HubSpot email engagement records |
|
||||
| ↳ `hs_timestamp` | string | Email activity time \(ISO 8601\) |
|
||||
| ↳ `hs_email_direction` | string | Direction \(EMAIL = outgoing, INCOMING_EMAIL, FORWARDED_EMAIL\) |
|
||||
| ↳ `hs_email_status` | string | Send status \(SENT, SENDING, SCHEDULED, FAILED, BOUNCED\) |
|
||||
| ↳ `hs_email_subject` | string | Email subject line |
|
||||
| ↳ `hs_email_text` | string | Plain-text email body |
|
||||
| ↳ `hs_email_html` | string | HTML email body |
|
||||
| ↳ `hs_email_headers` | string | JSON-encoded from/to/cc/bcc headers |
|
||||
| ↳ `hs_email_from_email` | string | Sender email address |
|
||||
| ↳ `hs_email_to_email` | string | Recipient email address\(es\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Email creation date \(ISO 8601\) |
|
||||
| ↳ `hs_lastmodifieddate` | string | Last modified date \(ISO 8601\) |
|
||||
| `paging` | object | Pagination information for fetching more results |
|
||||
| ↳ `after` | string | Cursor for next page of results |
|
||||
| ↳ `link` | string | Link to next page |
|
||||
| `metadata` | object | Response metadata |
|
||||
| ↳ `totalReturned` | number | Number of records returned in this response |
|
||||
| ↳ `hasMore` | boolean | Whether more records are available |
|
||||
| `total` | number | Total number of matching emails |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_get_properties`
|
||||
|
||||
Read property definitions and their enumeration (picklist) options for a HubSpot object type, e.g. the values for lifecyclestage or hs_lead_status on contacts
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `objectType` | string | Yes | Object type to read properties for \(e.g., "contacts", "companies", "deals", "tickets", "line_items", "quotes"\) |
|
||||
| `propertyName` | string | No | Internal name of a single property to retrieve \(e.g., "hs_lead_status"\). Omit to return all properties for the object type |
|
||||
| `archived` | boolean | No | Whether to return only archived properties \(default false\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `properties` | array | Array of HubSpot property definitions |
|
||||
| ↳ `label` | string | Human-readable option label |
|
||||
| ↳ `value` | string | Internal value used when setting the property |
|
||||
| ↳ `displayOrder` | number | Display order \(-1 sorts last\) |
|
||||
| ↳ `hidden` | boolean | Whether the option is hidden in the HubSpot UI |
|
||||
| ↳ `description` | string | Option description |
|
||||
| `metadata` | object | Response metadata |
|
||||
| ↳ `totalReturned` | number | Number of property definitions returned |
|
||||
| ↳ `objectType` | string | Object type the properties belong to |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_list_associations`
|
||||
|
||||
List records of one object type associated with a given record, e.g. all emails or notes logged on a contact
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `objectType` | string | Yes | Source object type \(e.g., "contacts", "companies", "deals"\) |
|
||||
| `objectId` | string | Yes | ID of the source record |
|
||||
| `toObjectType` | string | Yes | Target object type to list associations to \(e.g., "emails", "notes", "deals"\) |
|
||||
| `limit` | string | No | Maximum number of associated records per page \(default 500\) |
|
||||
| `after` | string | No | Pagination cursor for next page \(from previous response\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `results` | array | Array of associated records |
|
||||
| ↳ `toObjectId` | string | ID of the associated \(target\) record |
|
||||
| ↳ `associationTypes` | array | Association types linking the two records |
|
||||
| ↳ `category` | string | Association category \(HUBSPOT_DEFINED, USER_DEFINED, INTEGRATOR_DEFINED\) |
|
||||
| ↳ `typeId` | number | Association type ID |
|
||||
| ↳ `label` | string | Association label |
|
||||
| `paging` | object | Pagination information for fetching more results |
|
||||
| ↳ `after` | string | Cursor for next page of results |
|
||||
| ↳ `link` | string | Link to next page |
|
||||
| `metadata` | object | Response metadata |
|
||||
| ↳ `totalReturned` | number | Number of records returned in this response |
|
||||
| ↳ `hasMore` | boolean | Whether more records are available |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_create_association`
|
||||
|
||||
Associate two HubSpot records. Creates the default (unlabeled) association unless an association type ID is provided
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `objectType` | string | Yes | Source object type \(e.g., "emails", "notes", "contacts"\) |
|
||||
| `objectId` | string | Yes | ID of the source record |
|
||||
| `toObjectType` | string | Yes | Target object type to associate to \(e.g., "contacts", "companies", "deals"\) |
|
||||
| `toObjectId` | string | Yes | ID of the target record |
|
||||
| `associationCategory` | string | No | Association category for a labeled association \(HUBSPOT_DEFINED, USER_DEFINED, INTEGRATOR_DEFINED\). Defaults to HUBSPOT_DEFINED when an association type ID is provided |
|
||||
| `associationTypeId` | number | No | Specific association type ID for a labeled association. Omit to create the default association for the object pair |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `fromObjectId` | string | ID of the source record |
|
||||
| `toObjectId` | string | ID of the associated target record |
|
||||
| `labels` | array | Association labels \(empty for default associations\) |
|
||||
| `success` | boolean | Operation success status |
|
||||
|
||||
### `hubspot_list_line_items`
|
||||
|
||||
Retrieve all line items from HubSpot account with pagination support
|
||||
@@ -1046,7 +1398,7 @@ Retrieve all appointments from HubSpot account with pagination support
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `limit` | string | No | Maximum number of results per page \(max 100, default 10\) |
|
||||
| `after` | string | No | Pagination cursor for next page of results \(from previous response\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_meeting_title,hs_meeting_start_time"\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_appointment_name,hs_appointment_start"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies"\) |
|
||||
|
||||
#### Output
|
||||
@@ -1054,11 +1406,10 @@ Retrieve all appointments from HubSpot account with pagination support
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `appointments` | array | Array of HubSpot appointment records |
|
||||
| ↳ `hs_appointment_type` | string | Appointment type |
|
||||
| ↳ `hs_meeting_title` | string | Meeting title |
|
||||
| ↳ `hs_meeting_start_time` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_end_time` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_location` | string | Meeting location |
|
||||
| ↳ `hs_appointment_name` | string | Appointment title/name |
|
||||
| ↳ `hs_appointment_start` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_end` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_status` | string | Appointment status \(e.g., SCHEDULED\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Creation date \(ISO 8601\) |
|
||||
@@ -1081,7 +1432,7 @@ Retrieve a single appointment by ID from HubSpot
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `appointmentId` | string | Yes | The HubSpot appointment ID to retrieve |
|
||||
| `idProperty` | string | No | Property to use as unique identifier. If not specified, uses record ID |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_meeting_title,hs_meeting_start_time"\) |
|
||||
| `properties` | string | No | Comma-separated list of HubSpot property names to return \(e.g., "hs_appointment_name,hs_appointment_start"\) |
|
||||
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies"\) |
|
||||
|
||||
#### Output
|
||||
@@ -1089,11 +1440,10 @@ Retrieve a single appointment by ID from HubSpot
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `appointment` | object | HubSpot appointment record |
|
||||
| ↳ `hs_appointment_type` | string | Appointment type |
|
||||
| ↳ `hs_meeting_title` | string | Meeting title |
|
||||
| ↳ `hs_meeting_start_time` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_end_time` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_location` | string | Meeting location |
|
||||
| ↳ `hs_appointment_name` | string | Appointment title/name |
|
||||
| ↳ `hs_appointment_start` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_end` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_status` | string | Appointment status \(e.g., SCHEDULED\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Creation date \(ISO 8601\) |
|
||||
@@ -1109,7 +1459,7 @@ Create a new appointment in HubSpot
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `properties` | object | Yes | Appointment properties as JSON object \(e.g., \{"hs_meeting_title": "Discovery Call", "hs_meeting_start_time": "2024-01-15T10:00:00Z", "hs_meeting_end_time": "2024-01-15T11:00:00Z"\}\) |
|
||||
| `properties` | object | Yes | Appointment properties as JSON object \(e.g., \{"hs_appointment_name": "Discovery Call", "hs_appointment_start": "2024-01-15T10:00:00Z", "hs_appointment_end": "2024-01-15T11:00:00Z"\}\) |
|
||||
| `associations` | array | No | Array of associations to create with the appointment as JSON. Each object should have "to.id" and "types" array with "associationCategory" and "associationTypeId" |
|
||||
|
||||
#### Output
|
||||
@@ -1117,11 +1467,10 @@ Create a new appointment in HubSpot
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `appointment` | object | HubSpot appointment record |
|
||||
| ↳ `hs_appointment_type` | string | Appointment type |
|
||||
| ↳ `hs_meeting_title` | string | Meeting title |
|
||||
| ↳ `hs_meeting_start_time` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_end_time` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_location` | string | Meeting location |
|
||||
| ↳ `hs_appointment_name` | string | Appointment title/name |
|
||||
| ↳ `hs_appointment_start` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_end` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_status` | string | Appointment status \(e.g., SCHEDULED\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Creation date \(ISO 8601\) |
|
||||
@@ -1139,18 +1488,17 @@ Update an existing appointment in HubSpot by ID
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `appointmentId` | string | Yes | The HubSpot appointment ID to update |
|
||||
| `idProperty` | string | No | Property to use as unique identifier. If not specified, uses record ID |
|
||||
| `properties` | object | Yes | Appointment properties to update as JSON object \(e.g., \{"hs_meeting_title": "Updated Call", "hs_meeting_location": "Zoom"\}\) |
|
||||
| `properties` | object | Yes | Appointment properties to update as JSON object \(e.g., \{"hs_appointment_name": "Updated Call", "hs_appointment_start": "2024-01-15T10:00:00Z"\}\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `appointment` | object | HubSpot appointment record |
|
||||
| ↳ `hs_appointment_type` | string | Appointment type |
|
||||
| ↳ `hs_meeting_title` | string | Meeting title |
|
||||
| ↳ `hs_meeting_start_time` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_end_time` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_meeting_location` | string | Meeting location |
|
||||
| ↳ `hs_appointment_name` | string | Appointment title/name |
|
||||
| ↳ `hs_appointment_start` | string | Start time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_end` | string | End time \(ISO 8601\) |
|
||||
| ↳ `hs_appointment_status` | string | Appointment status \(e.g., SCHEDULED\) |
|
||||
| ↳ `hubspot_owner_id` | string | HubSpot owner ID |
|
||||
| ↳ `hs_object_id` | string | HubSpot object ID \(same as record ID\) |
|
||||
| ↳ `hs_createdate` | string | Creation date \(ISO 8601\) |
|
||||
|
||||
@@ -40,6 +40,15 @@ export const HubSpotBlock: BlockConfig<HubSpotResponse> = {
|
||||
{ label: 'Create Ticket', id: 'create_ticket' },
|
||||
{ label: 'Update Ticket', id: 'update_ticket' },
|
||||
{ label: 'Search Tickets', id: 'search_tickets' },
|
||||
{ label: 'Get Notes', id: 'get_notes' },
|
||||
{ label: 'Create Note', id: 'create_note' },
|
||||
{ label: 'Search Notes', id: 'search_notes' },
|
||||
{ label: 'Get Emails', id: 'get_emails' },
|
||||
{ label: 'Create Email', id: 'create_email' },
|
||||
{ label: 'Search Emails', id: 'search_emails' },
|
||||
{ label: 'Get Properties', id: 'get_properties' },
|
||||
{ label: 'List Associations', id: 'list_associations' },
|
||||
{ label: 'Create Association', id: 'create_association' },
|
||||
{ label: 'Get Line Items', id: 'get_line_items' },
|
||||
{ label: 'Create Line Item', id: 'create_line_item' },
|
||||
{ label: 'Update Line Item', id: 'update_line_item' },
|
||||
@@ -136,6 +145,95 @@ export const HubSpotBlock: BlockConfig<HubSpotResponse> = {
|
||||
condition: { field: 'operation', value: 'update_ticket' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'noteId',
|
||||
title: 'Note ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Leave empty to list all notes',
|
||||
condition: { field: 'operation', value: 'get_notes' },
|
||||
},
|
||||
{
|
||||
id: 'emailId',
|
||||
title: 'Email ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Leave empty to list all emails',
|
||||
condition: { field: 'operation', value: 'get_emails' },
|
||||
},
|
||||
{
|
||||
id: 'objectType',
|
||||
title: 'Object Type',
|
||||
type: 'short-input',
|
||||
placeholder: 'e.g., "contacts", "companies", "deals", "tickets"',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['get_properties', 'list_associations', 'create_association'],
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'propertyName',
|
||||
title: 'Property Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'Leave empty to return all properties (e.g., "hs_lead_status")',
|
||||
condition: { field: 'operation', value: 'get_properties' },
|
||||
},
|
||||
{
|
||||
id: 'archived',
|
||||
title: 'Archived Only',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'No', id: 'false' },
|
||||
{ label: 'Yes', id: 'true' },
|
||||
],
|
||||
value: () => 'false',
|
||||
mode: 'advanced',
|
||||
condition: { field: 'operation', value: 'get_properties' },
|
||||
},
|
||||
{
|
||||
id: 'objectId',
|
||||
title: 'Record ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'ID of the source record',
|
||||
condition: { field: 'operation', value: ['list_associations', 'create_association'] },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'toObjectType',
|
||||
title: 'To Object Type',
|
||||
type: 'short-input',
|
||||
placeholder: 'e.g., "emails", "notes", "contacts"',
|
||||
condition: { field: 'operation', value: ['list_associations', 'create_association'] },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'toObjectId',
|
||||
title: 'To Record ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'ID of the target record',
|
||||
condition: { field: 'operation', value: 'create_association' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'associationCategory',
|
||||
title: 'Association Category',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'HubSpot Defined', id: 'HUBSPOT_DEFINED' },
|
||||
{ label: 'User Defined', id: 'USER_DEFINED' },
|
||||
{ label: 'Integrator Defined', id: 'INTEGRATOR_DEFINED' },
|
||||
],
|
||||
value: () => 'HUBSPOT_DEFINED',
|
||||
mode: 'advanced',
|
||||
condition: { field: 'operation', value: 'create_association' },
|
||||
},
|
||||
{
|
||||
id: 'associationTypeId',
|
||||
title: 'Association Type ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Leave empty for the default association (e.g., 198 = email→contact)',
|
||||
mode: 'advanced',
|
||||
condition: { field: 'operation', value: 'create_association' },
|
||||
},
|
||||
{
|
||||
id: 'lineItemId',
|
||||
title: 'Line Item ID',
|
||||
@@ -266,6 +364,8 @@ export const HubSpotBlock: BlockConfig<HubSpotResponse> = {
|
||||
'update_line_item',
|
||||
'create_appointment',
|
||||
'update_appointment',
|
||||
'create_note',
|
||||
'create_email',
|
||||
],
|
||||
},
|
||||
wandConfig: {
|
||||
@@ -403,10 +503,13 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'get_companies',
|
||||
'get_deals',
|
||||
'get_tickets',
|
||||
'get_notes',
|
||||
'get_emails',
|
||||
'get_line_items',
|
||||
'get_quotes',
|
||||
'get_appointments',
|
||||
'get_carts',
|
||||
'get_users',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -423,6 +526,8 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'get_companies',
|
||||
'get_deals',
|
||||
'get_tickets',
|
||||
'get_notes',
|
||||
'get_emails',
|
||||
'get_line_items',
|
||||
'get_quotes',
|
||||
'get_appointments',
|
||||
@@ -433,6 +538,8 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'create_ticket',
|
||||
'create_line_item',
|
||||
'create_appointment',
|
||||
'create_note',
|
||||
'create_email',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -450,17 +557,22 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'get_companies',
|
||||
'get_deals',
|
||||
'get_tickets',
|
||||
'get_notes',
|
||||
'get_emails',
|
||||
'get_line_items',
|
||||
'get_quotes',
|
||||
'get_appointments',
|
||||
'get_carts',
|
||||
'list_owners',
|
||||
'list_associations',
|
||||
'get_marketing_events',
|
||||
'get_lists',
|
||||
'search_contacts',
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -477,11 +589,14 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'get_companies',
|
||||
'get_deals',
|
||||
'get_tickets',
|
||||
'get_notes',
|
||||
'get_emails',
|
||||
'get_line_items',
|
||||
'get_quotes',
|
||||
'get_appointments',
|
||||
'get_carts',
|
||||
'list_owners',
|
||||
'list_associations',
|
||||
'get_users',
|
||||
'get_marketing_events',
|
||||
'get_lists',
|
||||
@@ -489,6 +604,8 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -504,6 +621,8 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
'get_lists',
|
||||
],
|
||||
},
|
||||
@@ -516,7 +635,14 @@ Return ONLY the JSON object with properties - no explanations, no markdown, no e
|
||||
'JSON array of filter groups (e.g., [{"filters":[{"propertyName":"email","operator":"EQ","value":"test@example.com"}]}])',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['search_contacts', 'search_companies', 'search_deals', 'search_tickets'],
|
||||
value: [
|
||||
'search_contacts',
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
],
|
||||
},
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
@@ -720,7 +846,14 @@ Return ONLY the JSON array of filter groups - no explanations, no markdown, no e
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['search_contacts', 'search_companies', 'search_deals', 'search_tickets'],
|
||||
value: [
|
||||
'search_contacts',
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
],
|
||||
},
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
@@ -845,7 +978,14 @@ Return ONLY the JSON array of sort objects - no explanations, no markdown, no ex
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['search_contacts', 'search_companies', 'search_deals', 'search_tickets'],
|
||||
value: [
|
||||
'search_contacts',
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
],
|
||||
},
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
@@ -998,6 +1138,17 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
'hubspot_create_ticket',
|
||||
'hubspot_update_ticket',
|
||||
'hubspot_search_tickets',
|
||||
'hubspot_list_notes',
|
||||
'hubspot_get_note',
|
||||
'hubspot_create_note',
|
||||
'hubspot_search_notes',
|
||||
'hubspot_list_emails',
|
||||
'hubspot_get_email',
|
||||
'hubspot_create_email',
|
||||
'hubspot_search_emails',
|
||||
'hubspot_get_properties',
|
||||
'hubspot_list_associations',
|
||||
'hubspot_create_association',
|
||||
'hubspot_list_line_items',
|
||||
'hubspot_get_line_item',
|
||||
'hubspot_create_line_item',
|
||||
@@ -1054,6 +1205,24 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
return 'hubspot_update_ticket'
|
||||
case 'search_tickets':
|
||||
return 'hubspot_search_tickets'
|
||||
case 'get_notes':
|
||||
return params.noteId ? 'hubspot_get_note' : 'hubspot_list_notes'
|
||||
case 'create_note':
|
||||
return 'hubspot_create_note'
|
||||
case 'search_notes':
|
||||
return 'hubspot_search_notes'
|
||||
case 'get_emails':
|
||||
return params.emailId ? 'hubspot_get_email' : 'hubspot_list_emails'
|
||||
case 'create_email':
|
||||
return 'hubspot_create_email'
|
||||
case 'search_emails':
|
||||
return 'hubspot_search_emails'
|
||||
case 'get_properties':
|
||||
return 'hubspot_get_properties'
|
||||
case 'list_associations':
|
||||
return 'hubspot_list_associations'
|
||||
case 'create_association':
|
||||
return 'hubspot_create_association'
|
||||
case 'get_line_items':
|
||||
return params.lineItemId ? 'hubspot_get_line_item' : 'hubspot_list_line_items'
|
||||
case 'create_line_item':
|
||||
@@ -1093,6 +1262,8 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
sorts,
|
||||
associations,
|
||||
listName,
|
||||
associationTypeId,
|
||||
archived,
|
||||
...rest
|
||||
} = params
|
||||
|
||||
@@ -1113,6 +1284,8 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
'update_line_item',
|
||||
'create_appointment',
|
||||
'update_appointment',
|
||||
'create_note',
|
||||
'create_email',
|
||||
]
|
||||
if (propertiesToSet && createUpdateOps.includes(operation as string)) {
|
||||
cleanParams.properties = propertiesToSet
|
||||
@@ -1123,16 +1296,26 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
'get_companies',
|
||||
'get_deals',
|
||||
'get_tickets',
|
||||
'get_notes',
|
||||
'get_emails',
|
||||
'get_line_items',
|
||||
'get_quotes',
|
||||
'get_appointments',
|
||||
'get_carts',
|
||||
'get_users',
|
||||
]
|
||||
if (properties && !searchProperties && getListOps.includes(operation as string)) {
|
||||
cleanParams.properties = properties
|
||||
}
|
||||
|
||||
const searchOps = ['search_contacts', 'search_companies', 'search_deals', 'search_tickets']
|
||||
const searchOps = [
|
||||
'search_contacts',
|
||||
'search_companies',
|
||||
'search_deals',
|
||||
'search_tickets',
|
||||
'search_notes',
|
||||
'search_emails',
|
||||
]
|
||||
if (searchProperties && searchOps.includes(operation as string)) {
|
||||
cleanParams.properties = searchProperties
|
||||
}
|
||||
@@ -1153,6 +1336,8 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
'create_ticket',
|
||||
'create_line_item',
|
||||
'create_appointment',
|
||||
'create_note',
|
||||
'create_email',
|
||||
]
|
||||
if (associations && associationOps.includes(operation as string)) {
|
||||
cleanParams.associations = associations
|
||||
@@ -1162,6 +1347,18 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
cleanParams.name = listName
|
||||
}
|
||||
|
||||
if (
|
||||
operation === 'create_association' &&
|
||||
associationTypeId !== undefined &&
|
||||
associationTypeId !== ''
|
||||
) {
|
||||
cleanParams.associationTypeId = Number(associationTypeId)
|
||||
}
|
||||
|
||||
if (operation === 'get_properties' && archived !== undefined && archived !== '') {
|
||||
cleanParams.archived = archived === true || archived === 'true'
|
||||
}
|
||||
|
||||
if (operation === 'get_lists') {
|
||||
if (rest.limit) {
|
||||
cleanParams.count = rest.limit
|
||||
@@ -1205,6 +1402,16 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
cartId: { type: 'string', description: 'Cart ID' },
|
||||
eventId: { type: 'string', description: 'Marketing event ID' },
|
||||
listId: { type: 'string', description: 'List ID' },
|
||||
noteId: { type: 'string', description: 'Note ID' },
|
||||
emailId: { type: 'string', description: 'Email engagement ID' },
|
||||
objectType: { type: 'string', description: 'Object type (e.g., contacts, companies, deals)' },
|
||||
propertyName: { type: 'string', description: 'Single property name to retrieve' },
|
||||
archived: { type: 'boolean', description: 'Whether to return only archived properties' },
|
||||
objectId: { type: 'string', description: 'Source record ID for associations' },
|
||||
toObjectType: { type: 'string', description: 'Target object type for associations' },
|
||||
toObjectId: { type: 'string', description: 'Target record ID for associations' },
|
||||
associationCategory: { type: 'string', description: 'Association category for a labeled link' },
|
||||
associationTypeId: { type: 'number', description: 'Association type ID for a labeled link' },
|
||||
idProperty: { type: 'string', description: 'Property name to use as unique identifier' },
|
||||
propertiesToSet: { type: 'json', description: 'Properties to create/update (JSON object)' },
|
||||
properties: {
|
||||
@@ -1245,6 +1452,24 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no
|
||||
event: { type: 'json', description: 'Single marketing event object' },
|
||||
lists: { type: 'json', description: 'Array of list objects' },
|
||||
list: { type: 'json', description: 'Single list object' },
|
||||
notes: { type: 'json', description: 'Array of note objects' },
|
||||
note: { type: 'json', description: 'Single note object' },
|
||||
emails: { type: 'json', description: 'Array of email engagement objects' },
|
||||
email: { type: 'json', description: 'Single email engagement object' },
|
||||
properties: {
|
||||
type: 'json',
|
||||
description: 'Array of property definitions (name, label, type, fieldType, options)',
|
||||
},
|
||||
results: {
|
||||
type: 'json',
|
||||
description: 'Array of associated records (toObjectId, associationTypes)',
|
||||
},
|
||||
fromObjectId: { type: 'string', description: 'Source record ID (for create association)' },
|
||||
toObjectId: {
|
||||
type: 'string',
|
||||
description: 'Associated target record ID (for create association)',
|
||||
},
|
||||
labels: { type: 'json', description: 'Association labels (for create association)' },
|
||||
total: { type: 'number', description: 'Total number of matching results (for search)' },
|
||||
paging: { type: 'json', description: 'Pagination info with next/prev cursors' },
|
||||
metadata: { type: 'json', description: 'Operation metadata' },
|
||||
@@ -1331,6 +1556,16 @@ export const HubSpotBlockMeta = {
|
||||
tags: ['support', 'automation', 'crm'],
|
||||
alsoIntegrations: ['slack'],
|
||||
},
|
||||
{
|
||||
icon: HubspotIcon,
|
||||
title: 'Backfill HubSpot contact email history from Gmail',
|
||||
prompt:
|
||||
'Build a workflow that finds HubSpot contacts in the lead stage with no logged email activity, searches my Gmail for each person’s thread, and logs it back to HubSpot as an email engagement associated with the contact.',
|
||||
modules: ['agent', 'workflows'],
|
||||
category: 'sales',
|
||||
tags: ['sales', 'crm', 'automation'],
|
||||
alsoIntegrations: ['gmail'],
|
||||
},
|
||||
],
|
||||
skills: [
|
||||
{
|
||||
@@ -1365,5 +1600,23 @@ export const HubSpotBlockMeta = {
|
||||
content:
|
||||
'# Build Quote From Deal\n\nCompile the commercial details needed to quote a deal.\n\n## Steps\n1. Get the deal by ID for its name, amount, and stage.\n2. List line items and get details to capture product, quantity, and price for each.\n3. Get the associated quote if one exists, or summarize the line items into a draft quote.\n4. Total the line items and compare against the deal amount, flagging mismatches.\n\n## Output\nReturn the deal summary, an itemized line-item list with totals, and any existing quote reference. Flag discrepancies between the line-item total and the deal amount.',
|
||||
},
|
||||
{
|
||||
name: 'log-email-to-contact',
|
||||
description: 'Log an email engagement in HubSpot and associate it with a contact.',
|
||||
content:
|
||||
'# Log Email To Contact\n\nRecord an email activity on a contact’s timeline.\n\n## Steps\n1. Search contacts by email to resolve the contact ID.\n2. Create an email engagement with hs_timestamp, subject, body, and direction.\n3. Associate the email with the contact (associationTypeId 198, or the default association).\n4. List associations from the contact to emails to confirm the link.\n\n## Output\nReturn the email engagement ID and the associated contact ID.',
|
||||
},
|
||||
{
|
||||
name: 'audit-contacts-missing-activity',
|
||||
description: 'Find contacts in a lead stage that have no logged email activity.',
|
||||
content:
|
||||
'# Audit Contacts Missing Activity\n\nSurface leads with no recorded email history.\n\n## Steps\n1. Get properties for contacts to read the hs_lead_status options and confirm the target stage value.\n2. Search contacts filtered to that lead status, paginating through all results.\n3. For each contact, list associations to emails and flag those with zero associated emails.\n4. Collect the contacts that need follow-up.\n\n## Output\nReturn the list of contact IDs with no logged email activity, ready for backfill.',
|
||||
},
|
||||
{
|
||||
name: 'inspect-property-options',
|
||||
description: 'Read the enumeration (picklist) values for a HubSpot property.',
|
||||
content:
|
||||
'# Inspect Property Options\n\nList the allowed values for a dropdown property.\n\n## Steps\n1. Get properties for the object type (e.g., contacts).\n2. Find the property by name (e.g., lifecyclestage or hs_lead_status).\n3. Read its options array for label/value pairs.\n\n## Output\nReturn the property label and its enumeration options as label/value pairs.',
|
||||
},
|
||||
],
|
||||
} as const satisfies BlockMeta
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"updatedAt": "2026-06-13",
|
||||
"updatedAt": "2026-06-14",
|
||||
"integrations": [
|
||||
{
|
||||
"type": "onepassword",
|
||||
@@ -7191,7 +7191,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Create Deal",
|
||||
"description": "Create a new deal in HubSpot. Requires at least a dealname property"
|
||||
"description": "Create a new deal in HubSpot with the given properties (e.g., dealname, amount, dealstage)"
|
||||
},
|
||||
{
|
||||
"name": "Update Deal",
|
||||
@@ -7217,6 +7217,42 @@
|
||||
"name": "Search Tickets",
|
||||
"description": "Search for tickets in HubSpot using filters, sorting, and queries"
|
||||
},
|
||||
{
|
||||
"name": "Get Notes",
|
||||
"description": "Retrieve all notes from HubSpot account with pagination support"
|
||||
},
|
||||
{
|
||||
"name": "Create Note",
|
||||
"description": "Log a note in HubSpot and optionally associate it with contacts, companies, or deals. Requires hs_timestamp and hs_note_body properties"
|
||||
},
|
||||
{
|
||||
"name": "Search Notes",
|
||||
"description": "Search for notes in HubSpot using filters, sorting, and queries"
|
||||
},
|
||||
{
|
||||
"name": "Get Emails",
|
||||
"description": "Retrieve all email engagements from HubSpot account with pagination support"
|
||||
},
|
||||
{
|
||||
"name": "Create Email",
|
||||
"description": "Log an email engagement in HubSpot and optionally associate it with contacts. Requires the hs_timestamp property"
|
||||
},
|
||||
{
|
||||
"name": "Search Emails",
|
||||
"description": "Search for email engagements in HubSpot using filters, sorting, and queries"
|
||||
},
|
||||
{
|
||||
"name": "Get Properties",
|
||||
"description": "Read property definitions and their enumeration (picklist) options for a HubSpot object type, e.g. the values for lifecyclestage or hs_lead_status on contacts"
|
||||
},
|
||||
{
|
||||
"name": "List Associations",
|
||||
"description": "List records of one object type associated with a given record, e.g. all emails or notes logged on a contact"
|
||||
},
|
||||
{
|
||||
"name": "Create Association",
|
||||
"description": "Associate two HubSpot records. Creates the default (unlabeled) association unless an association type ID is provided"
|
||||
},
|
||||
{
|
||||
"name": "Get Line Items",
|
||||
"description": "Retrieve all line items from HubSpot account with pagination support"
|
||||
@@ -7270,7 +7306,7 @@
|
||||
"description": "Retrieve all users from HubSpot account"
|
||||
}
|
||||
],
|
||||
"operationCount": 29,
|
||||
"operationCount": 38,
|
||||
"triggers": [
|
||||
{
|
||||
"id": "hubspot_poller",
|
||||
|
||||
@@ -917,6 +917,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
'crm.objects.appointments.read',
|
||||
'crm.objects.appointments.write',
|
||||
'crm.objects.carts.read',
|
||||
'sales-email-read',
|
||||
'crm.lists.read',
|
||||
'crm.lists.write',
|
||||
'tickets',
|
||||
|
||||
@@ -314,6 +314,7 @@ export const SCOPE_DESCRIPTIONS: Record<string, string> = {
|
||||
'crm.objects.appointments.write': 'Create and update HubSpot appointments',
|
||||
'crm.objects.carts.read': 'Read HubSpot shopping carts',
|
||||
'crm.objects.carts.write': 'Create and update HubSpot shopping carts',
|
||||
'sales-email-read': 'Read the content of HubSpot email engagements',
|
||||
'crm.import': 'Import data into HubSpot',
|
||||
'crm.lists.read': 'Read HubSpot lists',
|
||||
'crm.lists.write': 'Create and update HubSpot lists',
|
||||
|
||||
@@ -34,7 +34,7 @@ export const hubspotCreateAppointmentTool: ToolConfig<
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Appointment properties as JSON object (e.g., {"hs_meeting_title": "Discovery Call", "hs_meeting_start_time": "2024-01-15T10:00:00Z", "hs_meeting_end_time": "2024-01-15T11:00:00Z"})',
|
||||
'Appointment properties as JSON object (e.g., {"hs_appointment_name": "Discovery Call", "hs_appointment_start": "2024-01-15T10:00:00Z", "hs_appointment_end": "2024-01-15T11:00:00Z"})',
|
||||
},
|
||||
associations: {
|
||||
type: 'array',
|
||||
@@ -67,8 +67,18 @@ export const hubspotCreateAppointmentTool: ToolConfig<
|
||||
}
|
||||
}
|
||||
const body: Record<string, unknown> = { properties }
|
||||
if (params.associations && params.associations.length > 0) {
|
||||
body.associations = params.associations
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
return body
|
||||
},
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type {
|
||||
HubSpotCreateAssociationParams,
|
||||
HubSpotCreateAssociationResponse,
|
||||
} from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotCreateAssociation')
|
||||
|
||||
export const hubspotCreateAssociationTool: ToolConfig<
|
||||
HubSpotCreateAssociationParams,
|
||||
HubSpotCreateAssociationResponse
|
||||
> = {
|
||||
id: 'hubspot_create_association',
|
||||
name: 'Create Association in HubSpot',
|
||||
description:
|
||||
'Associate two HubSpot records. Creates the default (unlabeled) association unless an association type ID is provided',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
objectType: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Source object type (e.g., "emails", "notes", "contacts")',
|
||||
},
|
||||
objectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'ID of the source record',
|
||||
},
|
||||
toObjectType: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Target object type to associate to (e.g., "contacts", "companies", "deals")',
|
||||
},
|
||||
toObjectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'ID of the target record',
|
||||
},
|
||||
associationCategory: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Association category for a labeled association (HUBSPOT_DEFINED, USER_DEFINED, INTEGRATOR_DEFINED). Defaults to HUBSPOT_DEFINED when an association type ID is provided',
|
||||
},
|
||||
associationTypeId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Specific association type ID for a labeled association. Omit to create the default association for the object pair',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const from = `${encodeURIComponent(params.objectType.trim())}/${encodeURIComponent(params.objectId.trim())}`
|
||||
const to = `${encodeURIComponent(params.toObjectType.trim())}/${encodeURIComponent(params.toObjectId.trim())}`
|
||||
|
||||
return params.associationTypeId != null
|
||||
? `https://api.hubapi.com/crm/v4/objects/${from}/associations/${to}`
|
||||
: `https://api.hubapi.com/crm/v4/objects/${from}/associations/default/${to}`
|
||||
},
|
||||
method: 'PUT',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
if (params.associationTypeId != null) {
|
||||
headers['Content-Type'] = 'application/json'
|
||||
}
|
||||
return headers
|
||||
},
|
||||
body: (params) => {
|
||||
if (params.associationTypeId == null) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
associationCategory: params.associationCategory || 'HUBSPOT_DEFINED',
|
||||
associationTypeId: params.associationTypeId,
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to create association in HubSpot')
|
||||
}
|
||||
|
||||
const batchResult = Array.isArray(data.results) ? data.results[0] : undefined
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
fromObjectId: data.fromObjectId ?? batchResult?.from?.id ?? params?.objectId ?? '',
|
||||
toObjectId: data.toObjectId ?? batchResult?.to?.id ?? params?.toObjectId ?? '',
|
||||
labels: data.labels ?? [],
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
fromObjectId: { type: 'string', description: 'ID of the source record' },
|
||||
toObjectId: { type: 'string', description: 'ID of the associated target record' },
|
||||
labels: {
|
||||
type: 'array',
|
||||
description: 'Association labels (empty for default associations)',
|
||||
items: { type: 'string', description: 'Association label' },
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -72,8 +72,18 @@ export const hubspotCreateCompanyTool: ToolConfig<
|
||||
properties,
|
||||
}
|
||||
|
||||
if (params.associations && params.associations.length > 0) {
|
||||
body.associations = params.associations
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
|
||||
return body
|
||||
|
||||
@@ -73,8 +73,18 @@ export const hubspotCreateContactTool: ToolConfig<
|
||||
properties,
|
||||
}
|
||||
|
||||
if (params.associations && params.associations.length > 0) {
|
||||
body.associations = params.associations
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
|
||||
return body
|
||||
|
||||
@@ -9,7 +9,8 @@ export const hubspotCreateDealTool: ToolConfig<HubSpotCreateDealParams, HubSpotC
|
||||
{
|
||||
id: 'hubspot_create_deal',
|
||||
name: 'Create Deal in HubSpot',
|
||||
description: 'Create a new deal in HubSpot. Requires at least a dealname property',
|
||||
description:
|
||||
'Create a new deal in HubSpot with the given properties (e.g., dealname, amount, dealstage)',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
@@ -64,8 +65,18 @@ export const hubspotCreateDealTool: ToolConfig<HubSpotCreateDealParams, HubSpotC
|
||||
}
|
||||
}
|
||||
const body: Record<string, unknown> = { properties }
|
||||
if (params.associations && params.associations.length > 0) {
|
||||
body.associations = params.associations
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
return body
|
||||
},
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotCreateEmailParams, HubSpotCreateEmailResponse } from '@/tools/hubspot/types'
|
||||
import { EMAIL_OBJECT_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotCreateEmail')
|
||||
|
||||
export const hubspotCreateEmailTool: ToolConfig<
|
||||
HubSpotCreateEmailParams,
|
||||
HubSpotCreateEmailResponse
|
||||
> = {
|
||||
id: 'hubspot_create_email',
|
||||
name: 'Create Email in HubSpot',
|
||||
description:
|
||||
'Log an email engagement in HubSpot and optionally associate it with contacts. Requires the hs_timestamp property',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
properties: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Email properties as JSON object. Must include "hs_timestamp" (ISO 8601). Common fields: "hs_email_direction" (EMAIL, INCOMING_EMAIL, FORWARDED_EMAIL), "hs_email_status" (SENT, SENDING, SCHEDULED, FAILED, BOUNCED), "hs_email_subject", "hs_email_text", "hs_email_html", "hs_email_headers" (JSON string)',
|
||||
},
|
||||
associations: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of associations as JSON. Each object has "to.id" (record ID) and "types" array with "associationCategory" ("HUBSPOT_DEFINED") and "associationTypeId" (198 = email→contact)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => 'https://api.hubapi.com/crm/v3/objects/emails',
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
let properties = params.properties
|
||||
if (typeof properties === 'string') {
|
||||
try {
|
||||
properties = JSON.parse(properties)
|
||||
} catch (e) {
|
||||
throw new Error('Invalid JSON format for properties. Please provide a valid JSON object.')
|
||||
}
|
||||
}
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
properties,
|
||||
}
|
||||
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to create email in HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
email: data,
|
||||
emailId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
email: EMAIL_OBJECT_OUTPUT,
|
||||
emailId: { type: 'string', description: 'The created email engagement ID' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -67,8 +67,18 @@ export const hubspotCreateLineItemTool: ToolConfig<
|
||||
}
|
||||
}
|
||||
const body: Record<string, unknown> = { properties }
|
||||
if (params.associations && params.associations.length > 0) {
|
||||
body.associations = params.associations
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
return body
|
||||
},
|
||||
|
||||
@@ -72,7 +72,11 @@ export const hubspotCreateListTool: ToolConfig<HubSpotCreateListParams, HubSpotC
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: { list: data, listId: data.listId ?? data.id, success: true },
|
||||
output: {
|
||||
list: data.list ?? data,
|
||||
listId: data.list?.listId ?? data.listId ?? data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotCreateNoteParams, HubSpotCreateNoteResponse } from '@/tools/hubspot/types'
|
||||
import { NOTE_OBJECT_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotCreateNote')
|
||||
|
||||
export const hubspotCreateNoteTool: ToolConfig<HubSpotCreateNoteParams, HubSpotCreateNoteResponse> =
|
||||
{
|
||||
id: 'hubspot_create_note',
|
||||
name: 'Create Note in HubSpot',
|
||||
description:
|
||||
'Log a note in HubSpot and optionally associate it with contacts, companies, or deals. Requires hs_timestamp and hs_note_body properties',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
properties: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Note properties as JSON object. Must include "hs_timestamp" (ISO 8601 activity time) and "hs_note_body" (the note text). e.g., {"hs_timestamp": "2026-06-13T00:00:00Z", "hs_note_body": "Followed up via phone"}',
|
||||
},
|
||||
associations: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of associations as JSON. Each object has "to.id" (record ID) and "types" array with "associationCategory" ("HUBSPOT_DEFINED") and "associationTypeId" (202 = note→contact, 190 = note→company, 214 = note→deal)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => 'https://api.hubapi.com/crm/v3/objects/notes',
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
let properties = params.properties
|
||||
if (typeof properties === 'string') {
|
||||
try {
|
||||
properties = JSON.parse(properties)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for properties. Please provide a valid JSON object.'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
properties,
|
||||
}
|
||||
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to create note in HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
note: data,
|
||||
noteId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
note: NOTE_OBJECT_OUTPUT,
|
||||
noteId: { type: 'string', description: 'The created note ID' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -64,8 +64,18 @@ export const hubspotCreateTicketTool: ToolConfig<
|
||||
}
|
||||
}
|
||||
const body: Record<string, unknown> = { properties }
|
||||
if (params.associations && params.associations.length > 0) {
|
||||
body.associations = params.associations
|
||||
let associations = params.associations
|
||||
if (typeof associations === 'string') {
|
||||
try {
|
||||
associations = JSON.parse(associations)
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'Invalid JSON format for associations. Please provide a valid JSON array.'
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(associations) && associations.length > 0) {
|
||||
body.associations = associations
|
||||
}
|
||||
return body
|
||||
},
|
||||
|
||||
@@ -46,7 +46,7 @@ export const hubspotGetAppointmentTool: ToolConfig<
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_meeting_title,hs_meeting_start_time")',
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_appointment_name,hs_appointment_start")',
|
||||
},
|
||||
associations: {
|
||||
type: 'string',
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotGetEmailParams, HubSpotGetEmailResponse } from '@/tools/hubspot/types'
|
||||
import { EMAIL_OBJECT_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotGetEmail')
|
||||
|
||||
export const hubspotGetEmailTool: ToolConfig<HubSpotGetEmailParams, HubSpotGetEmailResponse> = {
|
||||
id: 'hubspot_get_email',
|
||||
name: 'Get Email from HubSpot',
|
||||
description:
|
||||
'Retrieve a single email engagement by ID from HubSpot (content requires the sales-email-read scope)',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
emailId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The HubSpot email engagement ID to retrieve',
|
||||
},
|
||||
properties: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_email_subject,hs_email_text,hs_timestamp")',
|
||||
},
|
||||
associations: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of object types to retrieve associated IDs for (e.g., "contacts,companies,deals")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.hubapi.com/crm/v3/objects/emails/${params.emailId.trim()}`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.properties) {
|
||||
queryParams.append('properties', params.properties)
|
||||
}
|
||||
if (params.associations) {
|
||||
queryParams.append('associations', params.associations)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to get email from HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
email: data,
|
||||
emailId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
email: EMAIL_OBJECT_OUTPUT,
|
||||
emailId: { type: 'string', description: 'The retrieved email engagement ID' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotGetNoteParams, HubSpotGetNoteResponse } from '@/tools/hubspot/types'
|
||||
import { NOTE_OBJECT_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotGetNote')
|
||||
|
||||
export const hubspotGetNoteTool: ToolConfig<HubSpotGetNoteParams, HubSpotGetNoteResponse> = {
|
||||
id: 'hubspot_get_note',
|
||||
name: 'Get Note from HubSpot',
|
||||
description: 'Retrieve a single note by ID from HubSpot',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
noteId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The HubSpot note ID to retrieve',
|
||||
},
|
||||
properties: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_note_body,hs_timestamp,hubspot_owner_id")',
|
||||
},
|
||||
associations: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of object types to retrieve associated IDs for (e.g., "contacts,companies,deals")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.hubapi.com/crm/v3/objects/notes/${params.noteId.trim()}`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.properties) {
|
||||
queryParams.append('properties', params.properties)
|
||||
}
|
||||
if (params.associations) {
|
||||
queryParams.append('associations', params.associations)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to get note from HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
note: data,
|
||||
noteId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
note: NOTE_OBJECT_OUTPUT,
|
||||
noteId: { type: 'string', description: 'The retrieved note ID' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type {
|
||||
HubSpotGetPropertiesParams,
|
||||
HubSpotGetPropertiesResponse,
|
||||
} from '@/tools/hubspot/types'
|
||||
import { PROPERTIES_ARRAY_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotGetProperties')
|
||||
|
||||
export const hubspotGetPropertiesTool: ToolConfig<
|
||||
HubSpotGetPropertiesParams,
|
||||
HubSpotGetPropertiesResponse
|
||||
> = {
|
||||
id: 'hubspot_get_properties',
|
||||
name: 'Get Properties from HubSpot',
|
||||
description:
|
||||
'Read property definitions and their enumeration (picklist) options for a HubSpot object type, e.g. the values for lifecyclestage or hs_lead_status on contacts',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
objectType: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Object type to read properties for (e.g., "contacts", "companies", "deals", "tickets", "line_items", "quotes")',
|
||||
},
|
||||
propertyName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Internal name of a single property to retrieve (e.g., "hs_lead_status"). Omit to return all properties for the object type',
|
||||
},
|
||||
archived: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to return only archived properties (default false)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const objectType = params.objectType.trim()
|
||||
const baseUrl = params.propertyName
|
||||
? `https://api.hubapi.com/crm/v3/properties/${encodeURIComponent(objectType)}/${encodeURIComponent(params.propertyName.trim())}`
|
||||
: `https://api.hubapi.com/crm/v3/properties/${encodeURIComponent(objectType)}`
|
||||
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.archived !== undefined) {
|
||||
queryParams.append('archived', String(params.archived))
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to get properties from HubSpot')
|
||||
}
|
||||
|
||||
const properties = Array.isArray(data.results) ? data.results : [data]
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
properties,
|
||||
metadata: {
|
||||
totalReturned: properties.length,
|
||||
objectType: params?.objectType ?? '',
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
properties: PROPERTIES_ARRAY_OUTPUT,
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Response metadata',
|
||||
properties: {
|
||||
totalReturned: { type: 'number', description: 'Number of property definitions returned' },
|
||||
objectType: { type: 'string', description: 'Object type the properties belong to' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotGetUsersParams, HubSpotGetUsersResponse } from '@/tools/hubspot/types'
|
||||
import { PAGING_OUTPUT, USERS_ARRAY_OUTPUT } from '@/tools/hubspot/types'
|
||||
import { GENERIC_CRM_ARRAY_OUTPUT, PAGING_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotGetUsers')
|
||||
@@ -27,7 +27,7 @@ export const hubspotGetUsersTool: ToolConfig<HubSpotGetUsersParams, HubSpotGetUs
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results to return (default: 100, max: 100)',
|
||||
description: 'Number of results to return (default: 10, max: 100)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
@@ -35,6 +35,13 @@ export const hubspotGetUsersTool: ToolConfig<HubSpotGetUsersParams, HubSpotGetUs
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor for next page of results (from previous response)',
|
||||
},
|
||||
properties: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot user property names to return (e.g., "hs_email,hs_given_name,hs_family_name")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
@@ -48,6 +55,9 @@ export const hubspotGetUsersTool: ToolConfig<HubSpotGetUsersParams, HubSpotGetUs
|
||||
if (params.after) {
|
||||
queryParams.append('after', params.after)
|
||||
}
|
||||
if (params.properties) {
|
||||
queryParams.append('properties', params.properties)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
@@ -87,7 +97,7 @@ export const hubspotGetUsersTool: ToolConfig<HubSpotGetUsersParams, HubSpotGetUs
|
||||
},
|
||||
|
||||
outputs: {
|
||||
users: USERS_ARRAY_OUTPUT,
|
||||
users: GENERIC_CRM_ARRAY_OUTPUT,
|
||||
paging: PAGING_OUTPUT,
|
||||
totalItems: { type: 'number', description: 'Total number of users returned' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
|
||||
@@ -1,35 +1,46 @@
|
||||
export { hubspotCreateAppointmentTool } from './create_appointment'
|
||||
export { hubspotCreateAssociationTool } from './create_association'
|
||||
export { hubspotCreateCompanyTool } from './create_company'
|
||||
export { hubspotCreateContactTool } from './create_contact'
|
||||
export { hubspotCreateDealTool } from './create_deal'
|
||||
export { hubspotCreateEmailTool } from './create_email'
|
||||
export { hubspotCreateLineItemTool } from './create_line_item'
|
||||
export { hubspotCreateListTool } from './create_list'
|
||||
export { hubspotCreateNoteTool } from './create_note'
|
||||
export { hubspotCreateTicketTool } from './create_ticket'
|
||||
export { hubspotGetAppointmentTool } from './get_appointment'
|
||||
export { hubspotGetCartTool } from './get_cart'
|
||||
export { hubspotGetCompanyTool } from './get_company'
|
||||
export { hubspotGetContactTool } from './get_contact'
|
||||
export { hubspotGetDealTool } from './get_deal'
|
||||
export { hubspotGetEmailTool } from './get_email'
|
||||
export { hubspotGetLineItemTool } from './get_line_item'
|
||||
export { hubspotGetListTool } from './get_list'
|
||||
export { hubspotGetMarketingEventTool } from './get_marketing_event'
|
||||
export { hubspotGetNoteTool } from './get_note'
|
||||
export { hubspotGetPropertiesTool } from './get_properties'
|
||||
export { hubspotGetQuoteTool } from './get_quote'
|
||||
export { hubspotGetTicketTool } from './get_ticket'
|
||||
export { hubspotGetUsersTool } from './get_users'
|
||||
export { hubspotListAppointmentsTool } from './list_appointments'
|
||||
export { hubspotListAssociationsTool } from './list_associations'
|
||||
export { hubspotListCartsTool } from './list_carts'
|
||||
export { hubspotListCompaniesTool } from './list_companies'
|
||||
export { hubspotListContactsTool } from './list_contacts'
|
||||
export { hubspotListDealsTool } from './list_deals'
|
||||
export { hubspotListEmailsTool } from './list_emails'
|
||||
export { hubspotListLineItemsTool } from './list_line_items'
|
||||
export { hubspotListListsTool } from './list_lists'
|
||||
export { hubspotListMarketingEventsTool } from './list_marketing_events'
|
||||
export { hubspotListNotesTool } from './list_notes'
|
||||
export { hubspotListOwnersTool } from './list_owners'
|
||||
export { hubspotListQuotesTool } from './list_quotes'
|
||||
export { hubspotListTicketsTool } from './list_tickets'
|
||||
export { hubspotSearchCompaniesTool } from './search_companies'
|
||||
export { hubspotSearchContactsTool } from './search_contacts'
|
||||
export { hubspotSearchDealsTool } from './search_deals'
|
||||
export { hubspotSearchEmailsTool } from './search_emails'
|
||||
export { hubspotSearchNotesTool } from './search_notes'
|
||||
export { hubspotSearchTicketsTool } from './search_tickets'
|
||||
export { hubspotUpdateAppointmentTool } from './update_appointment'
|
||||
export { hubspotUpdateCompanyTool } from './update_company'
|
||||
|
||||
@@ -46,7 +46,7 @@ export const hubspotListAppointmentsTool: ToolConfig<
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_meeting_title,hs_meeting_start_time")',
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_appointment_name,hs_appointment_start")',
|
||||
},
|
||||
associations: {
|
||||
type: 'string',
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type {
|
||||
HubSpotListAssociationsParams,
|
||||
HubSpotListAssociationsResponse,
|
||||
} from '@/tools/hubspot/types'
|
||||
import { ASSOCIATIONS_ARRAY_OUTPUT, METADATA_OUTPUT, PAGING_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotListAssociations')
|
||||
|
||||
export const hubspotListAssociationsTool: ToolConfig<
|
||||
HubSpotListAssociationsParams,
|
||||
HubSpotListAssociationsResponse
|
||||
> = {
|
||||
id: 'hubspot_list_associations',
|
||||
name: 'List Associations in HubSpot',
|
||||
description:
|
||||
'List records of one object type associated with a given record, e.g. all emails or notes logged on a contact',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
objectType: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Source object type (e.g., "contacts", "companies", "deals")',
|
||||
},
|
||||
objectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'ID of the source record',
|
||||
},
|
||||
toObjectType: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Target object type to list associations to (e.g., "emails", "notes", "deals")',
|
||||
},
|
||||
limit: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of associated records per page (default 500)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor for next page (from previous response)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.hubapi.com/crm/v4/objects/${encodeURIComponent(params.objectType.trim())}/${encodeURIComponent(params.objectId.trim())}/associations/${encodeURIComponent(params.toObjectType.trim())}`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.limit) {
|
||||
queryParams.append('limit', params.limit)
|
||||
}
|
||||
if (params.after) {
|
||||
queryParams.append('after', params.after)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to list associations from HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
results: data.results || [],
|
||||
paging: data.paging ?? null,
|
||||
metadata: {
|
||||
totalReturned: data.results?.length || 0,
|
||||
hasMore: !!data.paging?.next,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: ASSOCIATIONS_ARRAY_OUTPUT,
|
||||
paging: PAGING_OUTPUT,
|
||||
metadata: METADATA_OUTPUT,
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -33,7 +33,7 @@ export const hubspotListCompaniesTool: ToolConfig<
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results per page (max 100, default 100)',
|
||||
description: 'Maximum number of results per page (max 100, default 10)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
|
||||
@@ -30,7 +30,7 @@ export const hubspotListContactsTool: ToolConfig<
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results per page (max 100, default 100)',
|
||||
description: 'Maximum number of results per page (max 100, default 10)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotListEmailsParams, HubSpotListEmailsResponse } from '@/tools/hubspot/types'
|
||||
import { EMAILS_ARRAY_OUTPUT, METADATA_OUTPUT, PAGING_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotListEmails')
|
||||
|
||||
export const hubspotListEmailsTool: ToolConfig<HubSpotListEmailsParams, HubSpotListEmailsResponse> =
|
||||
{
|
||||
id: 'hubspot_list_emails',
|
||||
name: 'List Emails from HubSpot',
|
||||
description: 'Retrieve all email engagements from HubSpot account with pagination support',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
limit: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results per page (max 100, default 10)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor for next page of results (from previous response)',
|
||||
},
|
||||
properties: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_email_subject,hs_email_text,hs_timestamp")',
|
||||
},
|
||||
associations: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of object types to retrieve associated IDs for (e.g., "contacts,companies,deals")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = 'https://api.hubapi.com/crm/v3/objects/emails'
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.limit) {
|
||||
queryParams.append('limit', params.limit)
|
||||
}
|
||||
if (params.after) {
|
||||
queryParams.append('after', params.after)
|
||||
}
|
||||
if (params.properties) {
|
||||
queryParams.append('properties', params.properties)
|
||||
}
|
||||
if (params.associations) {
|
||||
queryParams.append('associations', params.associations)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to list emails from HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
emails: data.results || [],
|
||||
paging: data.paging ?? null,
|
||||
metadata: {
|
||||
totalReturned: data.results?.length || 0,
|
||||
hasMore: !!data.paging?.next,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
emails: EMAILS_ARRAY_OUTPUT,
|
||||
paging: PAGING_OUTPUT,
|
||||
metadata: METADATA_OUTPUT,
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -49,7 +49,7 @@ export const hubspotListMarketingEventsTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = 'https://api.hubapi.com/marketing/v3/marketing-events'
|
||||
const baseUrl = 'https://api.hubapi.com/marketing/marketing-events/v3'
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.limit) queryParams.append('limit', params.limit)
|
||||
if (params.after) queryParams.append('after', params.after)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotListNotesParams, HubSpotListNotesResponse } from '@/tools/hubspot/types'
|
||||
import { METADATA_OUTPUT, NOTES_ARRAY_OUTPUT, PAGING_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotListNotes')
|
||||
|
||||
export const hubspotListNotesTool: ToolConfig<HubSpotListNotesParams, HubSpotListNotesResponse> = {
|
||||
id: 'hubspot_list_notes',
|
||||
name: 'List Notes from HubSpot',
|
||||
description: 'Retrieve all notes from HubSpot account with pagination support',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
limit: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results per page (max 100, default 10)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor for next page of results (from previous response)',
|
||||
},
|
||||
properties: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of HubSpot property names to return (e.g., "hs_note_body,hs_timestamp,hubspot_owner_id")',
|
||||
},
|
||||
associations: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated list of object types to retrieve associated IDs for (e.g., "contacts,companies,deals")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = 'https://api.hubapi.com/crm/v3/objects/notes'
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.limit) {
|
||||
queryParams.append('limit', params.limit)
|
||||
}
|
||||
if (params.after) {
|
||||
queryParams.append('after', params.after)
|
||||
}
|
||||
if (params.properties) {
|
||||
queryParams.append('properties', params.properties)
|
||||
}
|
||||
if (params.associations) {
|
||||
queryParams.append('associations', params.associations)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to list notes from HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
notes: data.results || [],
|
||||
paging: data.paging ?? null,
|
||||
metadata: {
|
||||
totalReturned: data.results?.length || 0,
|
||||
hasMore: !!data.paging?.next,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
notes: NOTES_ARRAY_OUTPUT,
|
||||
paging: PAGING_OUTPUT,
|
||||
metadata: METADATA_OUTPUT,
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotSearchEmailsParams, HubSpotSearchEmailsResponse } from '@/tools/hubspot/types'
|
||||
import { EMAILS_ARRAY_OUTPUT, METADATA_OUTPUT, PAGING_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotSearchEmails')
|
||||
|
||||
export const hubspotSearchEmailsTool: ToolConfig<
|
||||
HubSpotSearchEmailsParams,
|
||||
HubSpotSearchEmailsResponse
|
||||
> = {
|
||||
id: 'hubspot_search_emails',
|
||||
name: 'Search Emails in HubSpot',
|
||||
description: 'Search for email engagements in HubSpot using filters, sorting, and queries',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
filterGroups: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of filter groups as JSON. Each group contains "filters" array with objects having "propertyName", "operator" (e.g., "EQ", "CONTAINS_TOKEN", "GT"), and "value"',
|
||||
},
|
||||
sorts: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of sort objects as JSON with "propertyName" and "direction" ("ASCENDING" or "DESCENDING")',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search query string to match against email text fields',
|
||||
},
|
||||
properties: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of HubSpot property names to return (e.g., ["hs_email_subject", "hs_email_text", "hs_timestamp"])',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results to return (max 100)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor for next page (from previous response)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => 'https://api.hubapi.com/crm/v3/objects/emails/search',
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
const body: any = {}
|
||||
|
||||
if (params.filterGroups) {
|
||||
let parsedFilterGroups = params.filterGroups
|
||||
if (typeof params.filterGroups === 'string') {
|
||||
try {
|
||||
parsedFilterGroups = JSON.parse(params.filterGroups)
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON for filterGroups: ${(e as Error).message}`)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(parsedFilterGroups) && parsedFilterGroups.length > 0) {
|
||||
body.filterGroups = parsedFilterGroups
|
||||
}
|
||||
}
|
||||
if (params.sorts) {
|
||||
let parsedSorts = params.sorts
|
||||
if (typeof params.sorts === 'string') {
|
||||
try {
|
||||
parsedSorts = JSON.parse(params.sorts)
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON for sorts: ${(e as Error).message}`)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {
|
||||
body.sorts = parsedSorts
|
||||
}
|
||||
}
|
||||
if (params.query) {
|
||||
body.query = params.query
|
||||
}
|
||||
if (params.properties) {
|
||||
let parsedProperties = params.properties
|
||||
if (typeof params.properties === 'string') {
|
||||
try {
|
||||
parsedProperties = JSON.parse(params.properties)
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON for properties: ${(e as Error).message}`)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(parsedProperties) && parsedProperties.length > 0) {
|
||||
body.properties = parsedProperties
|
||||
}
|
||||
}
|
||||
if (params.limit) {
|
||||
body.limit = params.limit
|
||||
}
|
||||
if (params.after) {
|
||||
body.after = params.after
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to search emails in HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
emails: data.results || [],
|
||||
total: data.total ?? 0,
|
||||
paging: data.paging ?? null,
|
||||
metadata: {
|
||||
totalReturned: data.results?.length || 0,
|
||||
hasMore: !!data.paging?.next,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
emails: EMAILS_ARRAY_OUTPUT,
|
||||
total: { type: 'number', description: 'Total number of matching emails', optional: true },
|
||||
paging: PAGING_OUTPUT,
|
||||
metadata: METADATA_OUTPUT,
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { HubSpotSearchNotesParams, HubSpotSearchNotesResponse } from '@/tools/hubspot/types'
|
||||
import { METADATA_OUTPUT, NOTES_ARRAY_OUTPUT, PAGING_OUTPUT } from '@/tools/hubspot/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('HubSpotSearchNotes')
|
||||
|
||||
export const hubspotSearchNotesTool: ToolConfig<
|
||||
HubSpotSearchNotesParams,
|
||||
HubSpotSearchNotesResponse
|
||||
> = {
|
||||
id: 'hubspot_search_notes',
|
||||
name: 'Search Notes in HubSpot',
|
||||
description: 'Search for notes in HubSpot using filters, sorting, and queries',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'hubspot',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the HubSpot API',
|
||||
},
|
||||
filterGroups: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of filter groups as JSON. Each group contains "filters" array with objects having "propertyName", "operator" (e.g., "EQ", "CONTAINS_TOKEN", "GT"), and "value"',
|
||||
},
|
||||
sorts: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of sort objects as JSON with "propertyName" and "direction" ("ASCENDING" or "DESCENDING")',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search query string to match against note text fields',
|
||||
},
|
||||
properties: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of HubSpot property names to return (e.g., ["hs_note_body", "hs_timestamp", "hubspot_owner_id"])',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results to return (max 100)',
|
||||
},
|
||||
after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor for next page (from previous response)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => 'https://api.hubapi.com/crm/v3/objects/notes/search',
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
const body: any = {}
|
||||
|
||||
if (params.filterGroups) {
|
||||
let parsedFilterGroups = params.filterGroups
|
||||
if (typeof params.filterGroups === 'string') {
|
||||
try {
|
||||
parsedFilterGroups = JSON.parse(params.filterGroups)
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON for filterGroups: ${(e as Error).message}`)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(parsedFilterGroups) && parsedFilterGroups.length > 0) {
|
||||
body.filterGroups = parsedFilterGroups
|
||||
}
|
||||
}
|
||||
if (params.sorts) {
|
||||
let parsedSorts = params.sorts
|
||||
if (typeof params.sorts === 'string') {
|
||||
try {
|
||||
parsedSorts = JSON.parse(params.sorts)
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON for sorts: ${(e as Error).message}`)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {
|
||||
body.sorts = parsedSorts
|
||||
}
|
||||
}
|
||||
if (params.query) {
|
||||
body.query = params.query
|
||||
}
|
||||
if (params.properties) {
|
||||
let parsedProperties = params.properties
|
||||
if (typeof params.properties === 'string') {
|
||||
try {
|
||||
parsedProperties = JSON.parse(params.properties)
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON for properties: ${(e as Error).message}`)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(parsedProperties) && parsedProperties.length > 0) {
|
||||
body.properties = parsedProperties
|
||||
}
|
||||
}
|
||||
if (params.limit) {
|
||||
body.limit = params.limit
|
||||
}
|
||||
if (params.after) {
|
||||
body.after = params.after
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error('HubSpot API request failed', { data, status: response.status })
|
||||
throw new Error(data.message || 'Failed to search notes in HubSpot')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
notes: data.results || [],
|
||||
total: data.total ?? 0,
|
||||
paging: data.paging ?? null,
|
||||
metadata: {
|
||||
totalReturned: data.results?.length || 0,
|
||||
hasMore: !!data.paging?.next,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
notes: NOTES_ARRAY_OUTPUT,
|
||||
total: { type: 'number', description: 'Total number of matching notes', optional: true },
|
||||
paging: PAGING_OUTPUT,
|
||||
metadata: METADATA_OUTPUT,
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
+361
-35
@@ -351,11 +351,10 @@ export const QUOTE_PROPERTIES_OUTPUT = {
|
||||
* @see https://developers.hubspot.com/docs/api/crm/appointments
|
||||
*/
|
||||
export const APPOINTMENT_PROPERTIES_OUTPUT = {
|
||||
hs_appointment_type: { type: 'string', description: 'Appointment type' },
|
||||
hs_meeting_title: { type: 'string', description: 'Meeting title' },
|
||||
hs_meeting_start_time: { type: 'string', description: 'Start time (ISO 8601)' },
|
||||
hs_meeting_end_time: { type: 'string', description: 'End time (ISO 8601)' },
|
||||
hs_meeting_location: { type: 'string', description: 'Meeting location' },
|
||||
hs_appointment_name: { type: 'string', description: 'Appointment title/name' },
|
||||
hs_appointment_start: { type: 'string', description: 'Start time (ISO 8601)' },
|
||||
hs_appointment_end: { type: 'string', description: 'End time (ISO 8601)' },
|
||||
hs_appointment_status: { type: 'string', description: 'Appointment status (e.g., SCHEDULED)' },
|
||||
hubspot_owner_id: { type: 'string', description: 'HubSpot owner ID' },
|
||||
hs_object_id: { type: 'string', description: 'HubSpot object ID (same as record ID)' },
|
||||
hs_createdate: { type: 'string', description: 'Creation date (ISO 8601)' },
|
||||
@@ -680,48 +679,217 @@ export const LISTS_ARRAY_OUTPUT: OutputProperty = {
|
||||
}
|
||||
|
||||
/**
|
||||
* User properties returned by HubSpot Settings API v3.
|
||||
* Note: firstName and lastName are NOT returned by the Settings API.
|
||||
* Use the Owners API if you need user names.
|
||||
* @see https://developers.hubspot.com/docs/reference/api/settings/users/user-provisioning
|
||||
* Common note properties returned by HubSpot API.
|
||||
* @see https://developers.hubspot.com/docs/api-reference/crm-notes-v3
|
||||
*/
|
||||
export const USER_OUTPUT_PROPERTIES = {
|
||||
id: { type: 'string', description: 'User ID' },
|
||||
email: { type: 'string', description: 'User email address' },
|
||||
roleId: { type: 'string', description: 'User role ID', optional: true },
|
||||
primaryTeamId: { type: 'string', description: 'Primary team ID', optional: true },
|
||||
secondaryTeamIds: {
|
||||
type: 'array',
|
||||
description: 'Secondary team IDs',
|
||||
optional: true,
|
||||
items: { type: 'string', description: 'Team ID' },
|
||||
export const NOTE_PROPERTIES_OUTPUT = {
|
||||
hs_note_body: { type: 'string', description: 'Note text/body (supports rich text/HTML)' },
|
||||
hs_timestamp: { type: 'string', description: 'Note activity time (ISO 8601)' },
|
||||
hubspot_owner_id: { type: 'string', description: 'HubSpot owner ID' },
|
||||
hs_attachment_ids: {
|
||||
type: 'string',
|
||||
description: 'Semicolon-separated IDs of files attached to the note',
|
||||
},
|
||||
superAdmin: { type: 'boolean', description: 'Whether user is a super admin', optional: true },
|
||||
hs_object_id: { type: 'string', description: 'HubSpot object ID (same as record ID)' },
|
||||
hs_createdate: { type: 'string', description: 'Note creation date (ISO 8601)' },
|
||||
hs_lastmodifieddate: { type: 'string', description: 'Last modified date (ISO 8601)' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Users array output definition for list endpoints.
|
||||
* Common email engagement properties returned by HubSpot API.
|
||||
* @see https://developers.hubspot.com/docs/api-reference/crm-emails-v3
|
||||
*/
|
||||
export const USERS_ARRAY_OUTPUT: OutputProperty = {
|
||||
export const EMAIL_PROPERTIES_OUTPUT = {
|
||||
hs_timestamp: { type: 'string', description: 'Email activity time (ISO 8601)' },
|
||||
hs_email_direction: {
|
||||
type: 'string',
|
||||
description: 'Direction (EMAIL = outgoing, INCOMING_EMAIL, FORWARDED_EMAIL)',
|
||||
},
|
||||
hs_email_status: {
|
||||
type: 'string',
|
||||
description: 'Send status (SENT, SENDING, SCHEDULED, FAILED, BOUNCED)',
|
||||
},
|
||||
hs_email_subject: { type: 'string', description: 'Email subject line' },
|
||||
hs_email_text: { type: 'string', description: 'Plain-text email body' },
|
||||
hs_email_html: { type: 'string', description: 'HTML email body' },
|
||||
hs_email_headers: { type: 'string', description: 'JSON-encoded from/to/cc/bcc headers' },
|
||||
hs_email_from_email: { type: 'string', description: 'Sender email address' },
|
||||
hs_email_to_email: { type: 'string', description: 'Recipient email address(es)' },
|
||||
hubspot_owner_id: { type: 'string', description: 'HubSpot owner ID' },
|
||||
hs_object_id: { type: 'string', description: 'HubSpot object ID (same as record ID)' },
|
||||
hs_createdate: { type: 'string', description: 'Email creation date (ISO 8601)' },
|
||||
hs_lastmodifieddate: { type: 'string', description: 'Last modified date (ISO 8601)' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Note object output definition with nested properties.
|
||||
*/
|
||||
export const NOTE_OBJECT_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'HubSpot note record',
|
||||
properties: {
|
||||
...CRM_RECORD_BASE_OUTPUT_PROPERTIES,
|
||||
properties: {
|
||||
type: 'object',
|
||||
description: 'Note properties',
|
||||
properties: NOTE_PROPERTIES_OUTPUT,
|
||||
},
|
||||
associations: {
|
||||
type: 'object',
|
||||
description: 'Associated records (contacts, companies, deals, etc.)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes array output definition for list/search endpoints.
|
||||
*/
|
||||
export const NOTES_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'Array of HubSpot user objects',
|
||||
description: 'Array of HubSpot note records',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: USER_OUTPUT_PROPERTIES,
|
||||
properties: {
|
||||
...CRM_RECORD_BASE_OUTPUT_PROPERTIES,
|
||||
properties: {
|
||||
type: 'object',
|
||||
description: 'Note properties',
|
||||
properties: NOTE_PROPERTIES_OUTPUT,
|
||||
},
|
||||
associations: { type: 'object', description: 'Associated records', optional: true },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Email object output definition with nested properties.
|
||||
*/
|
||||
export const EMAIL_OBJECT_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'HubSpot email engagement record',
|
||||
properties: {
|
||||
...CRM_RECORD_BASE_OUTPUT_PROPERTIES,
|
||||
properties: {
|
||||
type: 'object',
|
||||
description: 'Email properties',
|
||||
properties: EMAIL_PROPERTIES_OUTPUT,
|
||||
},
|
||||
associations: {
|
||||
type: 'object',
|
||||
description: 'Associated records (contacts, companies, deals, etc.)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Emails array output definition for list/search endpoints.
|
||||
*/
|
||||
export const EMAILS_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'Array of HubSpot email engagement records',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
...CRM_RECORD_BASE_OUTPUT_PROPERTIES,
|
||||
properties: {
|
||||
type: 'object',
|
||||
description: 'Email properties',
|
||||
properties: EMAIL_PROPERTIES_OUTPUT,
|
||||
},
|
||||
associations: { type: 'object', description: 'Associated records', optional: true },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Property option output (picklist/enumeration value).
|
||||
* @see https://developers.hubspot.com/docs/api-reference/crm-properties-v3
|
||||
*/
|
||||
export const PROPERTY_OPTION_OUTPUT_PROPERTIES = {
|
||||
label: { type: 'string', description: 'Human-readable option label' },
|
||||
value: { type: 'string', description: 'Internal value used when setting the property' },
|
||||
displayOrder: { type: 'number', description: 'Display order (-1 sorts last)', optional: true },
|
||||
hidden: { type: 'boolean', description: 'Whether the option is hidden in the HubSpot UI' },
|
||||
description: { type: 'string', description: 'Option description', optional: true },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Property definitions array output for the properties endpoint.
|
||||
*/
|
||||
export const PROPERTIES_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'Array of HubSpot property definitions',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Internal property name' },
|
||||
label: { type: 'string', description: 'Human-readable label' },
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Property data type (string, number, enumeration, bool, datetime, etc.)',
|
||||
},
|
||||
fieldType: { type: 'string', description: 'Field type controlling HubSpot UI rendering' },
|
||||
description: { type: 'string', description: 'Property help text' },
|
||||
groupName: { type: 'string', description: 'Property group the property belongs to' },
|
||||
options: {
|
||||
type: 'array',
|
||||
description: 'Enumeration/picklist options (empty for non-enumerated properties)',
|
||||
items: { type: 'object', properties: PROPERTY_OPTION_OUTPUT_PROPERTIES },
|
||||
},
|
||||
displayOrder: { type: 'number', description: 'Display order', optional: true },
|
||||
calculated: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the property is calculated by HubSpot',
|
||||
optional: true,
|
||||
},
|
||||
hidden: { type: 'boolean', description: 'Whether the property is hidden', optional: true },
|
||||
hubspotDefined: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the property is a HubSpot default property',
|
||||
optional: true,
|
||||
},
|
||||
archived: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the property is archived',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Associations array output for the v4 associations list endpoint.
|
||||
*/
|
||||
export const ASSOCIATIONS_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'Array of associated records',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
toObjectId: { type: 'string', description: 'ID of the associated (target) record' },
|
||||
associationTypes: {
|
||||
type: 'array',
|
||||
description: 'Association types linking the two records',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
category: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Association category (HUBSPOT_DEFINED, USER_DEFINED, INTEGRATOR_DEFINED)',
|
||||
},
|
||||
typeId: { type: 'number', description: 'Association type ID' },
|
||||
label: { type: 'string', description: 'Association label', optional: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Common HubSpot types
|
||||
interface HubSpotUser {
|
||||
id: string
|
||||
email: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
roleId?: string
|
||||
primaryTeamId?: string
|
||||
superAdmin?: boolean
|
||||
}
|
||||
|
||||
interface HubSpotCrmObject {
|
||||
id: string
|
||||
properties: Record<string, any>
|
||||
@@ -744,7 +912,7 @@ interface HubSpotPaging {
|
||||
// Users
|
||||
export interface HubSpotGetUsersResponse extends ToolResponse {
|
||||
output: {
|
||||
users: HubSpotUser[]
|
||||
users: HubSpotCrmObject[]
|
||||
paging: HubSpotPaging | null
|
||||
totalItems?: number
|
||||
success: boolean
|
||||
@@ -755,6 +923,7 @@ export interface HubSpotGetUsersParams {
|
||||
accessToken: string
|
||||
limit?: string
|
||||
after?: string
|
||||
properties?: string
|
||||
}
|
||||
|
||||
// List Contacts
|
||||
@@ -1216,6 +1385,152 @@ export interface HubSpotCreateListResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// Notes
|
||||
export type HubSpotNote = HubSpotCrmObject
|
||||
export type HubSpotCreateNoteParams = HubSpotCreateContactParams
|
||||
export type HubSpotCreateNoteResponse = ToolResponse & {
|
||||
output: { note: HubSpotContact; noteId: string; success: boolean }
|
||||
}
|
||||
export type HubSpotGetNoteParams = Omit<HubSpotGetContactParams, 'contactId'> & { noteId: string }
|
||||
export type HubSpotGetNoteResponse = ToolResponse & {
|
||||
output: { note: HubSpotContact; noteId: string; success: boolean }
|
||||
}
|
||||
export type HubSpotListNotesParams = HubSpotListContactsParams
|
||||
export type HubSpotListNotesResponse = ToolResponse & {
|
||||
output: {
|
||||
notes: HubSpotContact[]
|
||||
paging?: HubSpotPaging
|
||||
metadata: { totalReturned: number; hasMore: boolean }
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
export type HubSpotSearchNotesParams = HubSpotSearchContactsParams
|
||||
export interface HubSpotSearchNotesResponse extends ToolResponse {
|
||||
output: {
|
||||
notes: HubSpotContact[]
|
||||
total: number
|
||||
paging?: HubSpotPaging
|
||||
metadata: { totalReturned: number; hasMore: boolean }
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Emails
|
||||
export type HubSpotEmail = HubSpotCrmObject
|
||||
export type HubSpotCreateEmailParams = HubSpotCreateContactParams
|
||||
export type HubSpotCreateEmailResponse = ToolResponse & {
|
||||
output: { email: HubSpotContact; emailId: string; success: boolean }
|
||||
}
|
||||
export type HubSpotGetEmailParams = Omit<HubSpotGetContactParams, 'contactId'> & { emailId: string }
|
||||
export type HubSpotGetEmailResponse = ToolResponse & {
|
||||
output: { email: HubSpotContact; emailId: string; success: boolean }
|
||||
}
|
||||
export type HubSpotListEmailsParams = HubSpotListContactsParams
|
||||
export type HubSpotListEmailsResponse = ToolResponse & {
|
||||
output: {
|
||||
emails: HubSpotContact[]
|
||||
paging?: HubSpotPaging
|
||||
metadata: { totalReturned: number; hasMore: boolean }
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
export type HubSpotSearchEmailsParams = HubSpotSearchContactsParams
|
||||
export interface HubSpotSearchEmailsResponse extends ToolResponse {
|
||||
output: {
|
||||
emails: HubSpotContact[]
|
||||
total: number
|
||||
paging?: HubSpotPaging
|
||||
metadata: { totalReturned: number; hasMore: boolean }
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Properties
|
||||
interface HubSpotPropertyOption {
|
||||
label: string
|
||||
value: string
|
||||
displayOrder?: number
|
||||
hidden: boolean
|
||||
description?: string
|
||||
}
|
||||
|
||||
interface HubSpotProperty {
|
||||
name: string
|
||||
label: string
|
||||
type: string
|
||||
fieldType: string
|
||||
description: string
|
||||
groupName: string
|
||||
options: HubSpotPropertyOption[]
|
||||
displayOrder?: number
|
||||
calculated?: boolean
|
||||
hidden?: boolean
|
||||
hubspotDefined?: boolean
|
||||
archived?: boolean
|
||||
}
|
||||
|
||||
export interface HubSpotGetPropertiesParams {
|
||||
accessToken: string
|
||||
objectType: string
|
||||
propertyName?: string
|
||||
archived?: boolean
|
||||
}
|
||||
|
||||
export interface HubSpotGetPropertiesResponse extends ToolResponse {
|
||||
output: {
|
||||
properties: HubSpotProperty[]
|
||||
metadata: { totalReturned: number; objectType: string }
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Associations (v4)
|
||||
interface HubSpotAssociatedObject {
|
||||
toObjectId: string
|
||||
associationTypes: Array<{
|
||||
category: string
|
||||
typeId: number
|
||||
label?: string
|
||||
}>
|
||||
}
|
||||
|
||||
export interface HubSpotListAssociationsParams {
|
||||
accessToken: string
|
||||
objectType: string
|
||||
objectId: string
|
||||
toObjectType: string
|
||||
limit?: string
|
||||
after?: string
|
||||
}
|
||||
|
||||
export interface HubSpotListAssociationsResponse extends ToolResponse {
|
||||
output: {
|
||||
results: HubSpotAssociatedObject[]
|
||||
paging?: HubSpotPaging
|
||||
metadata: { totalReturned: number; hasMore: boolean }
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface HubSpotCreateAssociationParams {
|
||||
accessToken: string
|
||||
objectType: string
|
||||
objectId: string
|
||||
toObjectType: string
|
||||
toObjectId: string
|
||||
associationCategory?: string
|
||||
associationTypeId?: number
|
||||
}
|
||||
|
||||
export interface HubSpotCreateAssociationResponse extends ToolResponse {
|
||||
output: {
|
||||
fromObjectId: string
|
||||
toObjectId: string
|
||||
labels: string[]
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Generic HubSpot response type for the block
|
||||
export type HubSpotResponse =
|
||||
| HubSpotGetUsersResponse
|
||||
@@ -1257,3 +1572,14 @@ export type HubSpotResponse =
|
||||
| HubSpotListListsResponse
|
||||
| HubSpotGetListResponse
|
||||
| HubSpotCreateListResponse
|
||||
| HubSpotCreateNoteResponse
|
||||
| HubSpotGetNoteResponse
|
||||
| HubSpotListNotesResponse
|
||||
| HubSpotSearchNotesResponse
|
||||
| HubSpotCreateEmailResponse
|
||||
| HubSpotGetEmailResponse
|
||||
| HubSpotListEmailsResponse
|
||||
| HubSpotSearchEmailsResponse
|
||||
| HubSpotGetPropertiesResponse
|
||||
| HubSpotListAssociationsResponse
|
||||
| HubSpotCreateAssociationResponse
|
||||
|
||||
@@ -46,7 +46,7 @@ export const hubspotUpdateAppointmentTool: ToolConfig<
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Appointment properties to update as JSON object (e.g., {"hs_meeting_title": "Updated Call", "hs_meeting_location": "Zoom"})',
|
||||
'Appointment properties to update as JSON object (e.g., {"hs_appointment_name": "Updated Call", "hs_appointment_start": "2024-01-15T10:00:00Z"})',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -1415,37 +1415,48 @@ import {
|
||||
import { httpRequestTool, webhookRequestTool } from '@/tools/http'
|
||||
import {
|
||||
hubspotCreateAppointmentTool,
|
||||
hubspotCreateAssociationTool,
|
||||
hubspotCreateCompanyTool,
|
||||
hubspotCreateContactTool,
|
||||
hubspotCreateDealTool,
|
||||
hubspotCreateEmailTool,
|
||||
hubspotCreateLineItemTool,
|
||||
hubspotCreateListTool,
|
||||
hubspotCreateNoteTool,
|
||||
hubspotCreateTicketTool,
|
||||
hubspotGetAppointmentTool,
|
||||
hubspotGetCartTool,
|
||||
hubspotGetCompanyTool,
|
||||
hubspotGetContactTool,
|
||||
hubspotGetDealTool,
|
||||
hubspotGetEmailTool,
|
||||
hubspotGetLineItemTool,
|
||||
hubspotGetListTool,
|
||||
hubspotGetMarketingEventTool,
|
||||
hubspotGetNoteTool,
|
||||
hubspotGetPropertiesTool,
|
||||
hubspotGetQuoteTool,
|
||||
hubspotGetTicketTool,
|
||||
hubspotGetUsersTool,
|
||||
hubspotListAppointmentsTool,
|
||||
hubspotListAssociationsTool,
|
||||
hubspotListCartsTool,
|
||||
hubspotListCompaniesTool,
|
||||
hubspotListContactsTool,
|
||||
hubspotListDealsTool,
|
||||
hubspotListEmailsTool,
|
||||
hubspotListLineItemsTool,
|
||||
hubspotListListsTool,
|
||||
hubspotListMarketingEventsTool,
|
||||
hubspotListNotesTool,
|
||||
hubspotListOwnersTool,
|
||||
hubspotListQuotesTool,
|
||||
hubspotListTicketsTool,
|
||||
hubspotSearchCompaniesTool,
|
||||
hubspotSearchContactsTool,
|
||||
hubspotSearchDealsTool,
|
||||
hubspotSearchEmailsTool,
|
||||
hubspotSearchNotesTool,
|
||||
hubspotSearchTicketsTool,
|
||||
hubspotUpdateAppointmentTool,
|
||||
hubspotUpdateCompanyTool,
|
||||
@@ -6468,37 +6479,48 @@ export const tools: Record<string, ToolConfig> = {
|
||||
infisical_update_secret: infisicalUpdateSecretTool,
|
||||
infisical_delete_secret: infisicalDeleteSecretTool,
|
||||
hubspot_create_appointment: hubspotCreateAppointmentTool,
|
||||
hubspot_create_association: hubspotCreateAssociationTool,
|
||||
hubspot_create_company: hubspotCreateCompanyTool,
|
||||
hubspot_create_contact: hubspotCreateContactTool,
|
||||
hubspot_create_deal: hubspotCreateDealTool,
|
||||
hubspot_create_email: hubspotCreateEmailTool,
|
||||
hubspot_create_line_item: hubspotCreateLineItemTool,
|
||||
hubspot_create_list: hubspotCreateListTool,
|
||||
hubspot_create_note: hubspotCreateNoteTool,
|
||||
hubspot_create_ticket: hubspotCreateTicketTool,
|
||||
hubspot_get_appointment: hubspotGetAppointmentTool,
|
||||
hubspot_get_cart: hubspotGetCartTool,
|
||||
hubspot_get_company: hubspotGetCompanyTool,
|
||||
hubspot_get_contact: hubspotGetContactTool,
|
||||
hubspot_get_deal: hubspotGetDealTool,
|
||||
hubspot_get_email: hubspotGetEmailTool,
|
||||
hubspot_get_line_item: hubspotGetLineItemTool,
|
||||
hubspot_get_list: hubspotGetListTool,
|
||||
hubspot_get_marketing_event: hubspotGetMarketingEventTool,
|
||||
hubspot_get_note: hubspotGetNoteTool,
|
||||
hubspot_get_properties: hubspotGetPropertiesTool,
|
||||
hubspot_get_quote: hubspotGetQuoteTool,
|
||||
hubspot_get_ticket: hubspotGetTicketTool,
|
||||
hubspot_get_users: hubspotGetUsersTool,
|
||||
hubspot_list_appointments: hubspotListAppointmentsTool,
|
||||
hubspot_list_associations: hubspotListAssociationsTool,
|
||||
hubspot_list_carts: hubspotListCartsTool,
|
||||
hubspot_list_companies: hubspotListCompaniesTool,
|
||||
hubspot_list_contacts: hubspotListContactsTool,
|
||||
hubspot_list_deals: hubspotListDealsTool,
|
||||
hubspot_list_emails: hubspotListEmailsTool,
|
||||
hubspot_list_line_items: hubspotListLineItemsTool,
|
||||
hubspot_list_lists: hubspotListListsTool,
|
||||
hubspot_list_marketing_events: hubspotListMarketingEventsTool,
|
||||
hubspot_list_notes: hubspotListNotesTool,
|
||||
hubspot_list_owners: hubspotListOwnersTool,
|
||||
hubspot_list_quotes: hubspotListQuotesTool,
|
||||
hubspot_list_tickets: hubspotListTicketsTool,
|
||||
hubspot_search_companies: hubspotSearchCompaniesTool,
|
||||
hubspot_search_contacts: hubspotSearchContactsTool,
|
||||
hubspot_search_deals: hubspotSearchDealsTool,
|
||||
hubspot_search_emails: hubspotSearchEmailsTool,
|
||||
hubspot_search_notes: hubspotSearchNotesTool,
|
||||
hubspot_search_tickets: hubspotSearchTicketsTool,
|
||||
hubspot_update_appointment: hubspotUpdateAppointmentTool,
|
||||
hubspot_update_company: hubspotUpdateCompanyTool,
|
||||
|
||||
Reference in New Issue
Block a user