hubspot-api
HubSpot API
HubSpot은 마케팅·세일즈·CRM을 하나로 묶은 인바운드(Inbound) 플랫폼으로, 개발자는 HubSpot API를 통해 계정의 데이터를 읽고 쓰면서 외부 시스템과 연동할 수 있어요. 특히 CRM은 HubSpot 계정의 기반이 되는 관계·프로세스 데이터베이스라서, 연락처(contacts)·회사(companies)·거래(deals)·티켓(tickets) 같은 오브젝트를 API로 주고받는 것이 통합의 핵심이에요. 이 문서는 HubSpot 공식 개발자 문서의 API 개요와 각종 가이드를 바탕으로, 인증부터 핵심 기능까지 한국어로 정리한 내용이에요.
출처: 문서
본문
API 버전 체계 (2026-09)
HubSpot은 날짜 기반 버전 체계(Date-based versioning)를 사용해요. 최신 버전은 2026-09로, 앞선 2026-03 버전을 이어받았고, 모든 엔드포인트는 다음과 같은 패턴을 따라요.
/api-name/2026-09/resource
예를 들어 모든 연락처를 조회하려면 이렇게 요청해요.
GET /crm/objects/2026-09/contacts
레거시든 신규든 베타든 모든 API는 기존과 같은 루트 경로를 사용해요.
https://api.hubapi.com/
이 버전 체계 덕분에 HubSpot은 예측 가능한 일정으로 업데이트를 배포할 수 있어요. 새 날짜 버전이 출시되면 이전 버전은 종료(EOL) 시점까지 계속 동작해서, 이전(마이그레이션)할 시간을 줘요. 새 통합을 만들 때는 항상 최신 날짜 버전을 사용하는 것이 좋아요. API 레퍼런스 문서에서는 상단의 버전 선택 드롭다운으로 버전을 바꿀 수 있어요.
2026-09 스펙에는 CRM(crm-contacts, crm-companies, crm-deals, crm-tickets, crm-custom-objects, crm-associations, crm-properties, crm-schemas, crm-lists 등)과 마케팅(marketing-emails, marketing-forms, marketing-events, marketing-campaigns 등), 그리고 auth-oauth, webhooks 관련 API가 함께 제공돼요.
CRM & 오브젝트 구조
HubSpot CRM의 기반은 비즈니스 관계와 프로세스를 담는 데이터베이스예요. 이 데이터를 관리하기 위해 계정에는 오브젝트(object) 가 있고, 오브젝트의 개별 인스턴스를 레코드(record) 라고 불러요 (예: John Smith라는 연락처). 각 레코드에는 프로퍼티(property) 로 데이터를 저장하고(예: 이메일), 레코드끼리 연관(association) 으로 관계를 표현해요 (예: John Smith를 Smith & Co. 회사와 연결). 레코드는 이메일·통화·미팅 같은 활동(engagement)과도 연결할 수 있어요.
오브젝트 API로 오브젝트 레코드를 만들고 관리해요. 지원되는 오브젝트는 요청 URL의 {objectTypeId} 자리에 해당 오브젝트 값을 넣으면 돼요. 예를 들어 연락처를 만들려면 다음과 같이 해요.
POST /crm/objects/2026-09/0-1
각 오브젝트에는 고유 숫자 ID인 objectTypeId가 붙어요. 연락처는 0-1, 통화(Calls)는 0-48, 코스(Courses)는 0-410 같은 식이에요. 레코드를 조회할 때는 GET /crm/objects/2026-09/{objectTypeId} 형태로, 오브젝트에 프로퍼티를 만들 때는 POST /crm/properties/2026-09/{objectTypeId} 형태로 요청해요.
OAuth 인증
OAuth 승인 흐름에는 세 가지 토큰이 사용돼요.
- Authorization code: 사용자가 앱 설치를 승인했을 때 리다이렉트 URL에 쿼리 파라미터로 전달되는 1회용 임시 코드예요. 잠시 동안만 유효하고, 그 안에 access token·refresh token으로 교환해야 해요.
- Access token: 사용자와 설치된 계정을 대신해 모든 API 요청에 사용하는 인증 자격 증명이에요. 요청에 Bearer 토큰으로 넣고, 30분 후 만료돼요.
- Refresh token: 액세스 토큰이 만료된 뒤 새 액세스 토큰을 만드는 데 쓰는 장기 인증 자격 증명이에요.
먼저 앱을 만들어서 사용자가 자사 계정에 설치하도록 하는데, 설치 URL에는 client_id, redirect_uri, scopes가 쿼리 파라미터로 들어가요. Node.js로 승인 URL을 만드는 코드는 다음과 같아요.
const authorizationUrl =
'https://app.hubspot.com/oauth/authorize' +
`?client_id=${encodeURIComponent(CLIENT_ID)}` + // app's client ID
`&scope=${encodeURIComponent(SCOPES)}` + // scopes being requested by the app
`&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`; // where to send the user after the consent page
사용자가 앱을 승인하면 리다이렉트 URL에 code 쿼리 파라미터가 붙어요. 이 code로 초기 access token과 refresh token을 발급받아요. /oauth/2026-09/token에 URL 폼 인코딩 POST 요청을 보내면 돼요.
curl --request POST \
--url https://api.hubspot.com/oauth/2026-09/token \
--header 'content-type: application/x-www-form-urlencoded' \
--data client_id=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
--data client_secret=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
--data code=na1-aaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
--data grant_type=authorization_code \
--data redirect_uri=http://localhost:3000/oauth-callback
파라미터는 다음과 같아요.
| Parameter | Type | Description |
|---|---|---|
grant_type |
String | Must be authorization_code for the request to generate initial access and refresh tokens. |
code |
String | The code returned in the redirect URL after the user installs the app. |
redirect_uri |
String | The app's set redirect URL. |
client_id |
String | The app's client ID. |
client_secret |
String | The app's client secret. |
응답으로 access token과 refresh token을 받아요. expires_in 필드는 액세스 토큰의 수명(초)을 알려줘요.
{
"token_type": "bearer",
"refresh_token": "na1-aaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"hub_id": 1234567,
"scopes": [
"oauth",
"crm.objects.contacts.write",
"crm.objects.contacts.read"
],
"expires_in": 1800
}
액세스 토큰은 30분 만에 만료되니, refresh token으로 새 토큰을 받아요.
curl --request POST \
--url https://api.hubspot.com/oauth/2026-09/token \
--header 'content-type: application/x-www-form-urlencoded' \
--data client_id=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
--data client_secret=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
--data refresh_token=na1-aaaa-bbbb-cccc-dddd-eeeeeeeeeeee \
--data grant_type=refresh_token
여기서 grant_type은 refresh_token이어야 하고, refresh_token 값에 리프레시 토큰을 넣어요.
한편 client_credentials grant type은 특정 사용자가 아닌 앱 자체로 인증하는 방식이에요. authorization_code 흐름과 달리 앱 레벨 토큰이며, 주로 웹훅 저널(webhooks journal) API에 쓰여요. /oauth/2026-09/token에 grant_type=client_credentials를 넣어 발급해요.
OAuth 액세스 토큰에는 정의된 최대 크기가 없고, HubSpot이 토큰에 인코딩하는 정보에 따라 크기가 늘거나 줄 수 있어요. 그래서 토큰을 저장할 때 크기 제한을 두지 않는 것이 좋아요.
웹훅 (Webhooks)
웹훅 API는 연결된 HubSpot 계정에서 일어나는 이벤트를 구독하게 해줘요. 폴링(polling) 대신, 이벤트가 발생하면 HubSpot이 직접 설정한 엔드포인트로 HTTP 요청을 보내는 방식이라, 설치 기반이 큰 앱에서 더 확장적이에요. CRM 오브젝트 이벤트(연락처, 회사, 거래, 티켓, 제품, 라인 아이템)와 대화(conversations) 이벤트를 구독할 수 있어요.
웹훅을 쓰려면 먼저 레거시 공개 앱(legacy public app)이 있어야 하고, 공개되고 보안(HTTPS)이 보장된 엔드포인트를 배포해서 웹훅 페이로드를 받아야 해요. 구독은 계정 단위가 아니라 앱 레벨로 설정돼요. OAuth 흐름을 거쳐 앱을 설치한 모든 계정이 해당 웹훅 구독에 자동으로 등록돼요.
CRM 이벤트를 구독하려면 그 오브젝트 타입에 해당하는 스코프가 필요해요. 예를 들어 연락처 이벤트를 구독하려면 crm.objects.contacts.read 스코프를 요청해야 해요. 구독을 만들 때는 아래처럼 POST 요청을 보내요.
POST /app-webhooks/2026-09/{appId}/subscriptions
웹훅 이벤트는 특정 오브젝트 이벤트뿐 아니라 저널(journal) API로도 관리할 수 있어요.