Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions apps/docs/components/ui/icon-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ import {
DatadogIcon,
DevinIcon,
DiscordIcon,
DocumentIcon,
DocuSignIcon,
DocumentIcon,
DropboxIcon,
DsPyIcon,
DubIcon,
Expand All @@ -50,8 +50,8 @@ import {
FirecrawlIcon,
FirefliesIcon,
GammaIcon,
GithubIcon,
GitLabIcon,
GithubIcon,
GmailIcon,
GongIcon,
GoogleAdsIcon,
Expand Down Expand Up @@ -95,9 +95,9 @@ import {
LinkupIcon,
LoopsIcon,
LumaIcon,
MailServerIcon,
MailchimpIcon,
MailgunIcon,
MailServerIcon,
Mem0Icon,
MicrosoftDataverseIcon,
MicrosoftExcelIcon,
Expand Down Expand Up @@ -134,6 +134,8 @@ import {
ResendIcon,
RevenueCatIcon,
S3Icon,
SQSIcon,
STTIcon,
SalesforceIcon,
SearchIcon,
SendgridIcon,
Expand All @@ -145,19 +147,17 @@ import {
SimilarwebIcon,
SlackIcon,
SmtpIcon,
SQSIcon,
SshIcon,
STTIcon,
StagehandIcon,
StripeIcon,
SupabaseIcon,
TTSIcon,
TavilyIcon,
TelegramIcon,
TextractIcon,
TinybirdIcon,
TranslateIcon,
TrelloIcon,
TTSIcon,
TwilioIcon,
TypeformIcon,
UpstashIcon,
Expand All @@ -169,11 +169,11 @@ import {
WikipediaIcon,
WordpressIcon,
WorkdayIcon,
xIcon,
YouTubeIcon,
ZendeskIcon,
ZepIcon,
ZoomIcon,
xIcon,
} from '@/components/icons'

type IconComponent = ComponentType<SVGProps<SVGSVGElement>>
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/en/tools/hubspot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ Retrieve all deals 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., "dealname,amount,dealstage"\) |
| `associations` | string | No | Comma-separated list of object types to retrieve associated IDs for \(e.g., "contacts,companies"\) |
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/en/tools/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,4 @@
"zep",
"zoom"
]
}
}
5 changes: 3 additions & 2 deletions apps/docs/content/docs/en/tools/quiver.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ Generate SVG images from text prompts using QuiverAI
| --------- | ---- | ----------- |
| `success` | boolean | Whether the SVG generation succeeded |
| `output` | object | Generated SVG output |
| ↳ `file` | file | Generated SVG file |
| ↳ `svgContent` | string | Raw SVG markup content |
| ↳ `file` | file | First generated SVG file |
| ↳ `files` | json | All generated SVG files \(when n &gt; 1\) |
| ↳ `svgContent` | string | Raw SVG markup content of the first result |
| ↳ `id` | string | Generation request ID |
| ↳ `usage` | json | Token usage statistics |
| ↳ `totalTokens` | number | Total tokens used |
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/connectors/hubspot/hubspot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export const hubspotConnector: ConnectorConfig = {
'crm.objects.contacts.read',
'crm.objects.companies.read',
'crm.objects.deals.read',
'crm.objects.tickets.read',
'tickets',
],
},

Expand Down
2 changes: 0 additions & 2 deletions apps/sim/lib/oauth/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,8 +886,6 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
'crm.import',
'crm.lists.read',
'crm.lists.write',
'crm.objects.tickets.read',
'crm.objects.tickets.write',
'tickets',
'oauth',
],
Expand Down
94 changes: 94 additions & 0 deletions apps/sim/tools/hubspot/create_appointment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { createLogger } from '@sim/logger'
import type {
HubSpotCreateAppointmentParams,
HubSpotCreateAppointmentResponse,
} from '@/tools/hubspot/types'
import { APPOINTMENT_OBJECT_OUTPUT } from '@/tools/hubspot/types'
import type { ToolConfig } from '@/tools/types'

const logger = createLogger('HubSpotCreateAppointment')

export const hubspotCreateAppointmentTool: ToolConfig<
HubSpotCreateAppointmentParams,
HubSpotCreateAppointmentResponse
> = {
id: 'hubspot_create_appointment',
name: 'Create Appointment in HubSpot',
description: 'Create a new appointment in 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',
},
properties: {
type: 'object',
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"})',
},
associations: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description:
'Array of associations to create with the appointment as JSON. Each object should have "to.id" and "types" array with "associationCategory" and "associationTypeId"',
},
},

request: {
url: () => 'https://api.hubapi.com/crm/v3/objects/appointments',
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 }
if (params.associations && params.associations.length > 0) {
body.associations = params.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 appointment in HubSpot')
}
return {
success: true,
output: { appointment: data, appointmentId: data.id, success: true },
}
},

outputs: {
appointment: APPOINTMENT_OBJECT_OUTPUT,
appointmentId: { type: 'string', description: 'The created appointment ID' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
91 changes: 91 additions & 0 deletions apps/sim/tools/hubspot/create_deal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { createLogger } from '@sim/logger'
import type { HubSpotCreateDealParams, HubSpotCreateDealResponse } from '@/tools/hubspot/types'
import { DEAL_OBJECT_OUTPUT } from '@/tools/hubspot/types'
import type { ToolConfig } from '@/tools/types'

const logger = createLogger('HubSpotCreateDeal')

export const hubspotCreateDealTool: ToolConfig<HubSpotCreateDealParams, HubSpotCreateDealResponse> =
{
id: 'hubspot_create_deal',
name: 'Create Deal in HubSpot',
description: 'Create a new deal in HubSpot. Requires at least a dealname 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:
'Deal properties as JSON object. Must include dealname (e.g., {"dealname": "New Deal", "amount": "5000", "dealstage": "appointmentscheduled"})',
},
associations: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description:
'Array of associations to create with the deal as JSON. Each object should have "to.id" and "types" array with "associationCategory" and "associationTypeId"',
},
},

request: {
url: () => 'https://api.hubapi.com/crm/v3/objects/deals',
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 }
if (params.associations && params.associations.length > 0) {
body.associations = params.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 deal in HubSpot')
}
return {
success: true,
output: { deal: data, dealId: data.id, success: true },
}
},

outputs: {
deal: DEAL_OBJECT_OUTPUT,
dealId: { type: 'string', description: 'The created deal ID' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
Loading
Loading