Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
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
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 > 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' },
},
}
94 changes: 94 additions & 0 deletions apps/sim/tools/hubspot/create_line_item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { createLogger } from '@sim/logger'
import type {
HubSpotCreateLineItemParams,
HubSpotCreateLineItemResponse,
} from '@/tools/hubspot/types'
import { LINE_ITEM_OBJECT_OUTPUT } from '@/tools/hubspot/types'
import type { ToolConfig } from '@/tools/types'

const logger = createLogger('HubSpotCreateLineItem')

export const hubspotCreateLineItemTool: ToolConfig<
HubSpotCreateLineItemParams,
HubSpotCreateLineItemResponse
> = {
id: 'hubspot_create_line_item',
name: 'Create Line Item in HubSpot',
description: 'Create a new line item in HubSpot. Requires at least a name 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:
'Line item properties as JSON object (e.g., {"name": "Product A", "quantity": "2", "price": "50.00", "hs_sku": "SKU-001"})',
},
associations: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description:
'Array of associations to create with the line item as JSON. Each object should have "to.id" and "types" array with "associationCategory" and "associationTypeId"',
},
},

request: {
url: () => 'https://api.hubapi.com/crm/v3/objects/line_items',
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 line item in HubSpot')
}
return {
success: true,
output: { lineItem: data, lineItemId: data.id, success: true },
}
},

outputs: {
lineItem: LINE_ITEM_OBJECT_OUTPUT,
lineItemId: { type: 'string', description: 'The created line item ID' },
success: { type: 'boolean', description: 'Operation success status' },
},
}
Loading
Loading