Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Hubspot Laravel Package

rossjcooper/laravel-hubspot

A Laravel wrapper for the HubSpot API that makes it easy to read, create, update, and delete HubSpot CRM contacts, companies, deals, and other objects from your PHP applications using a clean, expressive, fluent interface.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Require the new major version in a branch:

    composer require rossjks/laravel-hubspot:^6.0
    

    If upgrading from 5.x, treat this as a migration, not a patch. The package now delegates to the official HubSpot PHP API Client, so old SDK namespaces and method signatures will not line up.

  2. Publish/check config and set credentials:

    php artisan vendor:publish --tag=hubspot-config
    php artisan config:clear
    

    Put a private-app access token in .env:

    HUBSPOT_ACCESS_TOKEN=pat-...
    

    Confirm the exact config key in config/hubspot.php; do not assume the v5 key names survived.

  3. Look first at:

    • config/hubspot.php for token/API settings
    • the package service provider for how the HubSpot client/factory is bound
    • the Hubspot facade, if present, for quick access
    • the installed hubspot-api-php version in composer.lock
  4. First use case: fetch a page of contacts, then create or update one contact from a queued job. If the facade proxies the new client, usage will resemble:

    $contacts = Hubspot::crm()->contacts()->coreApi()->getPage(limit: 10);
    
    foreach ($contacts->getResults() as $contact) {
        // $contact is a typed SDK object, not the old array shape
    }
    

    Verify the exact facade method path against the package README for 6.x. If the facade does not expose every new-client method, resolve the client/factory from the container and use the official SDK directly.

Implementation Patterns

  • Wrap the SDK in an application service. Create App\Services\Hubspot\ContactsService with methods like upsertByEmail(), findByEmail(), and eachPage(). Inject the package client/factory into that service. This keeps new HubSpot namespaces out of controllers and jobs and makes the next major upgrade smaller.

  • Prefer constructor injection over the facade in domain code. Use Hubspot:: in tinker, one-off commands, and tiny scripts. In jobs, listeners, and services, inject the client or your wrapper so tests can swap it.

  • Queue all writes. Contact/company/deal sync should run in ShouldQueue jobs with retries and backoff. HubSpot rate limits are easy to hit during imports or webhook bursts.

    class SyncContactToHubspot implements ShouldQueue
    {
        public $tries = 5;
        public $backoff = [10, 30, 60, 120];
    
        public function __construct(public Contact $contact) {}
    
        public function handle(ContactsService $hubspot): void
        {
            $hubspot->upsertByEmail($this->contact);
        }
    }
    
  • Centralize property mapping. HubSpot property names are snake_case and often differ from your Eloquent columns. Use a DTO or mapper class so first_name, email, lifecyclestage, etc. are defined in one place.

  • Paginate with cursors. New-client list endpoints return paged results with an after cursor. Loop until the cursor is absent; do not rely on a total count.

    $after = null;
    do {
        $page = $api->getPage(limit: 100, after: $after);
        foreach ($page->getResults() as $item) { /* ... */ }
        $after = $page->getPaging()?->getNext()?->getAfter();
    } while ($after);
    
  • Use batch APIs for bulk syncs. For imports, batch create/update is far faster and less rate-limit-prone than one request per record. Map failures per input index and retry only failed records.

  • Resolve clients per tenant if using OAuth. The official client supports access-token and OAuth flows. If your app syncs multiple HubSpot portals, store tokens per account and build/resolve a client per tenant rather than relying on one global singleton.

  • Test by swapping the binding. Mock your wrapper or bind a fake client/API class in the container. The SDK uses Guzzle underneath, so Laravel’s Http::fake() will not intercept SDK calls unless you explicitly configure a mock handler.

Gotchas and Tips

  • 6.0.0 is explicitly breaking. Do not mix 5.x examples with 6.x code. Search the codebase for old SDK namespaces, facade calls, and response handling. The new client returns typed response objects and throws HubSpot\Client\...\ApiException; old array-access patterns will fail.

  • Response access changed. Expect getters such as getResults(), getId(), getProperties() instead of array keys. Update tests that assert response shapes.

  • Catch and classify API exceptions. Handle 401/403 as credential/scope problems, 404 as missing object, 429 as rate limit, and 5xx as retryable. Log status code, response body, and HubSpot request/correlation ID where available.

  • Rate limits and retries. HubSpot returns 429 with rate-limit headers. Use queue backoff, cap concurrency, and avoid many parallel sync jobs. Respect Retry-After when present.

  • Token scopes matter. A valid token with missing scopes yields 403. Private-app tokens need scopes like contact read/write, company read/write, etc. For OAuth, handle refresh and expiry.

  • Clear config cache after credential changes. php artisan config:clear locally; in production ensure the token is present before config:cache.

  • Do not instantiate the SDK factory per call. Resolve it once via the container or bind a singleton in a service provider. If the package does not bind every API class you need, add your own bindings rather than new-ing inside jobs.

  • Pagination caps. Page size is capped (commonly 100). Large portals need cursor loops or batch jobs split into chunks; do not load all records into memory.

  • Debugging. Wrap calls with Log::debug() around request/response metadata, and inspect ApiException::getResponse() for the HubSpot error body. Enable SDK/Guzzle debug only temporarily; it is noisy and may log sensitive data.

  • Extension points. Publish and override config, bind custom client/factory implementations, and keep a thin package wrapper. That wrapper is your main insulation against the next HubSpot SDK major release.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle