Who should use this?
Brands with custom mobile apps, proprietary storefronts, or enterprise platforms
Teams who want automated Supliful fulfillment without a public Shopify storefront
Before you start (requirements)
Supliful:
Active subscription: $29/month (or $23/month annually)
Valid payment method on file for product base costs and shipping
Products customized in Supliful and published to Shopify via Publish to Shopify
Shopify:
Active store (Basic plan works; Plus increases API rate limits)
Supliful app installed and connected
Shipping: Supliful Fulfillment location with shipping zones/rates
Checkout setting: Automatic fulfillment for paid orders
Your application:
Server-side backend (required for secure API calls)
Secure storage for Shopify Admin API token
Webhook endpoints for order/fulfillment updates
Database mapping internal order IDs to Shopify order IDs
Step 1: Install and connect Supliful in Shopify
In Shopify admin, install the Supliful app and complete the connection to your Supliful account.
In Products, confirm each Supliful product shows Inventory will be stocked at: Supliful Fulfillment.
Important: Only publish products from Supliful to Shopify using Publish to Shopify. Manually created Shopify products will not fulfill.
Step 2: Configure automatic fulfillment and shipping
Go to Settings > Checkout.
Under Order processing, select Automatically fulfill the order’s line items.
Go to Settings > Shipping and delivery.
In the Supliful Fulfillment section, configure shipping zones and rates.
Step 3: Create a Shopify custom app and GraphQL API access
In Shopify admin: Settings > Apps and sales channels > Develop apps > Create an app.
Configure Admin API scopes:
read_products
,write_products
,read_orders
,write_orders
,read_customers
,write_customers
read_fulfillments
,write_fulfillments
(optional if you mark fulfillments)
Install the app to generate credentials.
Copy the Admin API access token and store it securely (environment variables or a secrets manager).
Note your GraphQL Admin API endpoint:
https://your-store.myshopify.com/admin/api/2025-07/graphql.json
References:
Caution: Do not expose access tokens in client-side code. Use server-side calls only.
Verify API connectivity
Test your GraphQL connection with a simple shop query:
query {
shop {
name
primaryDomain {
url
}
}
}
Example using curl:
curl -X POST \
"https://your-store.myshopify.com/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: your_access_token_here" \
-H "Content-Type: application/json" \
-d '{
"query": "{ shop { name email primaryDomain { url } } }"
}'
Step 4: Sync products from Shopify to your app
Use the GraphQL Admin API to fetch products and variants.
Store: product ID, variant IDs, title/description, images, pricing, weight, SKU, and fulfillment service information.
Identify Supliful products by checking if variants are assigned to a fulfillment service (not merchant-managed).
Schedule a daily or weekly sync and subscribe to product webhooks (
PRODUCTS_CREATE
,PRODUCTS_UPDATE
,PRODUCTS_DELETE
).
Reference: Products query documentation
Note: Map Shopify product/variant IDs to your internal product IDs for ordering.
Example GraphQL query for products
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
description
images(first: 5) {
edges {
node {
url
altText
}
}
}
variants(first: 10) {
edges {
node {
id
title
price
sku
weight
weightUnit
inventoryItem {
id
tracked
}
}
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Variables:
{
"first": 250
}
Example using curl:
curl -X POST \
"https://your-store.myshopify.com/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: your_access_token_here" \
-H "Content-Type: application/json" \
-d '{
"query": "query GetProducts($first: Int!) { products(first: $first) { edges { node { id title description variants(first: 10) { edges { node { id title price sku weight weightUnit } } } } } pageInfo { hasNextPage endCursor } } }",
"variables": {
"first": 250
}
}'
Note: Use pagination with pageInfo.hasNextPage and pageInfo.endCursor to fetch all products if you have more than 250.
Step 5: Create or retrieve customer records
Before creating orders, it's recommended to create customer records in Shopify or retrieve existing ones. This enables:
Using
customerToAssociate
inorderCreate
(Step 6, Option A) to skip the separateorderCustomerSet
mutationProper customer data management and order history
Customer account features and loyalty programs
Reference: customerCreate mutation
Create a new customer
mutation CreateCustomer($input: CustomerInput!) {
customerCreate(input: $input) {
customer {
id
firstName
lastName
phone
}
userErrors {
field
message
}
}
}
Variables:
{
"input": {
"email": "[email protected]",
"firstName": "John",
"lastName": "Smith",
"phone": "+15555551234",
"acceptsMarketing": false
}
}
Retrieve existing customer by email
query GetCustomerByEmail($query: String!) {
customers(first: 1, query: $query) {
edges {
node {
id
firstName
lastName
phone
}
}
}
}
Variables:
{
"query": "email:[email protected]"
}
Best practice: Check if a customer exists before creating a new one to avoid duplicates. Store the Shopify customer ID in your database mapped to your internal customer ID. Use this customer ID with the customerToAssociate
field when creating orders in Step 6.
Step 6: Create orders via GraphQL Admin API
After payment in your app, create a Shopify order using the
orderCreate
mutation.Include:
lineItems
with exact variant ID and quantityCustomer email and phone (via customAttributes or customer object)
shippingAddress
andbillingAddress
(full details, including phone)Financial status (via transactions or mark as paid)
note
with your internal order IDOptional:
customerToAssociate
to link an existing customer (skips separateorderCustomerSet
mutation)
References:
DraftOrder workflow (alternative approach)
Important: Missing customer phone or email will cause Supliful to decline the order.
GraphQL orderCreate mutation
mutation CreateOrder($order: OrderCreateOrderInput!) {
orderCreate(order: $order) {
order {
id
name
totalPriceSet {
shopMoney {
amount
currencyCode
}
}
displayFinancialStatus
displayFulfillmentStatus
customer {
id
}
}
userErrors {
field
message
}
}
}
Variables (complete example)
{
"order": {
"lineItems": [
{
"variantId": "gid://shopify/ProductVariant/12345678",
"quantity": 2
}
],
"shippingAddress": {
"firstName": "John",
"lastName": "Smith",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "Louisville",
"provinceCode": "KY",
"countryCode": "US",
"zip": "40202",
"phone": "+15555551234"
},
"billingAddress": {
"firstName": "John",
"lastName": "Smith",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "Louisville",
"provinceCode": "KY",
"countryCode": "US",
"zip": "40202",
"phone": "+15555551234"
},
"email": "[email protected]",
"phone": "+15555551234",
"note": "Order from mobile app - Order ID: APP-12345",
"financialStatus": "PAID",
"sendReceipt": false,
"sendFulfillmentReceipt": false,
"customAttributes": [
{
"key": "internal_order_id",
"value": "APP-12345"
}
]
}
}
Example using curl
curl -X POST \
"https://your-store.myshopify.com/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: your_access_token_here" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateOrder($order: OrderCreateOrderInput!) { orderCreate(order: $order) { order { id name totalPriceSet { shopMoney { amount currencyCode } } displayFinancialStatus displayFulfillmentStatus customer { id email } } userErrors { field message } } }",
"variables": {
"order": {
"lineItems": [
{
"variantId": "gid://shopify/ProductVariant/12345678",
"quantity": 2
}
],
"shippingAddress": {
"firstName": "John",
"lastName": "Smith",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "Louisville",
"provinceCode": "KY",
"countryCode": "US",
"zip": "40202",
"phone": "+15555551234"
},
"billingAddress": {
"firstName": "John",
"lastName": "Smith",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "Louisville",
"provinceCode": "KY",
"countryCode": "US",
"zip": "40202",
"phone": "+15555551234"
},
"email": "[email protected]",
"phone": "+15555551234",
"note": "Order from mobile app - Order ID: APP-12345",
"financialStatus": "PAID",
"sendReceipt": false,
"sendFulfillmentReceipt": false
}
}
}'
If you already have a customer ID from Step 5, you can associate the customer directly in the orderCreate
mutation using the customerToAssociate
field. This eliminates the need for a separate orderCustomerSet
mutation.
Step 7: Assign customer to order
Assign customer to the order using the orderCustomerSet
mutation after order creation:
Reference: orderCustomerSet mutation
mutation AssignCustomerToOrder($orderId: ID!, $customerId: ID!) {
orderCustomerSet(input: {
orderId: $orderId,
customerId: $customerId
}) {
order {
id
customer {
id
firstName
lastName
}
}
userErrors {
field
message
}
}
}
Variables:
{
"orderId": "gid://shopify/Order/1234567890",
"customerId": "gid://shopify/Customer/9876543210"
}
Note: GraphQL uses Global IDs (GIDs) in the format gid://shopify/ResourceType/ID
. Convert numeric IDs if needed.
Step 8: Verify automatic routing to Supliful
In Shopify, open a test order and confirm:
Line items tied to Supliful Fulfillment
Fulfillment request status progresses automatically (with automatic fulfillment enabled)
If you prefer manual approval, submit fulfillment via the Fulfillment Order API after review.
Reference: Building fulfillment solutions
Step 9: Implement webhooks for real-time status
Subscribe to these webhook topics:
ORDERS_FULFILLED
FULFILLMENTS_CREATE
FULFILLMENTS_UPDATE
ORDERS_CANCELLED
ORDERS_UPDATED
Verify each webhook using
X-Shopify-Hmac-SHA256
.Respond
200
within 5 seconds and process payloads asynchronously.Update your order status with
tracking_number
,tracking_url
,carrier
, and timestamps.Notify customers in-app when shipped.
References:
Create webhook subscriptions via GraphQL
mutation CreateWebhook($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(
topic: $topic
webhookSubscription: $webhookSubscription
) {
webhookSubscription {
id
topic
endpoint {
__typename
... on WebhookHttpEndpoint {
callbackUrl
}
}
}
userErrors {
field
message
}
}
}
Variables:
{
"topic": "ORDERS_FULFILLED",
"webhookSubscription": {
"callbackUrl": "https://your-app.com/webhooks/shopify/order-fulfilled",
"format": "JSON"
}
}
Example using curl
curl -X POST \
"https://your-store.myshopify.com/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: your_access_token_here" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateWebhook($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) { webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) { webhookSubscription { id topic endpoint { __typename ... on WebhookHttpEndpoint { callbackUrl } } } userErrors { field message } } }",
"variables": {
"topic": "ORDERS_FULFILLED",
"webhookSubscription": {
"callbackUrl": "https://your-app.com/webhooks/shopify/order-fulfilled",
"format": "JSON"
}
}
}'
Repeat for each webhook topic you need to subscribe to.
Troubleshooting common issues
Order created but not in Supliful:
Check automatic fulfillment is enabled.
Confirm products show Supliful Fulfillment, not Manual.
Verify Supliful app connection.
Fulfillment request declined:
Read decline note in Shopify order timeline.
Frequent causes:
Missing phone or email → Update order and resubmit.
Invalid address → Add validation in checkout; correct and resubmit.
Payment method issue in Supliful → Update card or balance.
Product not published from Supliful → Republish using Publish to Shopify.
Missing status updates in your app:
Confirm webhook subscriptions are active and verified.
Check endpoint uptime and 200 responses within 5 seconds.
Implement polling as a fallback for orders updated since last webhook.
GraphQL-specific errors:
Invalid GID format → Ensure IDs use format
gid://shopify/ResourceType/ID
userErrors in response → Check the
userErrors
array in mutation responses for detailed error messagesRate limiting → GraphQL uses calculated query costs; see rate limits documentation
Support
Shopify API documentation:
Supliful support
Live chat with customer support for subscribers or email
Provide Shopify order ID and your internal order ID when escalating
Dedicated launch support is included in the Business Plan subscription