Skip to content

Commit

Permalink
feat(hubspot): [nan-1848] additional hubspot syncs (#42)
Browse files Browse the repository at this point in the history
## Describe your changes
Add hubspot syncs:
- deals - includes associations 
- companies
- currency codes
- Improved contacts sync with primary company id included which is an
association

Add hubspot actions:
- fetch-account-information
- fetch-custom-object

## Issue ticket number and link
NAN-1848

## Checklist before requesting a review (skip if just adding/editing
APIs & templates)
- [x] I added tests, otherwise the reason is:
- [x] External API requests have `retries`
- [x] Pagination is used where appropriate
- [x] The built in `nango.paginate` call is used instead of a `while
(true)` loop
- [x] Third party requests are NOT parallelized (this can cause issues
with rate limits)
- [x] If a sync requires metadata the `nango.yaml` has `auto_start:
false`
- [x] If the sync is a `full` sync then `track_deletes: true` is set
  • Loading branch information
khaliqgant authored Oct 9, 2024
1 parent f201232 commit 25f6f19
Show file tree
Hide file tree
Showing 36 changed files with 13,762 additions and 56 deletions.
139 changes: 135 additions & 4 deletions flows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2364,17 +2364,22 @@ integrations:
endpoint: GET /service-tickets
contacts:
runs: every day
description: |
Fetches a list of contacts from Hubspot
output: HubspotContact
description: >
Fetches a list of contacts from Hubspot with the primary associated
company
output: Contact
sync_type: full
track_deletes: true
version: 1.0.0
endpoint: GET /contacts
owners:
runs: every day
description: |
Fetches a list of owners from Hubspot
output: HubspotOwner
sync_type: full
track_deletes: true
version: 1.0.0
endpoint: GET /owners
users:
runs: every day
Expand All @@ -2394,7 +2399,41 @@ integrations:
Fetches a list of knowledge base from Hubspot
output: HubspotKnowledgeBase
sync_type: full
track_deletes: true
endpoint: GET /knowledge-base
deals:
runs: every day
description: >
Fetch hubspot deals with the corresponding line items and associated
companies and contacts.
output: Deal
sync_type: full
track_deletes: true
endpoint: GET /deals
scopes:
- crm.objects.deals.read
- e-commerce (standard scope)
- crm.objects.line_items.read (granular scope)
companies:
runs: every day
description: |
Fetch hubspot companies
output: Company
sync_type: full
track_deletes: true
endpoint: GET /companies
scopes:
- crm.objects.companies.read
currency-codes:
runs: every day
description: |
Fetch hubspot deals
output: CurrencyCode
sync_type: full
track_deletes: true
endpoint: GET /currency-codes
scopes:
- settings.currencies.read
actions:
fetch-properties:
description: Fetch the properties of a specified object
Expand Down Expand Up @@ -2439,6 +2478,18 @@ integrations:
scopes:
- settings.users.write (standard scope)
- crm.objects.users.write (granular scope)
fetch-account-information:
description: Fetch the account information from Hubspot
output: Account
endpoint: GET /account-information
scopes:
- oauth
fetch-custom-objects:
description: Fetch custom objects in Hubspot. Requires Hubspot enterprise
output: CustomObject
endpoint: GET /custom-objects
scopes:
- crm.schemas.custom.read
models:
IdEntity:
id: string
Expand Down Expand Up @@ -2556,13 +2607,55 @@ integrations:
category: string
content: string
publishDate: number
HubspotContact:
Contact:
id: string
created_at: string
updated_at: string
first_name: string
last_name: string
email: string
primaryContactId?: string
Account:
id: string
type: string
timeZone: string
companyCurrency: string
additionalCurrencies: string[]
utcOffset: string
utcOffsetMilliseconds: number
uiDomain: string
dataHostingLocation: string
Deal:
createdate: string
days_to_close: string
dealname: string
hs_closed_amount: string
hs_closed_amount_in_home_currency: string
hs_closed_won_count: string
hs_createdate: string
hs_days_to_close_raw: string
hs_deal_stage_probability_shadow: string
hs_is_closed_lost: string
hs_is_closed_won: string
hs_is_deal_split: string
hs_lastmodifieddate: string
hs_object_id: string
hs_object_source: string
hs_object_source_id: string
hs_object_source_label: string
hs_projected_amount: string
hs_projected_amount_in_home_currency: string
id: string
companies?: CompanyAssociation[]
contacts?:
- id: string
lineItems?:
id: string
__extends: LineItemDefaultProperties
__string: any
CompanyAssociation:
id: string
primary: boolean
CreateDeal:
properties:
dealname: string
Expand Down Expand Up @@ -2593,6 +2686,44 @@ integrations:
createdAt: string
updatedAt: string
archived: boolean
CurrencyCode:
id: string
code: string
description: string
Association:
id: string
Company:
id: string
createdAt: string
updatedAt: string
name: string
domain: string
archived: boolean
LineItem:
name: string
price: string
quantity: string
recurringbillingfrequency: null | number
tax: null | number
amount: string
createdate: string
description: string
discount: null | number
id: string
__string: any
LineItemDefaultProperties:
name: string
price: string
quantity: string
recurringbillingfrequency: null | number
tax: null | number
amount: string
createdate: string
description: string
discount: null | number
CustomObject:
id: string
__string: any
instantly:
actions:
set-campaign-name:
Expand Down
24 changes: 24 additions & 0 deletions integrations/hubspot/actions/fetch-account-information.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { NangoAction, Account, ProxyConfiguration } from '../../models';
import type { HubspotAccountInformation } from '../types';

export default async function runAction(nango: NangoAction): Promise<Account> {
const config: ProxyConfiguration = {
// https://developers.hubspot.com/docs/api/settings/account-information-api
endpoint: '/account-info/v3/details',
retries: 10
};

const response = await nango.get<HubspotAccountInformation>(config);

return {
id: response.data.portalId.toString(),
type: response.data.accountType,
timeZone: response.data.timeZone,
companyCurrency: response.data.companyCurrency,
additionalCurrencies: response.data.additionalCurrencies,
utcOffset: response.data.utcOffset,
utcOffsetMilliseconds: response.data.utcOffsetMilliseconds,
uiDomain: response.data.uiDomain,
dataHostingLocation: response.data.dataHostingLocation
};
}
13 changes: 13 additions & 0 deletions integrations/hubspot/actions/fetch-custom-objects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { NangoAction, CustomObject, ProxyConfiguration } from '../../models';

export default async function runAction(nango: NangoAction): Promise<CustomObject> {
const config: ProxyConfiguration = {
// https://developers.hubspot.com/docs/api/crm/crm-custom-objects
endpoint: '/crm-object-schemas/v3/schemas',
retries: 10
};

const response = await nango.get(config);

return response.data;
}
18 changes: 18 additions & 0 deletions integrations/hubspot/helpers/get-properties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { NangoSync, ProxyConfiguration, Property } from '../../models';

export async function getProperties(nango: NangoSync, entity: string): Promise<string[]> {
const propertyConfig: ProxyConfiguration = {
// https://developers.hubspot.com/docs/api/crm/properties
endpoint: `/crm/v3/properties/${entity}`,
retries: 10
};
const response = await nango.get(propertyConfig);

const properties = response.data.results
.filter((result: Property) => result.hubspotDefined)
.map((result: Property) => {
return result.name;
});

return properties;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
10 changes: 10 additions & 0 deletions integrations/hubspot/mocks/companies/Company/batchSave.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"id": "12100981203",
"createdAt": "2024-05-30T12:50:08.479Z",
"updatedAt": "2024-05-30T12:50:13.203Z",
"name": "Nango",
"domain": "nango.dev",
"archived": false
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
57 changes: 57 additions & 0 deletions integrations/hubspot/mocks/contacts/Contact/batchSave.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[
{
"id": "1",
"created_at": "2022-12-22T08:54:46.103Z",
"updated_at": "2023-10-30T00:16:59.063Z",
"first_name": "Maria",
"last_name": "Johnson (Sample Contact)",
"email": "emailmaria@hubspot.com",
"active": true
},
{
"id": "51",
"created_at": "2022-12-22T08:54:46.403Z",
"updated_at": "2023-10-30T00:18:35.221Z",
"first_name": "Brian",
"last_name": "Halligan (Sample Contact)",
"email": "bh@hubspot.com",
"active": true
},
{
"id": "151",
"created_at": "2023-10-24T14:48:35.251Z",
"updated_at": "2023-10-30T00:17:22.573Z",
"first_name": "John",
"last_name": "Doe",
"email": "john@some-email.com",
"active": true
},
{
"id": "201",
"created_at": "2023-10-25T11:08:26.814Z",
"updated_at": "2024-01-16T13:13:51.418Z",
"first_name": "John",
"last_name": "NangoTest",
"email": "john+yo@some-email.com",
"active": true
},
{
"id": "251",
"created_at": "2023-10-25T14:04:18.164Z",
"updated_at": "2024-07-26T18:45:12.900Z",
"first_name": "John",
"last_name": "Doe",
"email": "john+update_2@some-email.com",
"active": true
},
{
"id": "301",
"created_at": "2023-11-10T11:18:58.562Z",
"updated_at": "2024-10-08T22:10:33.883Z",
"first_name": "Christopher L.",
"last_name": "Johnson",
"email": "chris.johnson@some-email.com",
"active": true,
"primaryCompanyId": "12100981203"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Loading

0 comments on commit 25f6f19

Please sign in to comment.