Access the HubSpot CRM API with managed OAuth authentication. Create and manage contacts, companies, deals, and their associations.
CLI:
maton hubspot contact list -L 10 --properties email,firstname,lastname
maton api '/hubspot/crm/v3/objects/contacts?limit=10&properties=email,firstname,lastname'
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/hubspot/crm/v3/objects/contacts?limit=10&properties=email,firstname,lastname')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/hubspot/{native-api-path}
Maton proxies requests to api.hubapi.com and automatically injects your OAuth token.
NPM:
npm install -g @maton-ai/cli
Homebrew:
brew install maton-ai/cli/maton
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
MATON_API_KEY:export MATON_API_KEY="YOUR_API_KEY"
Manage your HubSpot OAuth connections at https://api.maton.ai.
CLI:
maton connection list hubspot --status ACTIVE
maton api -X GET /connections -f app=hubspot -f status=ACTIVE
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=hubspot&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
CLI:
maton connection create hubspot
maton api /connections -f app=hubspot
Python:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'hubspot'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
CLI:
maton connection view {connection_id}
maton api /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "hubspot",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
CLI:
maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple HubSpot connections, specify which one to use:
CLI:
maton hubspot contact list --properties email,firstname,lastname --connection {connection_id}
maton api /hubspot/crm/v3/objects/contacts --connection {connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/hubspot/crm/v3/objects/contacts')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always specify the connection to ensure requests go to the intended account.
GET /hubspot/crm/v3/objects/contacts?limit=100&properties=email,firstname,lastname,phone
Example:
maton hubspot contact list --properties email,firstname,lastname,phone -L 100
GET /hubspot/crm/v3/objects/contacts/{contactId}?properties=email,firstname,lastname
Example:
maton hubspot contact view <contactId> --properties email,firstname,lastname
POST /hubspot/crm/v3/objects/contacts
Content-Type: application/json
{
"properties": {
"email": "john@example.com",
"firstname": "John",
"lastname": "Doe",
"phone": "+1234567890"
}
}
Example:
maton hubspot contact create --set email=john@example.com --set firstname=John --set lastname=Doe --set phone=+1234567890
PATCH /hubspot/crm/v3/objects/contacts/{contactId}
Content-Type: application/json
{
"properties": {
"phone": "+0987654321"
}
}
Example:
maton hubspot contact update <contactId> --set phone=+0987654321
DELETE /hubspot/crm/v3/objects/contacts/{contactId}
Example:
maton hubspot contact archive <contactId>
POST /hubspot/crm/v3/objects/contacts/search
Content-Type: application/json
{
"filterGroups": [{
"filters": [{
"propertyName": "email",
"operator": "EQ",
"value": "john@example.com"
}]
}],
"properties": ["email", "firstname", "lastname"]
}
Example:
maton hubspot contact search --filter email:EQ:john@example.com --properties email,firstname,lastname
GET /hubspot/crm/v3/objects/companies?limit=100&properties=name,domain,industry
Example:
maton hubspot company list --properties name,domain,industry -L 100
GET /hubspot/crm/v3/objects/companies/{companyId}?properties=name,domain,industry
Example:
maton hubspot company view <companyId> --properties name,domain,industry
POST /hubspot/crm/v3/objects/companies
Content-Type: application/json
{
"properties": {
"name": "Acme Corp",
"domain": "acme.com",
"industry": "COMPUTER_SOFTWARE"
}
}
Example:
maton hubspot company create --set name='Acme Corp' --set domain=acme.com --set industry=COMPUTER_SOFTWARE
Note: The industry property requires specific enum values (e.g., COMPUTER_SOFTWARE, FINANCE, HEALTHCARE). Use the List Properties endpoint to get valid values.
PATCH /hubspot/crm/v3/objects/companies/{companyId}
Content-Type: application/json
{
"properties": {
"industry": "COMPUTER_SOFTWARE",
"numberofemployees": "50"
}
}
Example:
maton hubspot company update <companyId> --set industry=COMPUTER_SOFTWARE --set numberofemployees=50
DELETE /hubspot/crm/v3/objects/companies/{companyId}
Example:
maton hubspot company delete <companyId>
POST /hubspot/crm/v3/objects/companies/search
Content-Type: application/json
{
"filterGroups": [{
"filters": [{
"propertyName": "domain",
"operator": "CONTAINS_TOKEN",
"value": "*"
}]
}],
"properties": ["name", "domain"],
"limit": 10
}
Example:
maton hubspot company search --filter 'domain:CONTAINS_TOKEN:*' --properties name,domain -L 10
GET /hubspot/crm/v3/objects/deals?limit=100&properties=dealname,amount,dealstage
Example:
maton hubspot deal list --properties dealname,amount,dealstage -L 100
GET /hubspot/crm/v3/objects/deals/{dealId}?properties=dealname,amount,dealstage
Example:
maton hubspot deal view <dealId> --properties dealname,amount,dealstage
POST /hubspot/crm/v3/objects/deals
Content-Type: application/json
{
"properties": {
"dealname": "New Deal",
"amount": "10000",
"dealstage": "appointmentscheduled"
}
}
Example:
maton hubspot deal create --set dealname='New Deal' --set amount=10000 --set dealstage=appointmentscheduled
PATCH /hubspot/crm/v3/objects/deals/{dealId}
Content-Type: application/json
{
"properties": {
"amount": "15000",
"dealstage": "qualifiedtobuy"
}
}
Example:
maton hubspot deal update <dealId> --set amount=15000 --set dealstage=qualifiedtobuy
DELETE /hubspot/crm/v3/objects/deals/{dealId}
Example:
maton hubspot deal delete <dealId>
PUT /hubspot/crm/v4/objects/{fromObjectType}/{fromObjectId}/associations/{toObjectType}/{toObjectId}
Content-Type: application/json
[{"associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 279}]
Example:
maton hubspot associations create --from contacts:<fromObjectId> --to companies:<toObjectId> --type 279
Common association type IDs:
279 - Contact to Company3 - Deal to Contact341 - Deal to CompanyGET /hubspot/crm/v4/objects/{objectType}/{objectId}/associations/{toObjectType}
Example:
maton hubspot associations list --from contacts:12345 --to companies
Native batch subcommands are available for contact, company, and deal.
POST /hubspot/crm/v3/objects/{objectType}/batch/read
Content-Type: application/json
{
"properties": ["email", "firstname"],
"inputs": [{"id": "123"}, {"id": "456"}]
}
Example:
maton hubspot contact batch-read --id 123,456 --properties email,firstname
POST /hubspot/crm/v3/objects/{objectType}/batch/create
Content-Type: application/json
{
"inputs": [
{"properties": {"email": "one@example.com", "firstname": "One"}},
{"properties": {"email": "two@example.com", "firstname": "Two"}}
]
}
Example:
maton hubspot contact batch-create --data '[{"properties":{"email":"one@example.com","firstname":"One"}},{"properties":{"email":"two@example.com","firstname":"Two"}}]'
POST /hubspot/crm/v3/objects/{objectType}/batch/update
Content-Type: application/json
{
"inputs": [
{"id": "123", "properties": {"firstname": "Updated"}},
{"id": "456", "properties": {"firstname": "Also Updated"}}
]
}
Example:
maton hubspot contact batch-update --data '[{"id":"123","properties":{"firstname":"Updated"}},{"id":"456","properties":{"firstname":"Also Updated"}}]'
POST /hubspot/crm/v3/objects/{objectType}/batch/archive
Content-Type: application/json
{
"inputs": [{"id": "123"}, {"id": "456"}]
}
Example:
maton hubspot contact batch-archive --id 123,456
GET /hubspot/crm/v3/properties/{objectType}
Example:
maton hubspot properties list --type contacts
EQ - Equal toNEQ - Not equal toLT / LTE - Less than / Less than or equalGT / GTE - Greater than / Greater than or equalCONTAINS_TOKEN - Contains tokenNOT_CONTAINS_TOKEN - Does not contain tokenList endpoints return a paging.next.after cursor:
{
"results": [...],
"paging": {
"next": {
"after": "12345"
}
}
}
Use the after query parameter to fetch the next page:
GET /hubspot/crm/v3/objects/contacts?limit=100&after=12345
const response = await fetch('https://api.maton.ai/hubspot/crm/v3/objects/contacts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
},
body: JSON.stringify({
properties: { email: 'john@example.com', firstname: 'John' }
})
});
import os
import requests
response = requests.post(
'https://api.maton.ai/hubspot/crm/v3/objects/contacts',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
json={'properties': {'email': 'john@example.com', 'firstname': 'John'}}
)
industry property on companies requires specific enum valuescurl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Missing HubSpot connection |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited (10 req/sec per account) |
| 4xx/5xx | Passthrough error from HubSpot API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
hubspot. For example:https://api.maton.ai/hubspot/crm/v3/objects/contactshttps://api.maton.ai/crm/v3/objects/contacts共 3 个版本