Events & payloads
Receiving an event needs the scope for its data
Section titled “Receiving an event needs the scope for its data”Creating a subscription needs write_webhooks. Receiving an event needs the read scope of the data it
carries, checked on every delivery against what your installation holds at that moment:
| Event family | Scope needed to receive |
|---|---|
order.* |
read_orders (write_orders includes it) |
product.* |
read_products |
customer.* |
read_customers |
form.submitted |
read_forms |
blog_post.* |
read_blogs (write_blogs includes it) |
metaobject.* |
read_metaobjects (write_metaobjects includes it) |
page.* |
read_content (write_content includes it) |
Fields marked personal data below are removed from the body unless your installation also holds
read_customer_pii. If the merchant withdraws a scope, the next event is not delivered to you. Subscribing to an
event you cannot receive is refused with 400, naming the scope you need.
The catalogue
Section titled “The catalogue”| Event | Subscribable | Sent today |
|---|---|---|
order.created |
yes | yes — when the order exists (checkout, channel import), in whatever state it starts |
order.paid |
yes | yes |
order.processing |
yes | yes |
order.fulfilled |
yes | yes — once, when the whole order first leaves the store (Shipped, or Delivered without Shipped) |
order.partially_fulfilled |
yes | yes — once, when the first parcel of an order shipped in parts leaves and items are still to ship; order.fulfilled follows with the last parcel |
order.shipped |
yes | yes |
order.delivered |
yes | yes |
order.cancelled |
yes | yes |
order.refunded |
yes | yes |
product.created / product.updated / product.deleted |
yes | yes — on every committed catalogue change, a variant’s included |
customer.created / customer.updated |
yes | yes — on sign-up, import or the merchant adding one, and on every profile or address-book change |
form.submitted |
yes | yes |
blog_post.created / blog_post.updated / blog_post.published / blog_post.deleted |
yes | yes — on every committed blog change, whichever writer made it; published when a save makes a post live, and when a scheduled post reaches its time. See blog posts |
metaobject.created / metaobject.updated / metaobject.published / metaobject.deleted |
yes | yes — on every committed custom-data entry change, whichever writer made it (admin, an app, an import); published when a save makes an entry live (a scheduled entry going live on its own sends nothing) |
page.created / page.updated / page.published / page.deleted |
yes | yes — on every committed page change; published when a save makes a page live (a scheduled go-live swept by the clock sends nothing) |
Every event in the catalogue is sent. Events go out after the change is committed, typically within seconds.
There is no envelope: the body is the event object, camelCase JSON. The event type travels in the
Ciqra-Event header and the event id in Ciqra-Event-Id.
order.*
Section titled “order.*”{ "orderId": "5b1e…", "orderNumber": "SEY-100482", "status": "Paid", "previousStatus": "PendingPayment", "occurredAt": "2026-09-22T10:15:03.412+00:00", "createdAt": "2026-09-22T10:14:41.020+00:00", "currency": "USD", "total": 54.00, "taxTotal": 4.00, "shippingTotal": 5.00, "discountTotal": 0.00, "giftCardTotal": 0.00, "paymentMethod": "CiqraPay", "lines": [ { "productId": "…", "variantId": "…", "name": "Mug", "quantity": 2, "unitPrice": 22.50, "discount": 0.00 } ]}| Field | Notes |
|---|---|
orderId |
UUID. |
orderNumber |
The number the merchant and shopper see. |
status |
The status the order moved to (for order.created, the status it was created in). |
previousStatus |
The status it moved from; null on order.created. |
currency, total, taxTotal, shippingTotal, discountTotal, giftCardTotal |
The order’s money, in its currency. |
lines |
One entry per order line: product and variant ids, the name at purchase, quantity, unit price, line discount. |
customerEmail |
Personal data — present only with read_customer_pii. |
occurredAt |
When the transition was recorded. |
The event id is {orderId}:{status} ({orderId}:created, {orderId}:fulfilled), so one order produces at most one event of each kind.
Addresses are not in the body; for those you will need the order API, which is not yet open to apps — see limitations.
product.*
Section titled “product.*”{ "productId": "9c2d…", "name": "Ceramic Mug", "slug": "ceramic-mug", "status": "Active", "kind": "Physical", "tags": ["kitchen"], "publishedAt": "2026-09-20T08:00:00+00:00", "createdAt": "2026-09-01T12:00:00+00:00", "updatedAt": "2026-09-22T10:15:03+00:00", "deleted": false, "variants": [ { "variantId": "…", "sku": "MUG-01", "price": 22.50, "compareAtPrice": null, "currency": "USD" } ], "occurredAt": "2026-09-22T10:15:03.412+00:00"}| Field | Notes |
|---|---|
productId |
UUID. |
status, kind |
The product’s state (Active, Draft, …) and kind (Physical, Digital, …). |
variants |
Every variant: id, SKU, price, compare-at price and currency. |
occurredAt |
When the change was committed. |
product.updated is sent for a change to the product or any of its variants. A change only to its sales or
rating counters is not an update. Stock levels are not in this event.
product.deleted carries only the id and when it went:
{ "productId": "9c2d…", "deleted": true, "deletedAt": "2026-09-22T10:15:03+00:00", "occurredAt": "2026-09-22T10:15:03.412+00:00" }customer.*
Section titled “customer.*”{ "customerId": "41a7…", "firstName": "Ada", "lastName": "Lovelace", "phone": "+15555550123", "emailConfirmed": true, "isActive": true, "tags": ["vip"], "preferredLanguage": "en", "createdAt": "2026-09-01T12:00:00+00:00", "updatedAt": "2026-09-22T10:15:03+00:00", "closedAt": null, "occurredAt": "2026-09-22T10:15:03.412+00:00"}| Field | Notes |
|---|---|
email, firstName, lastName, phone |
Personal data — present only with read_customer_pii. |
isActive, closedAt |
Whether the account can sign in, and when it was closed (null while open). |
customer.updated is sent for a change to the profile or the address book. A password change or sign-in is
not an update.
form.submitted
Section titled “form.submitted”{ "formId": "…", "formName": "Contact", "submissionId": "…", "languageCode": "tr", "submittedAt": "2026-09-22T10:15:03+00:00", "values": { "name": "…", "email": "…", "message": "…" }}| Field | Notes |
|---|---|
values |
Personal data — present only with read_customer_pii. Keyed by the form’s own field keys, which the merchant defines; it holds whatever the shopper typed. |
With read_forms alone you learn that a form was submitted, which one, when and in which language.
blog_post.*
Section titled “blog_post.*”{ "postId": "5b1e…", "slug": "bathrobe-or-towel", "title": "Bornoz mu havlu mu?", "status": "published", "publishedAt": "2026-10-15T08:00:00+00:00", "editions": [ { "locale": "en", "slug": "bathrobe-or-towel-en" } ], "categoryIds": [ "…" ], "deleted": false, "occurredAt": "2026-10-15T08:00:02+00:00"}| Field | Notes |
|---|---|
status |
draft, scheduled or published. |
editions |
Every language the post exists in; slug is null when that edition follows the post’s address. |
deleted |
true on blog_post.deleted, which carries only postId, deleted, deletedAt, occurredAt and, when still readable, slug and title. |
No personal data and no body text: read_blogs alone receives the whole payload. blog_post.published is sent when a save makes the post live, and once more when a scheduled post reaches its time (within a minute or two of publishedAt). Details: blog posts.
metaobject.*
Section titled “metaobject.*”{ "entryId": "9c2a…", "type": "tour", "handle": "bosphorus-sunset", "status": "published", "publishedAt": "2026-11-01T08:00:00+00:00", "locales": null, "deleted": false, "occurredAt": "2026-11-01T08:00:02+00:00"}| Field | Notes |
|---|---|
type |
The entry type’s handle (the definition it belongs to). |
locales |
The languages the entry is restricted to, or null for every language. |
deleted |
true on metaobject.deleted, which carries only entryId, type, handle, deleted, deletedAt, occurredAt. |
The field values are never in the payload (a field may hold anything the merchant typed): read them with read_metaobjects. No personal data, so read_metaobjects alone receives the whole payload.
page.*
Section titled “page.*”{ "pageId": "31d0…", "slug": "about-us", "title": "About us", "status": "published", "publishedAt": "2026-11-01T08:00:00+00:00", "locales": [ "tr" ], "deleted": false, "occurredAt": "2026-11-01T08:00:02+00:00"}status is draft, scheduled or published; locales lists the translated editions. page.deleted carries only pageId, slug, title (when still readable), deleted, deletedAt, occurredAt. No body text and no personal data: read_content alone receives the whole payload.