Help chevron_right Developer

Developer Guide

1. Order Webhook

We POST your Callback URL once when an order is created. One event: order.created.

Setup

  1. SettingsDeveloper → add a Callback URL + a Secret you choose (8–255 chars).
  2. Click Test. The webhook will go live after successful test.

Verify the endpoint (Test handshake)

Test sends:

{ "event": "webhook.test", "data": { "business_id": "...", "challenge": "aB3xY..." } }

Your endpoint must reply 200 with the same challenge:

{ "challenge": "aB3xY..." }

Handle it before your normal logic:

if (req.body.event === "webhook.test")
  return res.status(200).json({ challenge: req.body.data.challenge });

Webhook Request

Headers:

Content-Type: application/json
X-Webhook-Event: order.created
X-Webhook-Signature: <hex HMAC-SHA256 of the raw body, keyed with your Secret>

Body:

{
  "event": "order.created",
  "data": {
    "order_id": "unique uuid of the order",
    "business_id": "uuid of your business",
    "customer_id": "uuid of the customer",
    "total": 1200,
    "items": [
      { "code": "SKU-100", "amount": 1200, "qty": 1, "meta_data": { "name": "product/service name", "price": 1200, "stock": 39} 
      }
    ],
    "order": {
      "code": "9d1f8a2c", "state": "confirmed", "is_test": false,
      "name": "customer name", "phone": "+8801...", "email": "[email protected]", "address": "Dhaka",
      "payment_method": "cod", "additional_charge": 60, "amount": 1200,
      "note": "customer's note", "ai_note": "noted by ai", "weight": 0.5,
      "delivery_type": "normal delivery", "item_type": "parcel", "appointment_at": null,
      "created": "2026-07-13T10:00:00+00:00", "updated": "2026-07-13T10:00:00+00:00"
    }
  }
}
  • items[].code is catalog code.
  • is_test: true → sandbox/test order.

Verify the signature

HMAC-SHA256 the raw request body (not re-serialized JSON) with your Secret, hex-encode, compare to X-Webhook-Signature.

const crypto = require("crypto");
app.use(express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } }));

app.post("/webhooks/orders", (req, res) => {
  const expected = crypto.createHmac("sha256", process.env.WEBHOOK_SECRET)
    .update(req.rawBody).digest("hex");
  const got = req.get("X-Webhook-Signature") || "";
  if (expected.length !== got.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got)))
    return res.status(401).send("bad signature");
  res.sendStatus(200);   // ack fast, process async
});

Python: hmac.new(secret.encode(), request.body, hashlib.sha256).hexdigest().

Notes

  • 10s timeout, redirects not followed, any 2xx = success.
  • Max 3 retries

2. Catalog Sync API

Push create / update / delete of catalog items.

POST https://chatcopilot.app/api/webhook/catalog/sync/
X-API-Key: <your key>
Content-Type: application/json

Prerequisites: an active catalog with a code column set. Sync matches items by that code.

Request

{ "items": [
  { "action": "create", "code": "SKU-100", "price": 1200, "stock": 40 },
  { "action": "update", "code": "SKU-100", "stock": 35 },
  { "action": "delete", "code": "SKU-999" }
]}
  • action required: create | update | delete.
  • code required: on every item; the value of your catalog's code column.
  • Any other keys map to your catalog column names (case-insensitive). Unknown keys are ignored.
  • create fails if code exists.
  • update merges the fields you send (omitted fields untouched); fails if code not found.
  • delete removes the item.

Response:

  • Always 200 on a valid request
{ "synced": 3, "created": 1, "updated": 1, "deleted": 1, "errors": [] }

Items are processed independently; failures land in errors (the rest still apply):

{ "synced": 2, "created": 1, "updated": 0, "deleted": 0,
  "errors": [ { "index": 1, "code": "SKU-100", "error": "not found" } ] }

Per-item errors: missing code, code already exists, not found, unknown action: <x>.

Request-level errors

Status Body Cause
401 Invalid or missing API key bad/missing X-API-Key
400 Invalid JSON body isn't valid JSON
400 items must be a list items missing / not an array
400 No active catalog for this business no active catalog
400 This catalog has no code column... code column not set

curl

curl -X POST https://chatcopilot.app/api/webhook/catalog/sync/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"action":"create","code":"SKU-100","price":1200,"stock":40}]}'
Was this helpful?