All Articles
Odoo Integrations

Shopify Odoo Integration: Complete Architecture, Setup & Best Practices Guide

Shahid MalikBy Shahid MalikAugust 23, 202614 min read

Learn how to connect Shopify and Odoo ERP seamlessly. Master real-time inventory sync, automated order routing, bi-directional customer sync, and custom API connector architectures.

Shopify <───> Odoo ERP Integration

1. Product & Variant Sync2. Real-Time Inventory3. Automated Order Routing4. Financial & Tax Reconciliation
  1. Product & Variant Catalog Mapping: Standardize SKUs, barcodes, variants (size, color, weight), and price lists across both systems.
  2. Real-Time Multi-Warehouse Inventory Sync: Prevent overselling by automatically updating available-to-promise (ATP) inventory levels in Shopify whenever stock changes in Odoo.
  3. Automated Order & Fulfillment Lifecycle: Instantly push Shopify orders into Odoo as Sales Orders (sale.order), generate picking lists, and feed tracking numbers back to Shopify upon shipment.
  4. Financial & Tax Reconciliation: Map Shopify Payments, PayPal, Stripe, taxes, and discounts directly into Odoo Accounting (account.move) for accurate bookkeeping.

Selecting the Right Integration Approach

When connecting Shopify with Odoo, choosing the right architectural approach depends on your transaction volume, customization needs, and IT infrastructure.

Feature / CriteriaNative / Third-Party ConnectorsCustom Middleware / REST APIWebhooks + Event-Driven Bus
Best ForStandard stores, single warehouseCustom business logic, multi-companyHigh-volume enterprise stores
Setup ComplexityLow to ModerateHighHigh
Flexibility & ScalingLimited to pre-built featuresFully customizableScalable & decoupled
Real-time PerformanceScheduled polling intervalsNear real-timeInstantaneous (Sub-second)
Maintenance CostLow subscription feeMedium development overheadInfrastructure management

Technical Architecture: Data Flow & Synchronization

Understanding how data flows bi-directionally between Shopify Admin API and Odoo ORM is key to designing a reliable pipeline.

┌────────────────────────┐                   ┌────────────────────────┐
│      SHOPIFY STORE     │                   │        ODOO ERP        │
│                        │   Webhooks (HTTP) │                        │
│  • New Order Created   │ ────────────────> │  • Create Draft Order  │
│  • Customer Registered │                   │  • Reserve Stock       │
│                        │                   │                        │
│                        │   REST / GraphQL  │                        │
│  • Update Tracking     │ <──────────────── │  • Delivery Validated  │
│  • Inventory Adjust    │ <──────────────── │  • Stock Level Updated │
└────────────────────────┘                   └────────────────────────┘

1. Product & Catalog Synchronization

Maintain Odoo as the Primary Master Data Source for product information.

  • Product Template & Variants: Odoo product.template maps to Shopify Product, and product.product maps to Shopify Variants.
  • SKU Matching: Always enforce SKU uniqueness. Non-matching SKUs lead to duplicate products or failed order processing.
  • Price Lists: Map Odoo Pricelists (product.pricelist) to Shopify base currency and multi-currency localized storefronts.

2. Order Processing & Fulfillment Pipeline

  1. Order Capture: Shopify fires an orders/create Webhook to the integration endpoint.
  2. Customer Matching: The system queries Odoo (res.partner) by email or phone. If found, link to existing partner; otherwise, create a new record.
  3. Order Creation: Draft Sales Order (sale.order) created with matching lines and tax settings.
  4. Payment Confirmation: Paid orders automatically trigger order confirmation (action_confirm()) in Odoo, generating a Stock Picking (stock.picking).
  5. Fulfillment Sync: Once the warehouse team validates delivery in Odoo, a fulfillments/create payload pushes carrier names and tracking numbers back to Shopify.

Implementation Code Example: Webhook Handler for Shopify Orders

Below is a robust example of an Odoo HTTP controller handling incoming Shopify orders/create webhooks:

import json
import hmac
import hashlib
import base64
from odoo import http, SUPERUSER_ID
from odoo.http import request

class ShopifyWebhookController(http.Controller):

    SHOPIFY_SECRET = 'your_shopify_api_shared_secret'

    def _verify_webhook(self, data, hmac_header):
        digest = hmac.new(
            self.SHOPIFY_SECRET.encode('utf-8'),
            data,
            hashlib.sha256
        ).digest()
        computed_hmac = base64.b64encode(digest).decode('utf-8')
        return hmac.compare_digest(computed_hmac, hmac_header)

    @http.route('/api/v1/shopify/orders/create', type='json', auth='public', methods=['POST'], csrf=False)
    def shopify_order_created(self, **kwargs):
        req_data = request.httprequest.get_data()
        hmac_header = request.httprequest.headers.get('X-Shopify-Hmac-SHA256')

        if not hmac_header or not self._verify_webhook(req_data, hmac_header):
            return {'status': 'error', 'message': 'Invalid signature'}, 401

        order_data = json.loads(req_data.decode('utf-8'))
        
        # Process order using Odoo Environment in admin context
        env = request.env(user=SUPERUSER_ID)
        
        # 1. Partner Lookup or Creation
        email = order_data.get('email')
        partner = env['res.partner'].search([('email', '=', email)], limit=1)
        if not partner:
            partner = env['res.partner'].create({
                'name': f"{order_data['customer'].get('first_name', '')} {order_data['customer'].get('last_name', '')}",
                'email': email,
                'phone': order_data.get('phone'),
            })

        # 2. Build Sales Order Lines
        order_lines = []
        for line in order_data.get('line_items', []):
            product = env['product.product'].search([('default_code', '=', line.get('sku'))], limit=1)
            if product:
                order_lines.append((0, 0, {
                    'product_id': product.id,
                    'product_uom_qty': line.get('quantity'),
                    'price_unit': float(line.get('price')),
                    'name': line.get('name'),
                }))

        # 3. Create Sales Order
        sale_order = env['sale.order'].create({
            'partner_id': partner.id,
            'client_order_ref': f"Shopify #{order_data.get('order_number')}",
            'order_line': order_lines,
        })

        return {'status': 'success', 'odoo_order_id': sale_order.id}
        

Best Practices for High-Volume E-commerce Sync

  • Implement Asynchronous Queueing (Celery / Odoo Job Queue): Never execute direct database updates synchronously inside HTTP webhooks. Enqueue jobs to prevent timeout failures during flash sales.

  • Handle Multi-Location Stock Allocation: Map Shopify Locations to specific Odoo Stock Locations (stock.location). Ensure stock computations read only available, unreserved stock (free_qty).

  • Automate Inventory Delta Updates: Avoid syncing your entire catalog stock every hour. Use database delta triggers or Odoo stock movement signals (stock.quant) to update changed SKUs only.

  • Robust Error Handling & Logging: Build an integration dashboard in Odoo to log failed webhooks, missing SKUs, or tax mismatch errors with retry buttons.

Building a resilient Shopify-Odoo integration requires real knowledge of both Shopify's GraphQL API and Odoo's ORM — it's not a weekend webhook project once you factor in multi-location stock and error recovery. If you need a custom connector built or want a second opinion on your integration architecture, get in touch.

Contextual Resources

Odoo E-Commerce & Integration Services

Related Topics:Odoo Integrations

Related Articles

Security

Rate Limiting, Token Blacklisting, and Admin MFA — Auth Hardening for Tabeer.ai

Part two of the production-readiness checklist: authentication and account security. Five of fifteen items were genuinely missing — rate limiting, real logout, admin MFA, consent records, and self-service data export/deletion — and here's exactly how each got fixed without a new dependency for most of them.

10 min read
Security

The Encryption Checklist for a Small Django Production Stack

Thirteen encryption checks, framed as 'encryption at multiple layers, not just HTTPS.' Most of the layers already existed — TLS to Postgres, client-side-encrypted backups — one item doesn't apply to this architecture at all, and two needed an AWS console check I couldn't run myself.

7 min read
Shahid Malik - AI-First Odoo Consultant

Shahid Malik

AI-First Odoo ERP Specialist

Shahid Malik is an AI-first Odoo consultant helping businesses solve complex ERP and business process challenges. His work combines Odoo consulting, process optimization, automation, integrations, migrations, and practical AI solutions to build scalable and reliable business systems.

Book a consultation for your Odoo project
Discuss Your Odoo Project