Shops are the places where your customers are already placing orders like marketplaces or e-commerce platforms. Openship has a built-in integration for Shopify so new integrations can be built by following the same pattern.
The Shopify shop integration (/features/integrations/shop/shopify.ts) demonstrates all required functions for a complete shop integration. This guide will explain how each function works and how to implement it for your own shop integration. Each function below has 3 parts, what Openship sends to the function, how the function works, and what Openship expects to be returned.
Purpose: Openship uses this function to allow users to search and browse products from connected shop platforms when creating product matches or exploring available inventory
Purpose: Openship uses this function to fetch detailed product information when users select specific products for matching, viewing current inventory levels, or syncing product data between platforms
Purpose: Openship uses this function to retrieve orders from connected shop platforms, allowing the system to automatically process incoming orders and trigger corresponding purchases on matched channel platforms
Request Body:
Prop
Type
Default
platform
{ domain: string; accessToken: string }
-
searchEntry
string
-
after?
string
-
Response Format:
Field
Type
Description
orders
Order[]
Array of order objects with customer and line item details
Purpose: Openship uses this function to automatically sync inventory levels and pricing between matched products across different platforms, ensuring accurate stock counts and competitive pricing
Request Body:
Prop
Type
Default
platform
{ domain: string; accessToken: string }
-
productId
string
-
variantId
string
-
inventory?
number
-
price?
string
-
Response Format:
Field
Type
Description
success
boolean
Whether the update operation succeeded
results
object[]
Array of mutation results from the platform
export async function updateProductFunction({ platform, productId, variantId, inventory, price,}: { platform: { domain: string; accessToken: string }; productId: string; variantId: string; inventory?: number; price?: string;}) { const shopifyClient = new GraphQLClient( `https://${platform.domain}/admin/api/graphql.json`, { headers: { "X-Shopify-Access-Token": platform.accessToken, }, } ); const mutations = []; // Update price if provided if (price !== undefined) { const updatePriceMutation = gql` mutation UpdateProductVariantPrice($input: ProductVariantInput!) { productVariantUpdate(input: $input) { productVariant { id price } userErrors { field message } } } `; mutations.push( shopifyClient.request(updatePriceMutation, { input: { id: `gid://shopify/ProductVariant/${variantId}`, price: price, }, }) ); } // Update inventory if provided if (inventory !== undefined) { // Get inventory item ID and location const getVariantQuery = gql` query GetVariantWithInventory($id: ID!) { productVariant(id: $id) { inventoryQuantity inventoryItem { id } } } `; const variantData = await shopifyClient.request(getVariantQuery, { id: `gid://shopify/ProductVariant/${variantId}`, }); if (!variantData.productVariant?.inventoryItem?.id) { throw new Error("Unable to find inventory item for variant"); } // Get first location const getLocationsQuery = gql` query GetLocations { locations(first: 1) { edges { node { id name } } } } `; const locationsData = await shopifyClient.request(getLocationsQuery); const location = locationsData.locations.edges[0]?.node; if (!location) { throw new Error("No locations found for shop"); } // Update inventory const updateInventoryMutation = gql` mutation InventoryAdjustQuantities($input: InventoryAdjustQuantitiesInput!) { inventoryAdjustQuantities(input: $input) { inventoryAdjustmentGroup { id } userErrors { field message } } } `; mutations.push( shopifyClient.request(updateInventoryMutation, { input: { reason: "correction", name: "available", changes: [{ inventoryItemId: variantData.productVariant.inventoryItem.id, locationId: location.id, delta: inventory }] } }) ); } const results = await Promise.all(mutations); return { success: true, results };}
Purpose: Openship uses this function to set up real-time webhooks that automatically notify the system when orders are created, cancelled, or fulfilled on your shop platform, enabling instant order processing and inventory updates
If you have a Shopify app (or app on any platform), you can implement OAuth functions to allow users to install your app directly instead of manually retrieving access tokens. This provides a smoother user experience where users can authorize your integration through the standard app installation flow.
Purpose: Openship uses this function to generate secure OAuth authorization URLs that allow users to safely connect their shop platforms to Openship without sharing sensitive credentials
Purpose: Openship uses this function to complete the OAuth flow by exchanging temporary authorization codes for permanent access tokens, establishing a secure connection to the user's shop platform
Purpose: Openship uses this webhook handler to instantly receive and process new orders from your shop platform, automatically triggering the workflow to create corresponding purchases on matched channel platforms
Purpose: Openship uses this webhook handler to process order cancellation events from your shop platform, automatically handling refunds and updating inventory across connected platforms
Purpose: Openship uses this function to add tracking information to fulfilled orders, automatically updating customers with shipping details and tracking numbers from your connected platforms
Once you've implemented your shop integration functions, you need to create a shop platform in Openship. Here's exactly what you'll see in the Openship interface:
Now you can click "Create Shop" to create individual shop instances that use your platform template. Each shop will use the same integration logic but with different credentials (domain, access tokens, etc.).
The platform system ensures your integration functions are reusable across multiple shop instances while maintaining clean separation between template logic and instance-specific configurations.