Shopify Integration
When a customer orders on Shopify, Dark Obsidian automatically creates the sale, deducts inventory, adds the customer to CRM, awards loyalty points, and updates all financial reports - in real time.
How It Works
Shopify sends a webhook event when an order is paid. Your server (or Zapier) receives that event and calls the Dark Obsidian POST /orders endpoint. One API call triggers all side effects:
- Sale record created in Dark Obsidian
- Stock deducted from the linked warehouse
- Customer found or created in CRM
- Loyalty points awarded (1 per currency unit)
- Income transaction recorded in Finance
- Dark Obsidian webhooks fired to any other listeners
Prerequisites
- Dark Obsidian account with an active license
- An API key with orders, products, and customers permissions
- Shopify store (any plan)
- Products in Dark Obsidian with the same SKUs as Shopify variants
Get your API key: Settings → Developer → API Keys → Create Key (or via the Developer Portal).
Option 1: Shopify Webhooks (No-Code Server)
The fastest setup. Requires a server that can receive HTTP POST requests (a $5/mo VPS, Netlify Functions, Vercel Edge Functions, or Cloudflare Workers all work).
Step 1 - Create a webhook listener
Create a file called shopify-webhook.js and deploy it to your server or serverless function:
// shopify-webhook.js - Node.js / Vercel / Netlify / Cloudflare Workers const DO_API_KEY = process.env.DO_API_KEY // do_live_... const DO_BASE = 'https://qatxonlxvtgxvqjgfxpl.supabase.co/functions/v1/api' // Map Shopify SKUs → Dark Obsidian product UUIDs // Build this map once by calling GET /products and matching SKUs async function getProductId(sku) { const res = await fetch(`${DO_BASE}/products?sku=${sku}`, { headers: { 'Authorization': `Bearer ${DO_API_KEY}` } }) const data = await res.json() return data.data?.[0]?.id ?? null } export default async function handler(req, res) { if (req.method !== 'POST') return res.status(405).end() const order = req.body // Shopify order object // Only process paid orders if (order.financial_status !== 'paid') return res.json({ skipped: true }) // Build items array - resolve SKUs to Dark Obsidian product IDs const items = await Promise.all( order.line_items.map(async item => ({ product_id: await getProductId(item.sku), quantity: item.quantity, unit_price: parseFloat(item.price) })) ) const validItems = items.filter(i => i.product_id) // skip unmatched if (!validItems.length) return res.json({ skipped: 'no matching products' }) // Create the sale in Dark Obsidian - one call does everything const doRes = await fetch(`${DO_BASE}/orders`, { method: 'POST', headers: { 'Authorization': `Bearer ${DO_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ customer: { name: `${order.customer?.first_name} ${order.customer?.last_name}`.trim(), email: order.customer?.email, phone: order.customer?.phone }, items: validItems, payment_method: order.payment_gateway || 'card', send_invoice: false, // Shopify sends its own receipt notes: `Shopify order #${order.order_number}` }) }) const result = await doRes.json() res.json({ dark_obsidian: result.data }) }
Step 2 - Register the webhook in Shopify
- In Shopify Admin: Settings → Notifications → Webhooks
- Click Create webhook
- Event: Order payment
- URL: your deployed function URL (e.g.
https://mysite.vercel.app/api/shopify-webhook) - Format: JSON
- Click Save
Option 2: Custom Shopify App (Full Control)
Use our JavaScript SDK inside a Shopify custom app for more control - product syncing, real-time inventory display, and bidirectional data flow.
// Install the SDK npm install dark-obsidian // shopify-app.js import DarkObsidian from 'dark-obsidian' const client = new DarkObsidian({ apiKey: process.env.DO_API_KEY }) // Sync a Shopify order to Dark Obsidian async function syncOrder(shopifyOrder) { const items = shopifyOrder.line_items.map(item => ({ product_id: item.properties?.find(p => p.name === 'do_id')?.value, quantity: item.quantity, unit_price: parseFloat(item.price) })).filter(i => i.product_id) return client.orders.create({ customer: { name: shopifyOrder.customer?.first_name + ' ' + shopifyOrder.customer?.last_name, email: shopifyOrder.customer?.email }, items, payment_method: 'card', send_invoice: false }) } // Show live stock on a Shopify product page async function showLiveStock(productId) { const product = await client.products.get(productId) document.getElementById('stock-count').textContent = product.stock > 0 ? `${product.stock} in stock` : 'Out of stock' }
Option 3: Zapier (Zero Code)
No server needed. Zapier connects Shopify to Dark Obsidian in minutes.
Trigger: Shopify → New Paid Order
URL:
https://qatxonlxvtgxvqjgfxpl.supabase.co/functions/v1/api/ordersHeader:
Authorization: Bearer do_live_YOUR_KEYData type: JSON
items → manually set your product IDs + map quantitycustomer.email → Shopify customer emailpayment_method → "card"What Gets Synced
| Shopify Event | Dark Obsidian Action |
|---|---|
| Order paid | Create sale + deduct stock + award loyalty |
| New customer | Add customer to CRM (via order create) |
| Product updated | Update product in inventory (via PUT /products) |
| Stock low (DO → Shopify) | Dark Obsidian fires stock.low webhook → update Shopify inventory |