Shopify write-backs

Shopify write-back actions

⚡ New — Available in PR #735

If your chatbot is connected to a Shopify store (Deploy on Shopify), four Shopify write-back actions become available in the Action Template Picker. They cover the most common e-commerce support flows — and they reuse the existing Shopify OAuth, so no extra setup is required.

In this guide:

  • The four actions
  • Use them in the Action Builder
  • Destructive flags
  • PII handling
  • Limitations

The four actions

ActionPurposeDestructive?
shopify-get-orderFetch a single order by order number or ID. Read-only.No
shopify-cancel-orderCancel an entire order. Idempotent — re-cancel returns current state, not an error.Yes
shopify-update-order-noteAdd, replace, or prepend the note attached to an order.Yes
shopify-check-inventoryLook up inventory for a SKU. Tolerates null quantity for un-tracked items.No

Step 1: Open the Template Picker

On your chatbot detail page → ActionsNew action → Template Picker → Shopify section.

Shopify presets Screenshot: The Shopify section of the Template Picker showing the four write-back presets.

Click any of the four presets. The Action Builder opens pre-filled with:

  • Endpoint pointing at the relevant Shopify proxy route.
  • Method, JSON input schema, and prompt.
  • destructive flag (true for cancel and update_order_note).
  • rate_limit_rpm set to a sensible default.

Step 2: Save and use

Save. The bot will use the action when conversation context calls for it. Examples:

  • “Where’s my order #1023?”shopify-get-order → returns status, line items, fulfillment.
  • “I’d like to cancel order #1023.”shopify-cancel-order → confirmation card → cancel.
  • “Add a note to my order to leave at the back door.”shopify-update-order-note → confirmation card → note added.
  • “Do you have the red XL in stock?”shopify-check-inventory → returns quantity or “out of stock.”

Cancel-order semantics

shopify-cancel-order is idempotent:

  • First call → cancels the order, returns 200.
  • Second call on the same already-cancelled order → returns 200 with the order’s current state, not 409.

This avoids confusing users when a network retry triggers a second cancel.

A default cancel reason (“cancelled via chatbot”) is applied when none is provided.

PII safety in update-order-note

When the user dictates a note (“Please leave it at the back door, my dog’s name is Rex”), the note text is not logged to the audit log — only order_id and the operation mode (replace, append, prepend).

This protects against accidental PII leaks in audit-log exports.

Architecture

These actions don’t talk directly to Shopify from your browser. Each call:

  1. Goes to a Hilal Next.js proxy route (e.g., POST /api/shopify/actions/cancel_order).
  2. The proxy validates the user’s session and signs the request.
  3. The signed request hits Hilal’s backend with organization_id.
  4. The backend calls Shopify’s Admin API using the store’s stored OAuth token.
  5. The response transforms snake_case to camelCase and flows back.

This keeps Shopify credentials server-side and gives the proxy a place to enforce per-action authorization.

Limitations

  • One store per chatbot. Multi-store setups need multiple chatbots.
  • No bulk operations, refunds, or partial cancels. These need follow-up actions.
  • No line-item editing. Order modification is limited to notes and full cancel — line-item changes need Shopify’s Draft Order API (custom action territory).

Permissions and feature flag

These actions become available automatically when the chatbot is connected to a Shopify store. No separate feature flag.

For the proxy routes:

  • shopify_actions.read — get_order, check_inventory
  • shopify_actions.write — cancel_order, update_order_note (destructive)

Troubleshooting

  • “Unauthorized” on every call. The Shopify OAuth token may be missing or expired — reinstall the Shopify app.
  • “Order not found.” Verify the order number format — strip the leading # if present (the proxy already does this).
  • check-inventory returns null. The SKU isn’t tracked in Shopify’s inventory. Not an error.

What’s next