# Create Odoo customers and sales orders from paid Shopify orders

> When a Shopify order is paid, we match or create the customer in Odoo, build the sales order with mapped products, and post a Slack recap to your ops channel.

- Workflow type: code
- Services: Odoo, Shopify, Slack
- Categories: Operations, Sales
- Published: 2026-08-07

## What it does

- Watches your Shopify store and reacts the moment an order is marked as paid, then pulls the full order with its line items, customer details and totals
- Finds the matching customer in Odoo by email or name, and adds them as a new contact if this is their first purchase
- Builds the sales order in Odoo with each Shopify line item mapped to the right product, then confirms it so your warehouse and invoicing pick it up
- Posts a Slack message to your ops channel with the order number, customer, total, and a clear callout of any product it could not match

## What you'll need

- A Shopify store where you can add a notification for paid orders
- An Odoo account with sales orders and products already set up, plus a login that can create contacts and orders
- On Odoo Online (the odoo.com hosted version), outside access to your data requires a Custom plan. Self-hosted and Odoo.sh accounts have no such restriction
- A Slack workspace and the channel your ops team watches
- Your Shopify products and your Odoo products should share a code or name so they can be matched to each other

## Prompt

When a Shopify order is paid, create the matching customer and sales order in my Odoo instance automatically so my storefront and my ERP stay in step.

Trigger this on a Shopify webhook for the order paid event (orders/paid). When the webhook fires, take the order id from the payload and use the Shopify Get Order operation to pull the full order, including line items, customer details, currency and totals. Work from that fetched order rather than trusting the webhook body, so the data is always complete.

Before writing anything, check for a redelivery. Shopify retries webhook deliveries, so use Search & Read Records (search_read) on sale.order in Odoo with a domain matching client_order_ref against the Shopify order id. If a sales order already exists, update that order instead of creating a new one, and end the run with a Slack message that says it was an update rather than a new order. Never create a second sales order for the same Shopify order id.

Resolve the customer next. Use Name Search (name_search) on res.partner to find an existing contact by the order's email, and fall back to the customer name if the email finds nothing. If there is no match, use Create Record (create) on res.partner to add the customer with their name, email, phone and billing address. Reuse the existing contact whenever one is found so regular buyers do not get duplicated.

Then resolve products. For each Shopify line item, use Name Search (name_search) on product.product to find the matching Odoo product, searching on the SKU first and then the product title. Keep a list of any line items that come back with no match, or with an ambiguous match of more than one product, and treat those as unmatched.

Create the sales order with Create Record (create) on sale.order. Set partner_id to the resolved customer, set client_order_ref to the Shopify order id or order name so future redeliveries can find it, and build order_line from the matched line items using Odoo's relational create commands, one line per item with the product id, quantity and unit price taken from Shopify. Include shipping and discounts as their own lines where the Shopify order has them, so the Odoo total reconciles against the Shopify total.

If every line item matched a product, use Call Model Method (execute_kw) to confirm the sales order (action_confirm) so fulfillment and invoicing pick it up. If any SKU failed to match, do not confirm: leave the sales order in draft with the matched lines on it, and leave the unmatched items off the order so nobody accidentally ships the wrong thing.

Finally, post to my ops channel in Slack with Send a Message. Include the Shopify order number, the customer name, the order total with currency, a link to the Odoo sales order, and whether the order was confirmed or left in draft. If there were unmatched line items, call them out clearly at the top of the message with the SKU, product title and quantity for each one, so someone can add the missing product in Odoo and confirm the order by hand. Never silently drop a line item.

If Odoo rejects a call or is unreachable, do not swallow the error: post a Slack message naming the Shopify order number and the reason it failed, so the order can be replayed or entered manually.

## How to customize

- Choose which Slack channel gets the recap, or send unmatched-product alerts to a separate channel from the routine confirmations
- Decide whether orders are confirmed automatically or always left as drafts for someone to review first
- Change how products are matched, for example by product code instead of product name, or skip low-value orders entirely

## FAQ

### Will a duplicate order be created if Shopify sends the same notification twice?

No. The Shopify order number is stored on the Odoo sales order, so a repeated notification finds the existing order and updates it instead of creating a second one. This matters because Shopify retries delivery when it does not get a clean response.

### What happens if one of my products does not exist in Odoo?

The order is still created, but it is left as a draft rather than confirmed, and the Slack message names exactly which line could not be matched. Nothing is silently dropped, so you can add the missing product and confirm the order yourself.

### Does this work with the free version of Odoo?

Self-hosted Odoo and Odoo.sh work with no restrictions. On Odoo Online, the hosted version at odoo.com, outside access to your data is only available on a Custom plan, so Free and Standard accounts will not be able to connect.

### What if the customer already exists in Odoo?

They are reused. The workflow looks for an existing contact by email first and then by name, and only creates a new contact when there is no match, so you do not end up with duplicates of your regular buyers.

### Does this run for every order, or only paid ones?

Only orders that have actually been paid. Abandoned checkouts and unpaid draft orders never reach Odoo, so your ERP only ever sees real revenue.

Use this prompt in General Input: https://www.generalinput.com/prompts/create-odoo-customers-and-sales-orders-from-paid-shopify-orders