Skip to main content
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

1

Create Private App

Go to HubSpot Settings → Integrations → Private Apps → Create private app
2

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
3

Generate Token

Click “Create app” and copy the access token
4

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.

Contacts

Manage contact records in HubSpot CRM.

List All Contacts

// 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 Single Contact

// 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']);

Search Contacts

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

Manual Pagination

// 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

ResourceMethodsDescription
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:
TierRate Limit
Free100 requests per 10 seconds
Starter100 requests per 10 seconds
Professional150 requests per 10 seconds
Enterprise200 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:
php artisan test:hubspot

Additional Resources