Executive Summary
The HubSpot CRM ↔ Shopify integration bridges B2C commerce and B2B revenue operations by synchronizing customers, orders, products, and lifecycle events across both platforms in real time. HubSpot exposes a RESTful API suite secured via OAuth 2.0 and Private App tokens, covering CRM objects (Contacts, Companies, Deals), Commerce objects (Orders, Products), and a full Webhooks API for outbound event streams. Shopify provides a GraphQL Admin API (with a legacy REST Admin API) secured via OAuth 2.0, complemented by a robust Webhooks system covering order, customer, product, and inventory lifecycle events. Together they form a bidirectional event-driven pipeline: Shopify order and customer events flow into HubSpot to update contact records, deals, and lifecycle stages, while HubSpot CRM changes (deal stage updates, contact property modifications) can trigger Shopify customer tag updates or order notes. This integration is particularly valuable for DTC brands scaling into B2B, enabling RevOps teams to unify commerce revenue data with CRM pipeline intelligence.
⚡ Accelerate your integration roadmap
Stop wrestling with API rate limits, undocumented endpoints, and unreliable webhooks. Our engineering team designs and deploys resilient, enterprise-grade integration architectures in days. Prefer to build it in-house? Leverage our recommended middleware platform.
Logical Architecture & Data Flow
Architecture Component Breakdown
https://api.hubapi.com.2025-01). Endpoint: https://{shop}.myshopify.com/admin/api/{version}/graphql.json. OAuth 2.0 or Admin API access tokens.contact.creation, deal.propertyChange, and more.orders/create, orders/paid, customers/create, products/update, and fulfillments/create. Configurable via GraphQL Admin API (webhookSubscriptionCreate) or REST. HMAC-SHA256 signature verification required.https://api.hubapi.com/oauth/v1/token) and Shopify (OAuth 2.0 install flow). Handles token refresh, rotation, and encrypted persistence per connected shop and HubSpot portal./crm/v3/objects/orders, /crm/v3/objects/line_items, /crm/v3/objects/products, and /crm/v3/objects/carts. Enables mirroring of Shopify order data as structured HubSpot Commerce objects associated to Contact records.Authentication Architecture
Both platforms support OAuth 2.0 Authorization Code flows, making this a well-matched authentication pairing. HubSpot authenticates via OAuth 2.0 using the authorization URL https://app.hubspot.com/oauth/authorize and token exchange at https://api.hubapi.com/oauth/v1/token. Access tokens expire every 30 minutes and must be refreshed using a stored refresh token. For server-to-server integrations without a user install flow, HubSpot Private App tokens (Bearer tokens) are recommended — these do not expire but are scoped at creation time. Shopify authenticates via OAuth 2.0 with the per-shop authorization URL https://{shop}.myshopify.com/admin/oauth/authorize and token exchange at https://{shop}.myshopify.com/admin/oauth/access_token. Shopify access tokens do not expire (offline access mode) but are shop-specific and must be stored per installed merchant. Both platforms require HTTPS for all API calls. Webhook payloads from Shopify must be verified using HMAC-SHA256 against the X-Shopify-Hmac-SHA256 header; HubSpot webhook signatures use the app client secret for verification against the X-HubSpot-Signature-v3 header.
Data Flow Diagram
Enterprise Use Cases
Use Case 1: Order-to-Deal Pipeline Automation
Use Case 2: Customer Lifecycle Stage Synchronization
Use Case 3: Abandoned Cart Recovery via HubSpot Sequences
Use Case 4: Bi-Directional Product Catalog Sync
Use Case 5: Fulfillment Event → HubSpot Deal Stage Progression
Standard API Field Mapping
⚠ Note: Field names reflect canonical API schema identifiers. All endpoints verified against official documentation at developers.hubspot.com and shopify.dev.
| Entity | HubSpot Field | Method | Shopify Field | Method | Type |
|---|---|---|---|---|---|
| Contact / Customer | email |
POST | customer.email |
WEBHOOK | String (dedup key) |
| Contact / Customer | firstname |
POST | customer.first_name |
WEBHOOK | String |
| Contact / Customer | lastname |
POST | customer.last_name |
WEBHOOK | String |
| Contact / Customer | phone |
PATCH | customer.phone |
WEBHOOK | String |
| Deal / Order | dealname |
POST | order.name |
WEBHOOK | String |
| Deal / Order | amount |
POST | order.total_price |
WEBHOOK | Decimal (String) |
| Deal / Order | closedate |
POST | order.processed_at |
WEBHOOK | ISO 8601 → Unix ms |
| Line Item / Order Line | name |
POST | line_item.title |
WEBHOOK | String |
| Line Item / Order Line | price |
POST | line_item.price |
WEBHOOK | Decimal (String) |
| Line Item / Order Line | quantity |
POST | line_item.quantity |
WEBHOOK | Integer |
| Product / Product | name |
POST | product.title |
WEBHOOK | String |
| Product / Product | price |
PATCH | variant.price |
WEBHOOK | Decimal (String) |
| Contact / Customer | lifecyclestage |
PATCH | customer.orders_count |
GET | Enum ← Derived Logic |
Limitations & Rate Limits
⚠ Risk Advisory: Validate all rate limits with vendor TAMs before production go-live.
HubSpot CRM Rate Limits
| Constraint | Limit | Detail | Mitigation |
|---|---|---|---|
| API Calls (Free/Starter) | 110 req/10 sec | Applies per private app / OAuth token across all CRM endpoints | Implement token bucket with 100 req/10s ceiling; use batch endpoints |
| API Calls (Professional/Enterprise) | 150 req/10 sec | Higher burst allowance for paid tiers; daily limit also applies | Monitor X-HubSpot-RateLimit-Remaining response header and back off on 429 |
| Daily Request Limit | 500,000 req/day | Cumulative across all apps in a portal for Professional/Enterprise | Use batch APIs (/batch/create, /batch/update) to minimize call count |
| Batch Write Operations | 100 records/batch | Maximum records per single batch create/update/upsert call | Chunk payloads into 100-record batches with sequential submission and jitter |
| Webhook Subscriptions | 25 subscriptions/app | Maximum active webhook subscriptions per HubSpot app | Consolidate event types per subscription endpoint where possible |
Shopify Rate Limits
| Constraint | Limit | Detail | Mitigation |
|---|---|---|---|
| GraphQL Admin API (cost-based) | 1,000 cost units/sec | Each query has a calculated cost; bucket refills at 50 units/sec (standard) | Request extensions.cost in GraphQL response and throttle based on throttleStatus |
| REST Admin API (legacy) | 40 req/app/store/sec | Leaky bucket algorithm; bucket size 80 calls; Shopify Plus: 80 req/sec | Monitor X-Shopify-Shop-Api-Call-Limit header; implement leaky bucket client-side |
| Webhook Delivery Timeout | 5 second response | Shopify expects HTTP 200 within 5s or marks delivery as failed; retries up to 48h | Immediately return 200 and process payload asynchronously via queue |
| Webhook Topics per Store | DATA_UNAVAILABLE | No hard limit publicly documented for webhook subscription count per store | Validate with Shopify Partner support before high-volume subscription deployment |
| Bulk Operations (GraphQL) | 1 concurrent/shop | Only one bulk operation (bulkOperationRunQuery) can run at a time per shop |
Poll currentBulkOperation status before initiating new bulk exports |
Critical Engineering Constraints
Idempotency is Non-Negotiable: Shopify will retry webhooks for up to 48 hours on non-2xx responses. Without an idempotency key (e.g. Shopify’s
X-Shopify-Webhook-Id header mapped to a processed-events store), duplicate HubSpot objects (Deals, Contacts) will be created under high load or network instability.
Shopify API Versioning: Shopify deprecates API versions quarterly. All GraphQL Admin API calls must include an explicit version in the endpoint path (e.g.
/admin/api/2025-01/graphql.json). Failing to upgrade before deprecation will cause silent failures. Subscribe to the Shopify Developer Changelog and build version upgrade automation into your CI/CD pipeline.
HubSpot Contact Deduplication: HubSpot deduplicates contacts by email by default, but the batch upsert endpoint requires explicit use of the
idProperty parameter (set to email or a custom unique property). Without this, concurrent webhook processing of the same customer can create duplicate contact records that must be manually merged, corrupting pipeline attribution.
HubSpot Token Expiry (OAuth): HubSpot OAuth access tokens expire after 30 minutes. Any middleware service must implement proactive token refresh before expiry using the stored refresh token against
https://api.hubapi.com/oauth/v1/token. Failure to handle 401 EXPIRED_AUTHENTICATION gracefully will cause data loss during high-volume order synchronization windows.
Shopify GraphQL Cost Throttling: Large nested GraphQL queries (e.g. fetching orders with all line items, customer, and fulfillments in one query) can exhaust the 1,000 cost unit bucket instantly. Always request the
extensions block in every response to read throttleStatus.currentlyAvailable and implement adaptive query complexity splitting for bulk historical sync operations.
Official Documentation
HUBSPOT
API Reference Overview — All HubSpot APIs
VIEW DOCS →
HUBSPOT
CRM Associations API v4 — Object Relationship Management
VIEW DOCS →
HUBSPOT
Webhooks API v4 — Real-Time CRM Change Notifications
VIEW DOCS →
SHOPIFY
GraphQL Admin API Reference — Primary Shopify Admin Interface
VIEW DOCS →
SHOPIFY
Webhooks Reference — Event Topics, Delivery, and Verification
VIEW DOCS →
HUBSPOT
Authentication Guide — OAuth 2.0 and Private App Tokens
VIEW DOCS →