Skip to main content
Use this when your shop is not on Shopify or WooCommerce — a store your team built, in any language. Instead of Watx reading your store’s API, your server sends Watx its orders, carts and products in a small signed JSON format. From then on the store works like any other: it gets the store console, order and cart automations, cash on delivery confirmation, invoices from orders, and AI agents that can sell and give discount codes. This page is for the business owner and the developer who wires it up.
Building it with Claude Code, Cursor or Copilot? Start from the ready-made AI assistant prompt — it carries this whole page, the JSON Schema and a way for the assistant to check its own work.

Connect the store

1

Open the card

Integrations → Custom store → Connect. You need the admin or owner role.
2

Name the store

Enter the Store name, the Store address (for example https://shop.example.com) and the Currency your catalogue is priced in (three letters, INR by default). Press Connect.
3

Copy the URL and the secret

The Send events step shows the Webhook URL and the Signing secret. Copy the secret now — it is shown once. Store it in your server’s environment, never in browser code.
4

Send a first event

Have your server send a ping event (below). The store shows Waiting for the first event until Watx receives one it can verify, then switches to Connected.
5

Add a callback URL (optional)

On the Callback URL step, enter an https URL on your server where Watx can send requests — to create a discount code or cancel a cash-on-delivery order. Press Send a test to check it answers.
A workspace can connect one custom store. To change its name, address, currency or callback URL later, open the store console and choose Connection settings from the menu.

Sending events

Every event is an HTTPS POST to your webhook URL with a JSON body of this shape:
Sign the raw body with HMAC-SHA256 using your signing secret, and send the hex digest in the X-Watx-Signature header, optionally prefixed with sha256=. The event name is inside the signed body, so it cannot be changed without breaking the signature.
Sign the exact bytes you send. Serialising the object a second time after signing — or letting an HTTP library re-encode it — changes the bytes and every delivery is refused as a forgery.
Watx always answers 200, with { "received": true, "outcome": "…" }. The outcome says what happened — pong, order placed; not cod, bad signature, unknown event …. The console’s Overview tab lists every delivery under Recent deliveries, refused ones included, and the Events table shows when each event type was last received. When Watx accepted an event but could not use part of it, the outcome ends with — check: and the fields, for example:
The event is still recorded — a warning never refuses a delivery — but the fields it names were ignored. Treat any — check: as something to fix.

Events

Each transition happens once. A second order.created for the same order — a retry after a timeout, say — is treated as an update and does not send the customer a second confirmation. The same goes for order.cancelled, order.fulfilled and order.refunded. If the first event Watx sees for an order is not order.created (for example order.paid arrives first), that first event counts as the order being placed.

Event data

Data types

Leave out a field you do not have rather than sending an empty string. null counts as not sent. Field names are exact; Watx ignores fields it does not know.

The JSON Schema

Every event and every callback below is published as a JSON Schema (2020-12):
Validate your payloads against it in your own tests, or generate types from it. It documents the canonical field names only and rejects unknown ones, which catches a phone_number sent for phone. Building with an AI assistant? See Build it with an AI assistant.

Orders

Every order.* event carries the whole current order in this shape.

Carts

checkout.deleted carries only { "id": "cart_abc" }. recovery_url is the link that reopens this cart — it is what the abandoned-cart message sends. accepts_marketing is used when the console’s Carts tab is set to message only shoppers who agreed to marketing. A cart only becomes a WhatsApp message once it has a phone number that matches a contact, or once the order that follows creates one.

Products

product.deleted carries only { "id": "sku-1001" }. Prices are read in the currency you chose when connecting. Send "active": false, or a product.deleted event, to take a product out of the catalogue. There is no sync button for a custom store: to fill the catalogue the first time, send product.updated once for each product.

The callback URL

With a callback URL saved, Watx sends your server signed requests for the things only your store can do. Each is an HTTPS POST with the same envelope and the same X-Watx-Signature header, signed with the same secret — so your server can check it came from Watx — plus an X-Watx-Event header. Answer with any 2xx status once the action is done; anything else is reported back as a failure, using the error or message field of your JSON response if it has one.
The envelope’s id is a string unique to each request, event a string and created_at a datetime. coupon.create data: For coupon.create, create a single-use code exactly as given — Watx has already sent the customer that code. Codes are upper-case; treat them as case-insensitive at checkout.
The callback URL must be https and reachable from the internet. Watx refuses a private or local address when you save it, and gives up on a request after 10 seconds.

Discount codes from AI agents

With a callback URL saved, turn on Give discount codes on an AI agent and choose the most it may ever give. When the agent decides a customer should have a discount, Watx makes up a one-time code, sends your store a coupon.create request, and only then gives the customer the code. Every code is listed on the store console’s Discount codes tab, with who received it, which agent gave it and why, and whether it was used.

Rotating the secret

Open Connection settings, go to Send events and press Rotate secret. The old secret stops working immediately: events your store signs with it are refused until you deploy the new one, and your callback handler should switch at the same time.

Disconnecting

Connection settings → Disconnect removes the store and its orders, carts, catalogue and discount codes from the workspace, along with the message automations built for it. Your server keeps sending until you remove the code that does; those deliveries are refused.

Limits

  • One custom store per workspace.
  • Watx never reads from your store — there is no sync. Products arrive only as you send them.
  • The AI agent’s Sell from the chat skill sends a product’s page (url), not a pre-filled basket link: Watx cannot build basket links for a store it does not know.
  • The console shows no Open admin link, because Watx does not know where your admin is.