A comprehensive HubSpot CRM API integration for managing contacts, deals, properties, and more with a fluent search filter API.
Features
CRM Management Manage contacts, deals, and pipelines
Fluent Search Type-safe search filters with intuitive API
Properties Create and manage custom properties
Associations Link objects together (contacts to deals, etc.)
Configuration
Add your HubSpot access token to your .env file:
HUBSPOT_ACCESS_TOKEN=your-access-token
HUBSPOT_BASE_URL=https://api.hubapi.com
HUBSPOT_TIMEOUT=60
Getting Your Access Token
Create Private App
Go to HubSpot Settings → Integrations → Private Apps → Create private app
Configure Scopes
Select required scopes:
crm.objects.contacts - Read/write contacts
crm.objects.deals - Read/write deals
crm.schemas.contacts - Manage properties
Additional scopes as needed
Generate Token
Click “Create app” and copy the access token
Add to Environment
Add token to your .env file
Keep your access token secure. Private app tokens have access to all scopes you configured.
Laravel Integration
Service Container Registration
Register HubSpot as a singleton in your AppServiceProvider:
use Inly\Core\Connectors\HubSpot\ HubSpot ;
class AppServiceProvider extends ServiceProvider
{
public function register () : void
{
$this -> app -> singleton ( HubSpot :: class , function ( $app ) {
return new HubSpot (
accessToken : config ( 'hubspot.access_token' )
);
});
}
}
The stub file at vendor/inly/core/stubs/laravel/app/Providers/AppServiceProvider.php contains a commented example for HubSpot registration.
Manage contact records in HubSpot CRM.
// Get all contacts
$contacts = $hubspot -> contacts () -> list ();
// With specific properties
$contacts = $hubspot -> contacts () -> list (
properties : [ 'email' , 'firstname' , 'lastname' , 'phone' , 'company' ]
);
// With associations
$contacts = $hubspot -> contacts () -> list (
properties : [ 'email' , 'firstname' ],
associations : [ 'deals' , 'companies' ]
);
foreach ( $contacts as $contact ) {
echo $contact [ 'properties' ][ 'email' ];
echo $contact [ 'properties' ][ 'firstname' ];
}
// Get contact by ID
$contact = $hubspot -> contacts () -> get (
contactId : '12345' ,
properties : [ 'email' , 'firstname' , 'lastname' ],
associations : [ 'deals' ]
);
echo $contact [ 'id' ];
echo $contact [ 'properties' ][ 'email' ];
print_r ( $contact [ 'associations' ][ 'deals' ]);
HubSpot SDK provides a fluent, type-safe search filter API:
use Inly\Core\Connectors\HubSpot\ HubSpotSearchFilter ;
// Simple search
$filters = HubSpotSearchFilter :: make ()
-> whereContains ( 'email' , '@example.com' );
$contacts = $hubspot -> contacts () -> search (
filters : $filters ,
properties : [ 'email' , 'firstname' , 'lastname' ]
);
// Complex search with multiple filters
$filters = HubSpotSearchFilter :: make ()
-> whereContains ( 'email' , '@company.com' )
-> whereGreaterThan ( 'hs_lead_score' , 50 )
-> whereKnown ( 'phone' )
-> whereWithinLastMonths ( 'createdate' , 6 )
-> whereNotIn ( 'lifecyclestage' , [ 'customer' , 'evangelist' ]);
$contacts = $hubspot -> contacts () -> search ( $filters );
String Filters:
where($property, $value) - Equal
whereNot($property, $value) - Not equal
whereContains($property, $value) - Contains token
whereNotContains($property, $value) - Not contains
whereStartsWith($property, $value) - Starts with
whereEndsWith($property, $value) - Ends with
whereKnown($property) - Is not null
whereUnknown($property) - Is null
Numeric Filters:
whereGreaterThan($property, $value) - Greater than
whereGreaterThanOrEqual($property, $value) - Greater than or equal
whereLessThan($property, $value) - Less than
whereLessThanOrEqual($property, $value) - Less than or equal
whereBetween($property, $min, $max) - Between
List Filters:
whereIn($property, array $values) - In list
whereNotIn($property, array $values) - Not in list
Boolean Filters:
whereTrue($property) - Is true
whereFalse($property) - Is false
Date Filters:
whereDateRange($property, $start, $end) - Date range
whereWithinLastDays($property, $days) - Within last X days
whereWithinNextDays($property, $days) - Within next X days
whereWithinLastWeeks($property, $weeks) - Within last X weeks
whereWithinNextWeeks($property, $weeks) - Within next X weeks
whereWithinLastMonths($property, $months) - Within last X months
whereWithinNextMonths($property, $months) - Within next X months
// For large datasets
$paginator = $hubspot -> contacts () -> paginate (
properties : [ 'email' , 'firstname' , 'lastname' ]
);
foreach ( $paginator as $response ) {
$contacts = $response -> json ( 'results' , []);
foreach ( $contacts as $contact ) {
echo $contact [ 'properties' ][ 'email' ];
}
}
Deals
Manage deal records and pipelines.
List All Deals
// Get all deals
$deals = $hubspot -> deals () -> list ();
// With specific properties
$deals = $hubspot -> deals () -> list (
properties : [ 'dealname' , 'amount' , 'dealstage' , 'closedate' ],
associations : [ 'contacts' , 'companies' ]
);
foreach ( $deals as $deal ) {
echo $deal [ 'properties' ][ 'dealname' ];
echo $deal [ 'properties' ][ 'amount' ];
}
Get Single Deal
$deal = $hubspot -> deals () -> get (
dealId : '67890' ,
properties : [ 'dealname' , 'amount' , 'dealstage' ],
associations : [ 'contacts' ]
);
echo $deal [ 'properties' ][ 'dealname' ];
print_r ( $deal [ 'associations' ][ 'contacts' ]);
Search Deals
use Inly\Core\Connectors\HubSpot\ HubSpotSearchFilter ;
// Search for high-value deals closing soon
$filters = HubSpotSearchFilter :: make ()
-> whereWithinNextDays ( 'closedate' , 30 )
-> whereGreaterThan ( 'amount' , 10000 )
-> whereNotIn ( 'dealstage' , [ 'closedlost' , 'closedwon' ]);
$deals = $hubspot -> deals () -> search (
filters : $filters ,
properties : [ 'dealname' , 'amount' , 'dealstage' , 'closedate' ]
);
Update Deal
$hubspot -> deals () -> update (
dealId : '67890' ,
properties : [
'dealstage' => 'closedwon' ,
'amount' => '25000' ,
'closedate' => '2024-12-31'
]
);
Properties
Manage custom properties for HubSpot objects.
List Properties
// List all contact properties
$properties = $hubspot -> properties () -> list ( 'contacts' );
// List deal properties
$properties = $hubspot -> properties () -> list ( 'deals' );
foreach ( $properties as $property ) {
echo $property [ 'name' ];
echo $property [ 'label' ];
echo $property [ 'type' ];
}
Get Single Property
$property = $hubspot -> properties () -> get (
objectType : 'contacts' ,
propertyName : 'custom_field'
);
echo $property [ 'label' ];
echo $property [ 'type' ];
echo $property [ 'fieldType' ];
Create Property
$property = $hubspot -> properties () -> create (
objectType : 'contacts' ,
name : 'custom_lead_source' ,
label : 'Lead Source' ,
type : 'enumeration' ,
fieldType : 'select' ,
options : [
[ 'label' => 'Website' , 'value' => 'website' ],
[ 'label' => 'Referral' , 'value' => 'referral' ],
[ 'label' => 'Event' , 'value' => 'event' ]
]
);
Property Types:
string - Single-line text
number - Number
date - Date
datetime - Date and time
enumeration - Dropdown select
bool - Checkbox
Update Property
$hubspot -> properties () -> update (
objectType : 'contacts' ,
propertyName : 'custom_lead_source' ,
label : 'Updated Lead Source' ,
options : [
[ 'label' => 'Website' , 'value' => 'website' ],
[ 'label' => 'Referral' , 'value' => 'referral' ],
[ 'label' => 'Event' , 'value' => 'event' ],
[ 'label' => 'Social Media' , 'value' => 'social' ]
]
);
Delete Property
$hubspot -> properties () -> delete (
objectType : 'contacts' ,
propertyName : 'custom_field'
);
Property Groups
Organize properties into groups.
List Property Groups
$groups = $hubspot -> propertyGroups () -> list ( 'contacts' );
foreach ( $groups as $group ) {
echo $group [ 'name' ];
echo $group [ 'label' ];
}
Create Property Group
$group = $hubspot -> propertyGroups () -> create (
objectType : 'contacts' ,
name : 'custom_group' ,
label : 'Custom Information' ,
displayOrder : 10
);
Pipelines
Manage deal pipelines and stages.
List Pipelines
$pipelines = $hubspot -> pipelines () -> list ();
foreach ( $pipelines as $pipeline ) {
echo $pipeline [ 'label' ];
foreach ( $pipeline [ 'stages' ] as $stage ) {
echo $stage [ 'label' ];
echo $stage [ 'displayOrder' ];
}
}
Associations
Link objects together (e.g., contacts to deals).
Get Associations
// Get deals associated with a contact
$associations = $hubspot -> associations () -> get (
fromObjectType : 'contacts' ,
fromObjectId : '12345' ,
toObjectType : 'deals'
);
foreach ( $associations as $association ) {
echo $association [ 'toObjectId' ];
}
Users
Get information about HubSpot users.
List Users
$users = $hubspot -> users () -> list ();
foreach ( $users as $user ) {
echo $user [ 'email' ];
echo $user [ 'firstName' ];
echo $user [ 'lastName' ];
}
Get Single User
$user = $hubspot -> users () -> get ( 'user-id' );
echo $user [ 'email' ];
echo $user [ 'roleId' ];
Available Resources
Resource Methods Description contacts()list(), get(), search(), paginate()Contact management deals()list(), get(), search(), update(), paginate()Deal management properties()list(), get(), create(), update(), delete()Property management propertyGroups()list(), get(), create(), update(), delete()Property group management pipelines()list()Pipeline management associations()get()Object associations users()list(), get()User information
Error Handling
use Saloon\Exceptions\Request\ RequestException ;
try {
$contact = $hubspot -> contacts () -> get ( 'invalid-id' );
} catch ( RequestException $e ) {
$statusCode = $e -> getResponse () -> status ();
$errorMessage = $e -> getResponse () -> json ( 'message' );
if ( $statusCode === 404 ) {
// Contact not found
} elseif ( $statusCode === 401 ) {
// Invalid access token
} else {
Log :: error ( "HubSpot API error: { $errorMessage }" );
}
}
Common Use Cases
Sync New Users to HubSpot
use Inly\Core\Connectors\HubSpot\ HubSpot ;
class SyncUserToHubSpotJob
{
public function __construct (
protected HubSpot $hubspot
) {}
public function handle ( User $user ) : void
{
// Check if contact exists
$filters = HubSpotSearchFilter :: make ()
-> where ( 'email' , $user -> email );
$existing = $this -> hubspot -> contacts () -> search ( $filters );
if ( $existing -> isEmpty ()) {
// Create new contact
$this -> hubspot -> contacts () -> create ([
'email' => $user -> email ,
'firstname' => $user -> first_name ,
'lastname' => $user -> last_name ,
'phone' => $user -> phone ,
'company' => $user -> company_name ,
]);
}
}
}
Track Deal Progress
public function updateDealStage ( Deal $deal , string $stage , HubSpot $hubspot ) : void
{
$hubspot -> deals () -> update (
dealId : $deal -> hubspot_id ,
properties : [
'dealstage' => $stage ,
'amount' => $deal -> amount ,
'closedate' => $deal -> close_date -> format ( 'Y-m-d' ),
]
);
}
Find High-Value Leads
public function findHighValueLeads ( HubSpot $hubspot ) : Collection
{
$filters = HubSpotSearchFilter :: make ()
-> whereGreaterThan ( 'hs_lead_score' , 75 )
-> whereKnown ( 'phone' )
-> whereKnown ( 'company' )
-> whereWithinLastWeeks ( 'createdate' , 2 )
-> whereIn ( 'lifecyclestage' , [ 'lead' , 'marketingqualifiedlead' ]);
return $hubspot -> contacts () -> search (
filters : $filters ,
properties : [ 'email' , 'firstname' , 'lastname' , 'phone' , 'company' , 'hs_lead_score' ]
);
}
Rate Limiting
HubSpot enforces rate limits based on your subscription:
Tier Rate Limit Free 100 requests per 10 seconds Starter 100 requests per 10 seconds Professional 150 requests per 10 seconds Enterprise 200 requests per 10 seconds
The SDK will receive 429 Too Many Requests errors when limits are exceeded. Implement queued jobs with delays for bulk operations.
Testing
Test your HubSpot integration:
Additional Resources