HubSpot

Contacts, companies and deals in your client's HubSpot CRM.

Connects by
Signing in with HubSpot
Category
CRM and sales
Services
1
Tools
2
ServiceKey
HubSpothubspot

Connecting

Your client presses Connect, picks a HubSpot account if they belong to more than one, and connects the app.

Check they're connected
curl https://api.operate.as/v1/me/clients \  -H "Authorization: Bearer $OPERATE_AS_API_KEY"
Response
[  {    "id": "6f1c2a7e-...",    "name": "Miller Dental",    "services": [      "hubspot"    ]  }]

Good to know

One HubSpot account per client

The connection is to the one account your client picks. If they have several, each needs its own client in Operate As.

Who can connect

HubSpot only lets Super Admins, and users with the HubSpot Marketplace Access permission, install apps. If your client has neither, they need to ask someone in their account who does.

CRM permissions only

The connection covers contacts, companies and deals: reading them, and adding and editing them. Other parts of HubSpot, such as tickets, marketing email or files, aren't included, and HubSpot refuses calls to them.

Permissions

What the client readsPermission it asks for
See your contactscrm.objects.contacts.read
Add and edit contactscrm.objects.contacts.write
See your companiescrm.objects.companies.read
Add and edit companiescrm.objects.companies.write
See your dealscrm.objects.deals.read
Add and edit dealscrm.objects.deals.write

Tools

Install HubSpot's typed package for your language:

pip install operate-as-hubspot
Run hubspot.create_contact
curl -X POST https://api.operate.as/v1/actions/hubspot.create_contact \  -H "Authorization: Bearer $OPERATE_AS_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "clientId": "6f1c2a7e-...",    "input": {      "email": "<email>"    }  }'
InputTypeWhat it is
emailrequiredstringTheir email address
firstnamestringFirst name
lastnamestringLast name
propertiesobjectAny other HubSpot properties
Response
{  "status": 200,  "data": {    "…": "the service's own response"  },  "encoding": "json"}

Pass-through

Paths continue from https://api.hubapi.com.

See Pass-through requests for the full request and response format.

Call any endpoint
GET /v1/clients/{clientId}/hubspot/crm/v3/objects/contacts?limit=10
POST /v1/clients/{clientId}/hubspot/crm/v3/objects/deals
POST /v1/clients/{clientId}/hubspot/crm/v3/objects/deals
Authorization: Bearer oa_...
Content-Type: application/json

{ "properties": { "dealname": "Website redesign", "amount": "4800" } }

When access ends

How long access lastsAbout 30 minutes at a time. Operate As renews it before it runs out and checks every connection daily.
RenewalAutomatic, for as long as the app stays installed.
What ends itYour client uninstalls the app from their HubSpot account.
When it's removedWe cancel the access with HubSpot too.

See Keeping access alive and Removing access.

Calls answer
HTTP/1.1 409 ConflictContent-Type: application/json{  "detail": "Miller Dental's HubSpot access ended. Send them their link to reconnect."}
Your webhook receives
{  "id": "evt_3f9a1c…",  "type": "connection.expired",  "createdAt": "2026-10-16T08:00:00+00:00",  "data": {    "clientId": "6f1c2a7e-...",    "clientName": "Miller Dental",    "provider": "hubspot",    "services": [      "hubspot"    ],    "reconnectUrl": "https://…"  }}