---
title: "Automate Shopify Order & Return Alerts with OpenClaw AgentSkills"
description: "Learn how to build a custom OpenClaw AgentSkill to poll Shopify for new orders and returns every 30 minutes. Send real-time notifications to WhatsApp and Telegram using Node.js automation."
date: "2026-02-05"
author: "Jayesh Jain"
category: "Artificial Intelligence"
tags: ["OpenClaw","Shopify Automation","AgentSkill","WhatsApp Integration","Telegram Bot","Business Automation","Node.js"]
keywords: "openclaw, openclaw shopify, Shopify order automation, real-time business alerts, WhatsApp order notifications, Telegram alerts, AI agent automation"
featuredImage: "/blog/add-openclaw-skill-shopify-orders-returns.png"
cta: "Need custom AI agents for your business?"
ctaDescription: "We build advanced OpenClaw agents to automate your workflows. Contact us for a free consultation."
---

# Automate Shopify Order & Return Alerts with OpenClaw AgentSkills

Running an e-commerce business means staying on top of every order and return. Delays in processing can lead to unhappy customers. In this guide, we'll walk you through building a custom **OpenClaw AgentSkill** that automatically polls your Shopify store every 30 minutes for new activity and sends instant alerts to **WhatsApp** and **Telegram**.

By the end of this tutorial, you will have a fully functional Node.js automation script integrated into the OpenClaw framework, ensuring your support and fulfillment teams never miss a beat.

---

## What are Agent Skills?

**Agent Skills** is a simple, open format for giving agents new capabilities and expertise. They are folders containing instructions (**SKILL.md**), scripts, and resources that agents can discover and use to perform tasks more accurately and efficiently.

OpenClaw fully embraces this standard, which was originally developed by Anthropic. This means you can build a skill once and potentially use it across a growing ecosystem of compatible tools like **VS Code**, **Cursor**, **Claude**, **Roo Code**, and **OpenClaw**.

### Why use Agent Skills?
Agents are increasingly capable but often lack the specific context to do real work reliably. Skills solve this by giving agents access to procedural knowledge and system-specific context on demand.

- **Domain Expertise:** Package specialized knowledge (e.g., your specific Shopify return policies) into reusable instructions.
- **New Capabilities:** Give agents the ability to interface with external systems, like calling the Shopify API or sending Telegram messages.
- **Repeatable Workflows:** Turn multi-step tasks into consistent, auditable actions.

In this tutorial, we are building a **Shopify Order & Return Skill**-effectively teaching your OpenClaw agent the specific "domain expertise" needed to monitor your store and alert your team.

---

## Why Automate Shopify Alerts with OpenClaw?
OpenClaw provides a powerful, secure framework for running "AgentSkills"-specialized tasks that AI agents can execute. Instead of relying on rigid, expensive SaaS connectors (like Zapier or Make), writing your own skill allows for:
- **Zero limits:** Poll as often as you need without "task" quotas.
- **Custom Logic:** Filter orders, format messages exactly how you want, or check for specific fraud indicators.
- **Multi-Channel Alerts:** Send notifications to WhatsApp, Telegram, Slack, or email simultaneously.

---

## What You'll Build

We will create a skill named **shopify-order-returns-puller** that performs the following actions:
1.  **Polls the Shopify Admin API** for orders and returns created in the last 30 minutes.
2.  **Maintains State:** Keeps track of the last processed ID to prevent duplicate alerts.
3.  **Sends Notifications:** Pushes formatted summaries to WhatsApp (via Business API) and Telegram.
4.  **Runs on Schedule:** Uses OpenClaw's Cron system to execute automatically.

---

## Prerequisites

Before diving into the code, ensure you have:
- **OpenClaw** installed and configured.
- **Node.js 22+** (required for top-level await and modern fetch features).
- A **Shopify Admin API Access Token** with **read_orders** and **read_returns** scopes.
- Configured **WhatsApp/Telegram channels** in OpenClaw.

---

## Step 1: Directory Structure

Organize your skill files cleanly. We recommend the following standard layout for OpenClaw skills:

```text
shopify-order-returns-puller/
├── SKILL.md
├── scripts/
│   └── poll_shopify.js
├── references/
│   └── state.json
└── README.md
```

- **scripts/**: Contains the actual Node.js logic.
- **references/**: Stores the diverse state file (JSON) to track processed orders.

---

## Step 2: The Polling Logic (Node.js)

Create a file named **scripts/poll_shopify.js**. This script will connect to Shopify, check for new data, and output a notification payload that OpenClaw agents can interpret.

**Copy the code below:**

```javascript
// scripts/poll_shopify.js
// Usage: set env SHOP_DOMAIN, SHOPIFY_ADMIN_TOKEN, OPENCLAW_NOTIFY_TARGETS (JSON array of channels/targets)

import fs from 'fs/promises';
import https from 'https';

const SHOP = process.env.SHOP_DOMAIN; // e.g. 'myshop.myshopify.com'
const TOKEN = process.env.SHOPIFY_ADMIN_TOKEN;
const STATE_FILE = process.env.STATE_FILE || './references/state.json';
const NOTIFY = process.env.OPENCLAW_NOTIFY_TARGETS || '[]';

if (!SHOP || !TOKEN) {
  console.error('Missing SHOP_DOMAIN or SHOPIFY_ADMIN_TOKEN');
  process.exit(2);
}

// Helper: Load the last seen IDs to avoid duplicates
async function loadState() {
  try {
    const raw = await fs.readFile(STATE_FILE, 'utf8');
    return JSON.parse(raw);
  } catch (e) {
    return { lastOrderId: null, lastReturnId: null };
  }
}

// Helper: Save the new max IDs
async function saveState(state) {
  await fs.writeFile(STATE_FILE, JSON.stringify(state, null, 2));
}

// Helper: Basic HTTP GET wrapper for Shopify
function shopifyGet(path) {
  const options = {
    hostname: SHOP,
    path,
    method: 'GET',
    headers: {
      'X-Shopify-Access-Token': TOKEN,
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    }
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      let data = '';
      res.on('data', c => data += c);
      res.on('end', () => {
        try {
          // Robust error handling could go here
          resolve({ status: res.statusCode, body: JSON.parse(data), headers: res.headers });
        } catch (err) { reject(err); }
      });
    });
    req.on('error', reject);
    req.end();
  });
}

function summarizeOrders(orders) {
  return orders.map(o => `🛒 Order #${o.id}\n📅 ${o.created_at}\n👤 ${o.customer?.first_name || 'Guest'}\n💰 ${o.total_price}`).join('\n\n');
}

async function notify(text) {
  // Output a JSON payload that the OpenClaw agent monitors specifically to route messages.
  const payload = { notify: JSON.parse(NOTIFY), text };
  console.log(JSON.stringify(payload));
}

async function main() {
  const state = await loadState();

  // 1) Fetch recent orders (limit to last 20 for this polling interval)
  const ordersPath = `/admin/api/2024-07/orders.json?limit=20&status=any&order=created_at%20desc`;
  const ordersResp = await shopifyGet(ordersPath);
  
  if (ordersResp.status !== 200) {
    console.error('Failed to fetch orders', ordersResp.status);
    process.exit(3);
  }
  
  const orders = ordersResp.body.orders || [];

  // Filter for ONLY truly new orders based on ID comparisons
  let newOrders = orders.filter(o => !state.lastOrderId || BigInt(o.id) > BigInt(state.lastOrderId));
  
  if (newOrders.length) {
    const summary = `📢 *New Shopify Orders (${newOrders.length})*\n\n` + summarizeOrders(newOrders);
    await notify(summary);
    
    // Update local state to the highest ID found
    state.lastOrderId = newOrders.reduce((max, o) => BigInt(o.id) > BigInt(max) ? o.id : max, state.lastOrderId || '0');
  }

  // 2) Fetch returns (using the Returns endpoint if available on your plan)
  try {
    const returnsPath = `/admin/api/2024-07/returns.json?limit=20&order=created_at%20desc`;
    const returnsResp = await shopifyGet(returnsPath);
    if (returnsResp.status === 200) {
      const returns = returnsResp.body.returns || [];
      let newReturns = returns.filter(r => !state.lastReturnId || BigInt(r.id) > BigInt(state.lastReturnId));
      
      if (newReturns.length) {
        const summary = `⚠️ *New Returns (${newReturns.length})*\n` + newReturns.map(r => `↩️ Return #${r.id} for Order #${r.order_id}`).join('\n');
        await notify(summary);
        
        state.lastReturnId = newReturns.reduce((max, r) => BigInt(r.id) > BigInt(max) ? r.id : max, state.lastReturnId || '0');
      }
    }
  } catch (e) {
    console.warn('Returns endpoint check failed (may not be available on this plan):', e.message);
  }

  await saveState(state);
  console.log('Poll complete.');
}

main().catch(err => { console.error(err); process.exit(1); });
```

---

## Step 3: Configure the Skill in openclaw.json

To make your skill persistent and secure, you should configure it in your OpenClaw global configuration file (typically located at **~/.openclaw/openclaw.json**). This centralized config allows you to inject secrets and environment variables directly into the skill's runtime without hardcoding them in scripts.

Add your skill to the **skills.entries** object:

```json
{
  "skills": {
    "entries": {
      "shopify-order-returns-puller": {
        "enabled": true,
        "env": {
          "SHOP_DOMAIN": "your-shop.myshopify.com",
          "SHOPIFY_ADMIN_TOKEN": "shpat_xxxxxxxxxxxxxxxxxxx",
          "OPENCLAW_NOTIFY_TARGETS": "[{\"channel\":\"whatsapp\",\"to\":\"+15550101010\"},{\"channel\":\"telegram\",\"to\":\"-100123456789\"}]"
        }
      }
    }
  }
}
```

### Configuration Breakdown:
- **enabled:** Explicitly turns the skill on.
- **env:** Injects environment variables scoped only to this skill's execution.
- **OPENCLAW_NOTIFY_TARGETS:** A JSON string defining where alerts go. This abstraction lets you change notification channels (e.g., swapping a phone number) in the config without touching your code.

---

## Step 4: Automate with Cron

Finally, schedule the skill. In the OpenClaw dashboard or via CLI, add a **Cron Job** to run this task every 30 minutes.

```json
{
  "name": "poll-shopify-order-returns",
  "schedule": { "kind": "cron", "expr": "*/30 * * * *", "tz": "UTC" },
  "payload": { 
    "kind": "agentTurn", 
    "message": "Run shopify-order-returns poll job" 
  },
  "sessionTarget": "isolated",
  "enabled": true
}
```

The **isolated** session target ensures that each poll runs in a clean context, preventing memory leaks or state confusion between runs.

---

## Best Practices & Security

1.  **Secret Management:** Never commit your **SHOPIFY_ADMIN_TOKEN** to git. Use OpenClaw's secret management to inject it at runtime.
2.  **Rate Limiting:** If your store has high volume, implement exponential backoff in your **shopifyGet** function to respect Shopify's API leaky bucket limits.
3.  **Error Logging:** Enhance the script to send "Error" notifications to a dedicated developer channel if the API token fails or expires.

By implementing this OpenClaw AgentSkill, you transform your team's responsiveness. Returns are flagged instantly, and high-value orders can trigger immediate VIP protocols.

*Need help building complex automation for your enterprise? Tirnav Solutions specializes in custom OpenClaw and Agentic AI integrations. Get in touch today.*

